1 //! Additional methods for Read and Write
2 //!
3 //! The additional methods implemented allow reading and writing integers and floats
4 //! in the specified endianness.
5 //!
6 //! # Usage
7 //!
8 //! Basically, you need to `use` the trait WritePodExt or ReadPodExt.
9 //!
10 //! # Examples
11 //!
12 //! ## Reading
13 //!
14 //! To read some value from a reader, import ReadPodExt and the needed endianness.
15 //!
16 //! ```
17 //! use podio::{ReadPodExt, BigEndian};
18 //!
19 //! let slice: &[u8] = &[0x10, 0x20, 0x30, 0x40];
20 //! let mut reader = std::io::Cursor::new(slice);
21 //!
22 //! let value = reader.read_u32::<BigEndian>().unwrap();
23 //!
24 //! assert_eq!(value, 0x10203040);
25 //! ```
26 //!
27 //! ## Writing
28 //!
29 //! For writing, you need to import the trait WritePodExt.
30 //!
31 //! ```
32 //! use podio::{WritePodExt, LittleEndian};
33 //!
34 //! let slice: &mut [u8] = &mut [0; 2];
35 //! let mut writer = std::io::Cursor::new(slice);
36 //!
37 //! writer.write_u16::<LittleEndian>(0x8802).unwrap();
38 //!
39 //! assert_eq!(writer.into_inner(), &[0x02, 0x88]);
40 //! ```
41 //!
42 //! ## Read exact
43 //!
44 //! One additional method, not really dealing with POD, is `read_exact`.
45 //!
46 //! ```
47 //! use podio::ReadPodExt;
48 //!
49 //! let slice: &[u8] = &[0, 1, 2, 3];
50 //! let mut reader = std::io::Cursor::new(slice);
51 //!
52 //! assert_eq!(reader.read_exact(1).unwrap(), [0]);
53 //! assert_eq!(reader.read_exact(2).unwrap(), [1,2]);
54 //! assert_eq!(reader.read_exact(0).unwrap(), []);
55 //! assert_eq!(reader.read_exact(1).unwrap(), [3]);
56 //! assert!(reader.read_exact(1).is_err());
57 
58 #![warn(missing_docs)]
59 
60 use std::io;
61 use std::io::prelude::*;
62 
63 /// Little endian. The number `0xABCD` is stored `[0xCD, 0xAB]`
64 pub enum LittleEndian {}
65 /// Big endian. The number `0xABCD` is stored `[0xAB, 0xCD]`
66 pub enum BigEndian {}
67 
68 /// Trait implementing conversion methods for a specific endianness
69 pub trait Endianness {
70     /// Converts a value from the platform type to the specified endianness
int_to_target<T: EndianConvert>(val: T) -> T71     fn int_to_target<T: EndianConvert>(val: T) -> T;
72     /// Converts a value from the sepcified endianness to the platform type
int_from_target<T: EndianConvert>(val: T) -> T73     fn int_from_target<T: EndianConvert>(val: T) -> T;
74 }
75 
76 /// Generic trait for endian conversions on integers
77 pub trait EndianConvert {
78     /// Convert self to a big-endian value
to_be(self) -> Self79     fn to_be(self) -> Self;
80     /// Convert self to a little-endian value
to_le(self) -> Self81     fn to_le(self) -> Self;
82     /// Convert a big-endian value to the target endianness
from_be(x: Self) -> Self83     fn from_be(x: Self) -> Self;
84     /// Convert a little-endian value to the target endiannes
from_le(x: Self) -> Self85     fn from_le(x: Self) -> Self;
86 }
87 
88 /// Additional write methods for a io::Write
89 pub trait WritePodExt {
90     /// Write a u64
write_u64<T: Endianness>(&mut self, u64) -> io::Result<()>91     fn write_u64<T: Endianness>(&mut self, u64) -> io::Result<()>;
92     /// Write a u32
write_u32<T: Endianness>(&mut self, u32) -> io::Result<()>93     fn write_u32<T: Endianness>(&mut self, u32) -> io::Result<()>;
94     /// Write a u16
write_u16<T: Endianness>(&mut self, u16) -> io::Result<()>95     fn write_u16<T: Endianness>(&mut self, u16) -> io::Result<()>;
96     /// Write a u8
write_u8(&mut self, u8) -> io::Result<()>97     fn write_u8(&mut self, u8) -> io::Result<()>;
98     /// Write a i64
write_i64<T: Endianness>(&mut self, i64) -> io::Result<()>99     fn write_i64<T: Endianness>(&mut self, i64) -> io::Result<()>;
100     /// Write a i32
write_i32<T: Endianness>(&mut self, i32) -> io::Result<()>101     fn write_i32<T: Endianness>(&mut self, i32) -> io::Result<()>;
102     /// Write a i16
write_i16<T: Endianness>(&mut self, i16) -> io::Result<()>103     fn write_i16<T: Endianness>(&mut self, i16) -> io::Result<()>;
104     /// Write a i8
write_i8(&mut self, i8) -> io::Result<()>105     fn write_i8(&mut self, i8) -> io::Result<()>;
106     /// Write a f32
write_f32<T: Endianness>(&mut self, f32) -> io::Result<()>107     fn write_f32<T: Endianness>(&mut self, f32) -> io::Result<()>;
108     /// Write a f64
write_f64<T: Endianness>(&mut self, f64) -> io::Result<()>109     fn write_f64<T: Endianness>(&mut self, f64) -> io::Result<()>;
110 }
111 
112 /// Additional read methods for a io::Read
113 pub trait ReadPodExt {
114     /// Read a u64
read_u64<T: Endianness>(&mut self) -> io::Result<u64>115     fn read_u64<T: Endianness>(&mut self) -> io::Result<u64>;
116     /// Read a u32
read_u32<T: Endianness>(&mut self) -> io::Result<u32>117     fn read_u32<T: Endianness>(&mut self) -> io::Result<u32>;
118     /// Read a u16
read_u16<T: Endianness>(&mut self) -> io::Result<u16>119     fn read_u16<T: Endianness>(&mut self) -> io::Result<u16>;
120     /// Read a u8
read_u8(&mut self) -> io::Result<u8>121     fn read_u8(&mut self) -> io::Result<u8>;
122     /// Read a i64
read_i64<T: Endianness>(&mut self) -> io::Result<i64>123     fn read_i64<T: Endianness>(&mut self) -> io::Result<i64>;
124     /// Read a i32
read_i32<T: Endianness>(&mut self) -> io::Result<i32>125     fn read_i32<T: Endianness>(&mut self) -> io::Result<i32>;
126     /// Read a i16
read_i16<T: Endianness>(&mut self) -> io::Result<i16>127     fn read_i16<T: Endianness>(&mut self) -> io::Result<i16>;
128     /// Read a i8
read_i8(&mut self) -> io::Result<i8>129     fn read_i8(&mut self) -> io::Result<i8>;
130     /// Read a f32
read_f32<T: Endianness>(&mut self) -> io::Result<f32>131     fn read_f32<T: Endianness>(&mut self) -> io::Result<f32>;
132     /// Read a f64
read_f64<T: Endianness>(&mut self) -> io::Result<f64>133     fn read_f64<T: Endianness>(&mut self) -> io::Result<f64>;
134     /// Read a specific number of bytes
read_exact(&mut self, usize) -> io::Result<Vec<u8>>135     fn read_exact(&mut self, usize) -> io::Result<Vec<u8>>;
136 }
137 
138 impl Endianness for LittleEndian {
139     #[inline]
int_to_target<T: EndianConvert>(val: T) -> T140     fn int_to_target<T: EndianConvert>(val: T) -> T {
141         val.to_le()
142     }
143     #[inline]
int_from_target<T: EndianConvert>(val: T) -> T144     fn int_from_target<T: EndianConvert>(val: T) -> T {
145         <T as EndianConvert>::from_le(val)
146     }
147 }
148 
149 impl Endianness for BigEndian {
150     #[inline]
int_to_target<T: EndianConvert>(val: T) -> T151     fn int_to_target<T: EndianConvert>(val: T) -> T {
152         val.to_be()
153     }
154     #[inline]
int_from_target<T: EndianConvert>(val: T) -> T155     fn int_from_target<T: EndianConvert>(val: T) -> T {
156         <T as EndianConvert>::from_be(val)
157     }
158 }
159 
160 macro_rules! impl_platform_convert {
161     ($T:ty) => {
162         impl EndianConvert for $T {
163             #[inline]
164             fn to_be(self) -> $T {
165                 self.to_be()
166             }
167 
168             #[inline]
169             fn to_le(self) -> $T {
170                 self.to_le()
171             }
172 
173             #[inline]
174             fn from_be(x: $T) -> $T {
175                 if cfg!(target_endian = "big") { x } else { x.swap_bytes() }
176             }
177 
178             #[inline]
179             fn from_le(x: $T) -> $T {
180                 if cfg!(target_endian = "little") { x } else { x.swap_bytes() }
181             }
182         }
183     };
184 }
185 
186 impl_platform_convert!(u8);
187 impl_platform_convert!(u16);
188 impl_platform_convert!(u32);
189 impl_platform_convert!(u64);
190 
191 #[cfg(target_endian = "little")]
192 macro_rules! val_to_buf {
193     ($val:ident, $T:expr) => {
194         {
195             let mut buf = [0; $T];
196             for i in 0..buf.len() {
197                 buf[i] = ($val >> (i * 8)) as u8;
198             }
199             buf
200         }
201     };
202 }
203 
204 #[cfg(target_endian = "big")]
205 macro_rules! val_to_buf {
206     ($val:ident, $T:expr) => {
207         {
208             let mut buf = [0; $T];
209             for i in 0..buf.len() {
210                 buf[buf.len() - 1 - i] = ($val >> (i * 8)) as u8;
211             }
212             buf
213         }
214     };
215 }
216 
217 impl<W: Write> WritePodExt for W {
write_u64<T: Endianness>(&mut self, val: u64) -> io::Result<()>218     fn write_u64<T: Endianness>(&mut self, val: u64) -> io::Result<()> {
219         let tval = <T as Endianness>::int_to_target(val);
220         let buf = val_to_buf!(tval, 8);
221         self.write_all(&buf)
222     }
223 
write_u32<T: Endianness>(&mut self, val: u32) -> io::Result<()>224     fn write_u32<T: Endianness>(&mut self, val: u32) -> io::Result<()> {
225         let tval = <T as Endianness>::int_to_target(val);
226         let buf = val_to_buf!(tval, 4);
227         self.write_all(&buf)
228     }
229 
write_u16<T: Endianness>(&mut self, val: u16) -> io::Result<()>230     fn write_u16<T: Endianness>(&mut self, val: u16) -> io::Result<()> {
231         let tval = <T as Endianness>::int_to_target(val);
232         let buf = val_to_buf!(tval, 2);
233         self.write_all(&buf)
234     }
235 
write_u8(&mut self, val: u8) -> io::Result<()>236     fn write_u8(&mut self, val: u8) -> io::Result<()> {
237         self.write_all(&[val])
238     }
239 
write_i64<T: Endianness>(&mut self, val: i64) -> io::Result<()>240     fn write_i64<T: Endianness>(&mut self, val: i64) -> io::Result<()> {
241         self.write_u64::<T>(val as u64)
242     }
243 
write_i32<T: Endianness>(&mut self, val: i32) -> io::Result<()>244     fn write_i32<T: Endianness>(&mut self, val: i32) -> io::Result<()> {
245         self.write_u32::<T>(val as u32)
246     }
247 
write_i16<T: Endianness>(&mut self, val: i16) -> io::Result<()>248     fn write_i16<T: Endianness>(&mut self, val: i16) -> io::Result<()> {
249         self.write_u16::<T>(val as u16)
250     }
251 
write_i8(&mut self, val: i8) -> io::Result<()>252     fn write_i8(&mut self, val: i8) -> io::Result<()> {
253         self.write_u8(val as u8)
254     }
255 
write_f32<T: Endianness>(&mut self, val: f32) -> io::Result<()>256     fn write_f32<T: Endianness>(&mut self, val: f32) -> io::Result<()> {
257         let tval: u32 = val.to_bits();
258         self.write_u32::<T>(tval)
259     }
260 
write_f64<T: Endianness>(&mut self, val: f64) -> io::Result<()>261     fn write_f64<T: Endianness>(&mut self, val: f64) -> io::Result<()> {
262         let tval: u64 = val.to_bits();
263         self.write_u64::<T>(tval)
264     }
265 }
266 
267 #[inline]
fill_buf<R: Read>(reader: &mut R, buf: &mut [u8]) -> io::Result<()>268 fn fill_buf<R: Read>(reader: &mut R, buf: &mut [u8]) -> io::Result<()> {
269     let mut idx = 0;
270     while idx != buf.len() {
271         match reader.read(&mut buf[idx..]) {
272             Ok(0) => return Err(io::Error::new(io::ErrorKind::Other, "Could not read enough bytes")),
273             Ok(v) => { idx += v; }
274             Err(ref e) if e.kind() == io::ErrorKind::Interrupted => {}
275             Err(e) => return Err(e),
276         }
277     }
278     Ok(())
279 }
280 
281 #[cfg(target_endian = "little")]
282 macro_rules! buf_to_val {
283     ($buf:ident, $T:ty) => {
284         {
285             let mut val: $T = 0;
286             for i in 0..$buf.len() {
287                 val |= ($buf[i] as $T) << (i * 8);
288             }
289             val
290         }
291     };
292 }
293 
294 #[cfg(target_endian = "big")]
295 macro_rules! buf_to_val {
296     ($buf:ident, $T:ty) => {
297         {
298             let mut val: $T = 0;
299             for i in 0..$buf.len() {
300                 val |= ($buf[$buf.len() - 1 - i] as $T) << (i * 8);
301             }
302             val
303         }
304     };
305 }
306 
307 impl<R: Read> ReadPodExt for R {
read_u64<T: Endianness>(&mut self) -> io::Result<u64>308     fn read_u64<T: Endianness>(&mut self) -> io::Result<u64> {
309         let buf = &mut [0u8; 8];
310         try!(fill_buf(self, buf));
311         let tval = buf_to_val!(buf, u64);
312         Ok(<T as Endianness>::int_from_target(tval))
313     }
314 
read_u32<T: Endianness>(&mut self) -> io::Result<u32>315     fn read_u32<T: Endianness>(&mut self) -> io::Result<u32> {
316         let buf = &mut [0u8; 4];
317         try!(fill_buf(self, buf));
318         let tval = buf_to_val!(buf, u32);
319         Ok(<T as Endianness>::int_from_target(tval))
320     }
321 
read_u16<T: Endianness>(&mut self) -> io::Result<u16>322     fn read_u16<T: Endianness>(&mut self) -> io::Result<u16> {
323         let buf = &mut [0u8; 2];
324         try!(fill_buf(self, buf));
325         let tval = buf_to_val!(buf, u16);
326         Ok(<T as Endianness>::int_from_target(tval))
327     }
328 
read_u8(&mut self) -> io::Result<u8>329     fn read_u8(&mut self) -> io::Result<u8> {
330         let buf = &mut [0u8; 1];
331         try!(fill_buf(self, buf));
332         Ok(buf[0])
333     }
334 
read_i64<T: Endianness>(&mut self) -> io::Result<i64>335     fn read_i64<T: Endianness>(&mut self) -> io::Result<i64> {
336         self.read_u64::<T>().map(|v| v as i64)
337     }
338 
read_i32<T: Endianness>(&mut self) -> io::Result<i32>339     fn read_i32<T: Endianness>(&mut self) -> io::Result<i32> {
340         self.read_u32::<T>().map(|v| v as i32)
341     }
342 
read_i16<T: Endianness>(&mut self) -> io::Result<i16>343     fn read_i16<T: Endianness>(&mut self) -> io::Result<i16> {
344         self.read_u16::<T>().map(|v| v as i16)
345     }
346 
read_i8(&mut self) -> io::Result<i8>347     fn read_i8(&mut self) -> io::Result<i8> {
348         self.read_u8().map(|v| v as i8)
349     }
350 
read_f64<T: Endianness>(&mut self) -> io::Result<f64>351     fn read_f64<T: Endianness>(&mut self) -> io::Result<f64> {
352         self.read_u64::<T>().map(|v| f64::from_bits(v))
353     }
354 
read_f32<T: Endianness>(&mut self) -> io::Result<f32>355     fn read_f32<T: Endianness>(&mut self) -> io::Result<f32> {
356         self.read_u32::<T>().map(|v| f32::from_bits(v))
357     }
358 
read_exact(&mut self, len: usize) -> io::Result<Vec<u8>>359     fn read_exact(&mut self, len: usize) -> io::Result<Vec<u8>> {
360         let mut res = vec![0; len];
361         try!(fill_buf(self, &mut res));
362         Ok(res)
363     }
364 }
365