1#![warn(missing_docs)]
59
60use std::io;
61use std::io::prelude::*;
62
63pub enum LittleEndian {}
65pub enum BigEndian {}
67
68pub trait Endianness {
70 fn is_little_endian() -> bool;
72}
73
74pub trait WritePodExt {
76 fn write_u64<T: Endianness>(&mut self, u64) -> io::Result<()>;
78 fn write_u32<T: Endianness>(&mut self, u32) -> io::Result<()>;
80 fn write_u16<T: Endianness>(&mut self, u16) -> io::Result<()>;
82 fn write_u8(&mut self, u8) -> io::Result<()>;
84 fn write_i64<T: Endianness>(&mut self, i64) -> io::Result<()>;
86 fn write_i32<T: Endianness>(&mut self, i32) -> io::Result<()>;
88 fn write_i16<T: Endianness>(&mut self, i16) -> io::Result<()>;
90 fn write_i8(&mut self, i8) -> io::Result<()>;
92 fn write_f32<T: Endianness>(&mut self, f32) -> io::Result<()>;
94 fn write_f64<T: Endianness>(&mut self, f64) -> io::Result<()>;
96}
97
98pub trait ReadPodExt {
100 fn read_u64<T: Endianness>(&mut self) -> io::Result<u64>;
102 fn read_u32<T: Endianness>(&mut self) -> io::Result<u32>;
104 fn read_u16<T: Endianness>(&mut self) -> io::Result<u16>;
106 fn read_u8(&mut self) -> io::Result<u8>;
108 fn read_i64<T: Endianness>(&mut self) -> io::Result<i64>;
110 fn read_i32<T: Endianness>(&mut self) -> io::Result<i32>;
112 fn read_i16<T: Endianness>(&mut self) -> io::Result<i16>;
114 fn read_i8(&mut self) -> io::Result<i8>;
116 fn read_f32<T: Endianness>(&mut self) -> io::Result<f32>;
118 fn read_f64<T: Endianness>(&mut self) -> io::Result<f64>;
120 fn read_exact(&mut self, usize) -> io::Result<Vec<u8>>;
122}
123
124impl Endianness for LittleEndian {
125 fn is_little_endian() -> bool {
126 true
127 }
128}
129
130impl Endianness for BigEndian {
131 fn is_little_endian() -> bool {
132 false
133 }
134}
135
136impl<W: Write> WritePodExt for W {
137 fn write_u64<T: Endianness>(&mut self, val: u64) -> io::Result<()> {
138 let buf = match <T as Endianness>::is_little_endian() {
139 true => u64::to_le_bytes(val),
140 false => u64::to_be_bytes(val),
141 };
142 self.write_all(&buf)
143 }
144
145 fn write_u32<T: Endianness>(&mut self, val: u32) -> io::Result<()> {
146 let buf = match <T as Endianness>::is_little_endian() {
147 true => u32::to_le_bytes(val),
148 false => u32::to_be_bytes(val),
149 };
150 self.write_all(&buf)
151 }
152
153 fn write_u16<T: Endianness>(&mut self, val: u16) -> io::Result<()> {
154 let buf = match <T as Endianness>::is_little_endian() {
155 true => u16::to_le_bytes(val),
156 false => u16::to_be_bytes(val),
157 };
158 self.write_all(&buf)
159 }
160
161 fn write_u8(&mut self, val: u8) -> io::Result<()> {
162 self.write_all(&[val])
163 }
164
165 fn write_i64<T: Endianness>(&mut self, val: i64) -> io::Result<()> {
166 self.write_u64::<T>(val as u64)
167 }
168
169 fn write_i32<T: Endianness>(&mut self, val: i32) -> io::Result<()> {
170 self.write_u32::<T>(val as u32)
171 }
172
173 fn write_i16<T: Endianness>(&mut self, val: i16) -> io::Result<()> {
174 self.write_u16::<T>(val as u16)
175 }
176
177 fn write_i8(&mut self, val: i8) -> io::Result<()> {
178 self.write_u8(val as u8)
179 }
180
181 fn write_f32<T: Endianness>(&mut self, val: f32) -> io::Result<()> {
182 let tval: u32 = val.to_bits();
183 self.write_u32::<T>(tval)
184 }
185
186 fn write_f64<T: Endianness>(&mut self, val: f64) -> io::Result<()> {
187 let tval: u64 = val.to_bits();
188 self.write_u64::<T>(tval)
189 }
190}
191
192#[inline]
193fn fill_buf<R: Read>(reader: &mut R, buf: &mut [u8]) -> io::Result<()> {
194 let mut idx = 0;
195 while idx != buf.len() {
196 match reader.read(&mut buf[idx..]) {
197 Ok(0) => return Err(io::Error::new(io::ErrorKind::Other, "Could not read enough bytes")),
198 Ok(v) => { idx += v; }
199 Err(ref e) if e.kind() == io::ErrorKind::Interrupted => {}
200 Err(e) => return Err(e),
201 }
202 }
203 Ok(())
204}
205
206impl<R: Read> ReadPodExt for R {
207 fn read_u64<T: Endianness>(&mut self) -> io::Result<u64> {
208 let mut buf = [0u8; 8];
209 fill_buf(self, &mut buf)?;
210 let val = match <T as Endianness>::is_little_endian() {
211 true => u64::from_le_bytes(buf),
212 false => u64::from_be_bytes(buf),
213 };
214 Ok(val)
215 }
216
217 fn read_u32<T: Endianness>(&mut self) -> io::Result<u32> {
218 let mut buf = [0u8; 4];
219 fill_buf(self, &mut buf)?;
220 let val = match <T as Endianness>::is_little_endian() {
221 true => u32::from_le_bytes(buf),
222 false => u32::from_be_bytes(buf),
223 };
224 Ok(val)
225 }
226
227 fn read_u16<T: Endianness>(&mut self) -> io::Result<u16> {
228 let mut buf = [0u8; 2];
229 fill_buf(self, &mut buf)?;
230 let val = match <T as Endianness>::is_little_endian() {
231 true => u16::from_le_bytes(buf),
232 false => u16::from_be_bytes(buf),
233 };
234 Ok(val)
235 }
236
237 fn read_u8(&mut self) -> io::Result<u8> {
238 let buf = &mut [0u8; 1];
239 fill_buf(self, buf)?;
240 Ok(buf[0])
241 }
242
243 fn read_i64<T: Endianness>(&mut self) -> io::Result<i64> {
244 self.read_u64::<T>().map(|v| v as i64)
245 }
246
247 fn read_i32<T: Endianness>(&mut self) -> io::Result<i32> {
248 self.read_u32::<T>().map(|v| v as i32)
249 }
250
251 fn read_i16<T: Endianness>(&mut self) -> io::Result<i16> {
252 self.read_u16::<T>().map(|v| v as i16)
253 }
254
255 fn read_i8(&mut self) -> io::Result<i8> {
256 self.read_u8().map(|v| v as i8)
257 }
258
259 fn read_f64<T: Endianness>(&mut self) -> io::Result<f64> {
260 self.read_u64::<T>().map(|v| f64::from_bits(v))
261 }
262
263 fn read_f32<T: Endianness>(&mut self) -> io::Result<f32> {
264 self.read_u32::<T>().map(|v| f32::from_bits(v))
265 }
266
267 fn read_exact(&mut self, len: usize) -> io::Result<Vec<u8>> {
268 let mut res = vec![0; len];
269 fill_buf(self, &mut res)?;
270 Ok(res)
271 }
272}