1use itertools::Itertools;
9use std::io::Write;
10use std::os::unix::fs::MetadataExt;
11
12pub trait BinaryInputOutputSafe {}
13impl BinaryInputOutputSafe for i8 {}
14impl BinaryInputOutputSafe for i16 {}
15impl BinaryInputOutputSafe for i32 {}
16impl BinaryInputOutputSafe for i64 {}
17impl BinaryInputOutputSafe for u8 {}
18impl BinaryInputOutputSafe for u16 {}
19impl BinaryInputOutputSafe for u32 {}
20impl BinaryInputOutputSafe for u64 {}
21impl BinaryInputOutputSafe for f32 {}
22impl BinaryInputOutputSafe for f64 {}
23use std::io::Error;
26
27#[allow(dead_code)]
28pub fn binary_write_from_ref<T>(f: &mut std::fs::File, p: &T, n: usize) -> Result<(), Error> {
29 let raw = p as *const T as *const u8;
30 unsafe {
31 let sli: &[u8] = std::slice::from_raw_parts(raw, n * (std::mem::size_of::<T>()));
32 f.write_all(sli)?;
33 Ok(())
34 }
35}
36
37pub fn binary_read_to_ref<T>(f: &mut std::fs::File, p: &mut T, n: usize) -> Result<(), Error> {
38 let mut raw = p as *mut T as *mut u8;
39 unsafe {
40 use std::io::Read;
41 let bytes_to_read = n * std::mem::size_of::<T>();
42 let mut bytes_read = 0;
43 const MAX_TRIES: usize = 10;
46 let mut reads = Vec::<usize>::new();
47 for _ in 0..MAX_TRIES {
48 if bytes_read == bytes_to_read {
49 break;
50 }
51 raw = raw.add(bytes_read);
52 let sli: &mut [u8] = std::slice::from_raw_parts_mut(raw, bytes_to_read - bytes_read);
53 let n = f.read(sli).unwrap();
54 reads.push(n);
55 bytes_read += n;
56 }
57 if bytes_read != bytes_to_read {
58 let metadata = f.metadata()?;
59 let msg = format!(
60 "Failure in binary_read_to_ref, bytes_read = {}, but \
61 bytes_to_read = {}. Bytes read on successive\nattempts = {}.\n\
62 File has length {} and inode {}.",
63 bytes_read,
64 bytes_to_read,
65 reads.iter().format(","),
66 metadata.len(),
67 metadata.ino(),
68 );
69 panic!("{}", msg);
70 }
71 }
72 Ok(())
73}
74
75#[allow(dead_code)]
79pub fn binary_write_vec<T>(f: &mut std::fs::File, x: &[T]) -> Result<(), Error>
80where
81 T: BinaryInputOutputSafe,
82{
83 let n = x.len();
84 binary_write_from_ref::<usize>(f, &n, 1)?;
85 binary_write_from_ref::<T>(f, &x[0], x.len())
86}
87
88#[allow(dead_code)]
89pub fn binary_read_vec<T>(f: &mut std::fs::File, x: &mut Vec<T>) -> Result<(), Error>
90where
91 T: BinaryInputOutputSafe,
92{
93 let mut n: usize = 0;
96 binary_read_to_ref::<usize>(f, &mut n, 1)?;
97
98 let len = x.len();
102 if len + n > x.capacity() {
103 let extra: usize = len + n - x.capacity();
104 x.reserve(extra);
105 }
106 unsafe {
107 x.set_len(len + n);
108 }
109
110 binary_read_to_ref::<T>(f, &mut x[len], n)
113}
114
115pub fn binary_write_vec_vec<T>(f: &mut std::fs::File, x: &[Vec<T>]) -> Result<(), Error>
116where
117 T: BinaryInputOutputSafe,
118{
119 let n = x.len();
120 binary_write_from_ref::<usize>(f, &n, 1)?;
121 for i in 0..n {
122 binary_write_vec::<T>(f, &x[i])?;
123 }
124 Ok(())
125}
126
127pub fn binary_read_vec_vec<T>(f: &mut std::fs::File, x: &mut Vec<Vec<T>>) -> Result<(), Error>
128where
129 T: BinaryInputOutputSafe + Clone,
130{
131 let mut n: usize = 0;
132 binary_read_to_ref::<usize>(f, &mut n, 1)?;
133 let len = x.len();
134 if len + n > x.capacity() {
135 let extra: usize = len + n - x.capacity();
136 x.reserve(extra);
137 }
138 x.resize(len + n, Vec::<T>::new());
139 for i in 0..n {
140 binary_read_vec::<T>(f, &mut x[i])?;
141 }
142 Ok(())
143}