byteordered/
wrap.rs

1//! Wrapper types providing byte order awareness.
2
3use byteorder::{
4    BigEndian, LittleEndian, NativeEndian, NetworkEndian, ReadBytesExt, WriteBytesExt,
5};
6use std::fmt::Arguments;
7use std::io::{BufRead, Read, Result as IoResult, Seek, SeekFrom, Write};
8use {Endian, Endianness, StaticEndianness};
9
10/// Wrapper type for a reader or writer with an assumed byte order.
11///
12/// More details can be found at the [crate level documentation][1].
13///
14/// [1]: index.html
15#[derive(Debug, Clone)]
16pub struct ByteOrdered<T, E> {
17    inner: T,
18    endianness: E,
19}
20
21impl<T, E> ByteOrdered<T, E>
22where
23    E: Default,
24{
25    #[inline]
26    fn new_default(inner: T) -> Self {
27        ByteOrdered {
28            inner,
29            endianness: Default::default(),
30        }
31    }
32}
33
34impl<T> ByteOrdered<T, StaticEndianness<LittleEndian>> {
35    /// Obtains a new reader or writer that assumes data in _little endian_.
36    #[inline]
37    pub fn le(inner: T) -> Self {
38        ByteOrdered::new_default(inner)
39    }
40}
41
42impl<T> ByteOrdered<T, StaticEndianness<BigEndian>> {
43    /// Obtains a new reader or writer that assumes data in _big endian_.
44    #[inline]
45    pub fn be(inner: T) -> Self {
46        ByteOrdered::new_default(inner)
47    }
48}
49
50impl<T> ByteOrdered<T, StaticEndianness<NativeEndian>> {
51    /// Obtains a new reader or writer that assumes data in the system's
52    /// _native endianness_. While this method might sounds a bit pointless,
53    /// it enables easier byte order changes through method chaining).
54    #[inline]
55    pub fn native(inner: T) -> Self {
56        ByteOrdered::new_default(inner)
57    }
58}
59
60impl<T> ByteOrdered<T, StaticEndianness<NetworkEndian>> {
61    /// Obtains a new reader or writer that assumes _network order_.
62    #[inline]
63    pub fn network(inner: T) -> Self {
64        ByteOrdered::new_default(inner)
65    }
66}
67
68impl<T> ByteOrdered<T, Endianness> {
69    /// Creates a new reader or writer that assumes data in the given byte
70    /// order known at _run-time_.
71    /// That is, the type representing the byte order
72    /// is the enum type [`Endianness`].
73    ///
74    /// Although it is equivalent to [`ByteOrdered::new`][`new`], this function
75    /// leaves a code signal that subsequent calls depend on conditions
76    /// resolved at run-time. If you know the data's endianness in compile
77    /// time, the other constructors are preferred (e.g. [`new`], [`le`] or
78    /// [`be`]), so as to avoid the overhead of dynamic dispatching.
79    ///
80    /// [`Endianness`]: ../base/struct.Endianness.html
81    /// [`new`]: struct.ByteOrdered.html#method.new
82    /// [`le`]: struct.ByteOrdered.html#method.le
83    /// [`be`]: struct.ByteOrdered.html#method.be
84    #[inline]
85    pub fn runtime(inner: T, endianness: Endianness) -> Self {
86        ByteOrdered::new(inner, endianness)
87    }
88}
89
90impl<T, E> From<(T, E)> for ByteOrdered<T, E> {
91    #[inline]
92    fn from((inner, endianness): (T, E)) -> Self {
93        ByteOrdered { inner, endianness }
94    }
95}
96
97impl<T, E> ByteOrdered<T, E>
98where
99    E: Endian,
100{
101    /// Creates a new reader or writer that assumes data in the given byte
102    /// order. This flexible constructor admits any kind of byte order (static
103    /// and dynamic).
104    ///
105    /// **Note:** The other constructors ([`le`], [`be`], [`native`], and
106    /// [`runtime`]) are more recommended because they are easier to use and
107    /// leave a better signal of whether the endianness is known at compile
108    /// time or at run time. For example, if you pass a value literal of type
109    /// `Endianness` (such as `Endianness::Little`), the program will perform
110    /// dynamic dispatching in spite of the fixed byte order. The use of this
111    /// method is more appropriate when constructing functions which are
112    /// generic over the endianness type.
113    ///
114    /// [`le`]: struct.ByteOrdered.html#method.le
115    /// [`be`]: struct.ByteOrdered.html#method.be
116    /// [`native`]: struct.ByteOrdered.html#method.native
117    /// [`runtime`]: struct.ByteOrdered.html#method.runtime
118    #[inline]
119    pub fn new(inner: T, endianness: E) -> Self {
120        ByteOrdered { inner, endianness }
121    }
122
123    /// Recovers the inner reader or writer from this wrapper. Information
124    /// about the assumed byte order is discarded.
125    #[inline]
126    pub fn into_inner(self) -> T {
127        self.inner
128    }
129
130    /// Obtains an exclusive mutable reference to the inner reader or writer in
131    /// this wrapper. Information about the assumed byte order is ignored until
132    /// the reference is dropped.
133    #[inline]
134    pub fn inner_mut(&mut self) -> &mut T {
135        &mut self.inner
136    }
137
138    /// Converts from `ByteOrdered<T, E>` to `ByteOrdered<&mut T, E>`,
139    /// copying the endianness information.
140    #[inline]
141    pub fn as_mut(&mut self) -> ByteOrdered<&mut T, E>
142    where
143        E: Copy,
144    {
145        let e = self.endianness;
146        ByteOrdered::new(self.inner_mut(), e)
147    }
148
149    /// Disbands a `ByteOrder` into its parts.
150    #[inline]
151    pub fn into_parts(self) -> (T, E) {
152        (self.inner, self.endianness)
153    }
154
155    /// Maps a `ByteOrdered<T, E>` into a `ByteOrdered<O, E>` by applying the
156    /// given function to the inner reader or writer.
157    #[inline]
158    pub fn map<F, U>(self, f: F) -> ByteOrdered<U, E>
159    where
160        F: FnOnce(T) -> U,
161    {
162        let (src, e) = self.into_parts();
163        ByteOrdered::new(f(src), e)
164    }
165
166    /// Changes the assumed byte order of the reader or writer.
167    #[inline]
168    pub fn into_endianness<E2: Endian>(self, endianness: E2) -> ByteOrdered<T, E2> {
169        ByteOrdered::new(self.inner, endianness)
170    }
171
172    /// Modifies the assumed byte order of the reader or writer
173    /// inline with the value.
174    /// Since the endianness type needs to be the same,
175    /// this function is only relevant when
176    /// `E` is a run-time defined byte order
177    /// (see [`Endianness`]).
178    ///
179    /// [`Endianness`]: ../base/struct.Endianness.html
180    #[inline]
181    pub fn set_endianness(&mut self, endianness: E) {
182        self.endianness = endianness;
183    }
184
185    /// Changes the assumed byte order of the reader or writer to
186    /// little endian.
187    #[inline]
188    pub fn into_le(self) -> ByteOrdered<T, StaticEndianness<LittleEndian>> {
189        ByteOrdered::le(self.inner)
190    }
191
192    /// Changes the assumed byte order of the reader or writer to
193    /// little endian.
194    #[inline]
195    pub fn into_be(self) -> ByteOrdered<T, StaticEndianness<BigEndian>> {
196        ByteOrdered::be(self.inner)
197    }
198
199    /// Changes the assumed byte order of the reader or writer to
200    /// the system's native endianness.
201    #[inline]
202    pub fn into_native(self) -> ByteOrdered<T, StaticEndianness<NativeEndian>> {
203        ByteOrdered::native(self.inner)
204    }
205
206    /// Converts the assumed endianness to the opposite of the current order.
207    #[inline]
208    pub fn into_opposite(self) -> ByteOrdered<T, E::Opposite>
209    where
210        E: Endian,
211    {
212        let e = self.endianness.into_opposite();
213        ByteOrdered {
214            inner: self.inner,
215            endianness: e,
216        }
217    }
218
219    /// Retrieves the byte order assumed by this wrapper.
220    #[inline]
221    pub fn endianness(&self) -> E
222    where
223        E: Copy,
224    {
225        self.endianness
226    }
227
228    /// Checks whether the assumed endianness is the system's native byte
229    /// order.
230    #[inline]
231    pub fn is_native(&self) -> bool
232    where
233        E: Endian,
234    {
235        self.endianness.is_native()
236    }
237}
238
239impl<R, E> Read for ByteOrdered<R, E>
240where
241    R: Read,
242{
243    #[inline]
244    fn read(&mut self, buf: &mut [u8]) -> IoResult<usize> {
245        self.inner.read(buf)
246    }
247
248    #[inline]
249    fn read_to_end(&mut self, buf: &mut Vec<u8>) -> IoResult<usize> {
250        self.inner.read_to_end(buf)
251    }
252
253    #[inline]
254    fn read_to_string(&mut self, buf: &mut String) -> IoResult<usize> {
255        self.inner.read_to_string(buf)
256    }
257
258    #[inline]
259    fn read_exact(&mut self, buf: &mut [u8]) -> IoResult<()> {
260        self.inner.read_exact(buf)
261    }
262}
263
264impl<W, E> Write for ByteOrdered<W, E>
265where
266    W: Write,
267{
268    #[inline]
269    fn write(&mut self, buf: &[u8]) -> IoResult<usize> {
270        self.inner.write(buf)
271    }
272
273    #[inline]
274    fn flush(&mut self) -> IoResult<()> {
275        self.inner.flush()
276    }
277
278    #[inline]
279    fn write_all(&mut self, buf: &[u8]) -> IoResult<()> {
280        self.inner.write_all(buf)
281    }
282
283    #[inline]
284    fn write_fmt(&mut self, fmt: Arguments) -> IoResult<()> {
285        self.inner.write_fmt(fmt)
286    }
287}
288
289impl<R, E> ByteOrdered<R, E>
290where
291    R: ReadBytesExt,
292    E: Endian,
293{
294    /// Reads a signed 8 bit integer from the underlying reader.
295    ///
296    /// This method does exactly the same thing as `read_i8` in
297    /// `byteorder::ReadBytesExt`. It is included so that users do not have to
298    /// import the former trait.
299    ///
300    /// # Errors
301    ///
302    /// This method returns the same errors as [`Read::read_exact`].
303    ///
304    /// [`Read::read_exact`]: https://doc.rust-lang.org/std/io/trait.Read.html#method.read_exact
305    ///
306    /// # Examples
307    ///
308    /// Read unsigned 8 bit integers from a `Read`:
309    ///
310    /// ```rust
311    /// use byteordered::ByteOrdered;
312    ///
313    /// # fn run() -> std::io::Result<()> {
314    /// let mut rdr = ByteOrdered::native(&[2, 5][..]);
315    /// assert_eq!(2, rdr.read_i8()?);
316    /// assert_eq!(5, rdr.read_i8()?);
317    /// # Ok(())
318    /// # }
319    /// # run().unwrap();
320    /// ```
321    #[inline]
322    pub fn read_i8(&mut self) -> IoResult<i8> {
323        ReadBytesExt::read_i8(self)
324    }
325
326    /// Reads an unsigned 8 bit integer from the underlying reader.
327    ///
328    /// This method does exactly the same thing as `read_u8` in
329    /// `byteorder::ReadBytesExt`. It is included so that users do not have to
330    /// import the former trait.
331    ///
332    /// # Errors
333    ///
334    /// This method returns the same errors as [`Read::read_exact`].
335    ///
336    /// [`Read::read_exact`]: https://doc.rust-lang.org/std/io/trait.Read.html#method.read_exact
337    ///
338    /// # Examples
339    ///
340    /// Read unsigned 8 bit integers from a `Read`:
341    ///
342    /// ```rust
343    /// use byteordered::ByteOrdered;
344    ///
345    /// # fn run() -> std::io::Result<()> {
346    /// let mut rdr = ByteOrdered::native(&[2, 5][..]);
347    /// assert_eq!(2, rdr.read_u8()?);
348    /// assert_eq!(5, rdr.read_u8()?);
349    /// # Ok(())
350    /// # }
351    /// # run().unwrap();
352    /// ```
353    #[inline]
354    pub fn read_u8(&mut self) -> IoResult<u8> {
355        ReadBytesExt::read_u8(self)
356    }
357
358    /// Reads a signed 16 bit integer from the underlying reader.
359    ///
360    /// # Errors
361    ///
362    /// This method returns the same errors as [`Read::read_exact`].
363    ///
364    /// [`Read::read_exact`]: https://doc.rust-lang.org/std/io/trait.Read.html#method.read_exact
365    ///
366    /// # Examples
367    ///
368    /// Read signed 16 bit big-endian integers from a `Read`:
369    ///
370    /// ```rust
371    /// use byteordered::ByteOrdered;
372    ///
373    /// # fn run() -> std::io::Result<()> {
374    /// let mut rdr = ByteOrdered::be(&[0x00, 0xc1, 0xff, 0x7c][..]);
375    /// assert_eq!(193, rdr.read_i16()?);
376    /// assert_eq!(-132, rdr.read_i16()?);
377    /// # Ok(())
378    /// # }
379    /// # run().unwrap();
380    /// ```
381    #[inline]
382    pub fn read_i16(&mut self) -> IoResult<i16> {
383        self.endianness.read_i16(self.inner.by_ref())
384    }
385
386    /// Reads a sequence of signed 16 bit integers from the underlying reader.
387    ///
388    /// The given buffer is either filled completely or an error is returned.
389    /// If an error is returned,
390    /// the contents of `dst` are unspecified.
391    ///
392    /// # Errors
393    ///
394    /// This method returns the same errors as [`Read::read_exact`].
395    ///
396    /// [`Read::read_exact`]: https://doc.rust-lang.org/std/io/trait.Read.html#method.read_exact
397    ///
398    /// # Examples
399    ///
400    /// Read two signed 16 bit big-endian integers from a `Read`:
401    ///
402    /// ```rust
403    /// # use byteordered::ByteOrdered;
404    /// # fn run() -> std::io::Result<()> {
405    /// let mut out = [0; 2];
406    /// let mut rdr = ByteOrdered::be(&[0x00, 0xc1, 0xff, 0x7c][..]);
407    /// rdr.read_i16_into(&mut out)?;
408    /// assert_eq!(out, [193, -132]);
409    /// # Ok(())
410    /// # }
411    /// ```
412    #[inline]
413    pub fn read_i16_into(&mut self, dst: &mut [i16]) -> IoResult<()> {
414        self.endianness.read_i16_into(self.inner.by_ref(), dst)
415    }
416
417    /// Reads an unsigned 16 bit integer from the underlying reader.
418    ///
419    /// # Errors
420    ///
421    /// This method returns the same errors as [`Read::read_exact`].
422    ///
423    /// [`Read::read_exact`]: https://doc.rust-lang.org/std/io/trait.Read.html#method.read_exact
424    #[inline]
425    pub fn read_u16(&mut self) -> IoResult<u16> {
426        self.endianness.read_u16(self.inner.by_ref())
427    }
428
429    /// Reads a sequence of unsigned 16 bit integers from the underlying reader.
430    ///
431    /// The given buffer is either filled completely or an error is returned.
432    /// If an error is returned,
433    /// the contents of `dst` are unspecified.
434    ///
435    /// # Errors
436    ///
437    /// This method returns the same errors as [`Read::read_exact`].
438    ///
439    /// [`Read::read_exact`]: https://doc.rust-lang.org/std/io/trait.Read.html#method.read_exact
440    #[inline]
441    pub fn read_u16_into(&mut self, dst: &mut [u16]) -> IoResult<()> {
442        self.endianness.read_u16_into(self.inner.by_ref(), dst)
443    }
444
445    /// Reads a signed 32 bit integer from the underlying reader.
446    ///
447    /// # Errors
448    ///
449    /// This method returns the same errors as [`Read::read_exact`].
450    ///
451    /// [`Read::read_exact`]: https://doc.rust-lang.org/std/io/trait.Read.html#method.read_exact
452    #[inline]
453    pub fn read_i32(&mut self) -> IoResult<i32> {
454        self.endianness.read_i32(self.inner.by_ref())
455    }
456
457    /// Reads a sequence of signed 32 bit integers from the underlying reader.
458    ///
459    /// The given buffer is either filled completely or an error is returned.
460    /// If an error is returned,
461    /// the contents of `dst` are unspecified.
462    ///
463    /// # Errors
464    ///
465    /// This method returns the same errors as [`Read::read_exact`].
466    ///
467    /// [`Read::read_exact`]: https://doc.rust-lang.org/std/io/trait.Read.html#method.read_exact
468    #[inline]
469    pub fn read_i32_into(&mut self, dst: &mut [i32]) -> IoResult<()> {
470        self.endianness.read_i32_into(self.inner.by_ref(), dst)
471    }
472
473    /// Reads an unsigned 32 bit integer from the underlying reader.
474    ///
475    /// # Errors
476    ///
477    /// This method returns the same errors as [`Read::read_exact`].
478    ///
479    /// [`Read::read_exact`]: https://doc.rust-lang.org/std/io/trait.Read.html#method.read_exact
480    #[inline]
481    pub fn read_u32(&mut self) -> IoResult<u32> {
482        self.endianness.read_u32(self.inner.by_ref())
483    }
484
485    /// Reads a sequence of unsigned 32 bit integers from the underlying reader.
486    ///
487    /// The given buffer is either filled completely or an error is returned.
488    /// If an error is returned,
489    /// the contents of `dst` are unspecified.
490    ///
491    /// # Errors
492    ///
493    /// This method returns the same errors as [`Read::read_exact`].
494    ///
495    /// [`Read::read_exact`]: https://doc.rust-lang.org/std/io/trait.Read.html#method.read_exact
496    #[inline]
497    pub fn read_u32_into(&mut self, dst: &mut [u32]) -> IoResult<()> {
498        self.endianness.read_u32_into(self.inner.by_ref(), dst)
499    }
500
501    /// Reads a signed 64 bit integer from the underlying reader.
502    ///
503    /// # Errors
504    ///
505    /// This method returns the same errors as [`Read::read_exact`].
506    ///
507    /// [`Read::read_exact`]: https://doc.rust-lang.org/std/io/trait.Read.html#method.read_exact
508    #[inline]
509    pub fn read_i64(&mut self) -> IoResult<i64> {
510        self.endianness.read_i64(self.inner.by_ref())
511    }
512
513    /// Reads a sequence of signed 64 bit integers from the underlying reader.
514    ///
515    /// The given buffer is either filled completely or an error is returned.
516    /// If an error is returned,
517    /// the contents of `dst` are unspecified.
518    ///
519    /// # Errors
520    ///
521    /// This method returns the same errors as [`Read::read_exact`].
522    ///
523    /// [`Read::read_exact`]: https://doc.rust-lang.org/std/io/trait.Read.html#method.read_exact
524    #[inline]
525    pub fn read_i64_into(&mut self, dst: &mut [i64]) -> IoResult<()> {
526        self.endianness.read_i64_into(self.inner.by_ref(), dst)
527    }
528
529    /// Reads an unsigned 16 bit integer from the underlying reader.
530    ///
531    /// # Errors
532    ///
533    /// This method returns the same errors as [`Read::read_exact`].
534    ///
535    /// [`Read::read_exact`]: https://doc.rust-lang.org/std/io/trait.Read.html#method.read_exact
536    #[inline]
537    pub fn read_u64(&mut self) -> IoResult<u64> {
538        self.endianness.read_u64(self.inner.by_ref())
539    }
540
541    /// Reads a sequence of unsigned 64 bit integers from the underlying reader.
542    ///
543    /// The given buffer is either filled completely or an error is returned.
544    /// If an error is returned,
545    /// the contents of `dst` are unspecified.
546    ///
547    /// # Errors
548    ///
549    /// This method returns the same errors as [`Read::read_exact`].
550    ///
551    /// [`Read::read_exact`]: https://doc.rust-lang.org/std/io/trait.Read.html#method.read_exact
552    #[inline]
553    pub fn read_u64_into(&mut self, dst: &mut [u64]) -> IoResult<()> {
554        self.endianness.read_u64_into(self.inner.by_ref(), dst)
555    }
556
557    /// Reads a signed 128 bit integer from the underlying reader.
558    ///
559    /// # Errors
560    ///
561    /// This method returns the same errors as [`Read::read_exact`].
562    ///
563    /// [`Read::read_exact`]: https://doc.rust-lang.org/std/io/trait.Read.html#method.read_exact
564    #[inline]
565    pub fn read_i128(&mut self) -> IoResult<i128> {
566        self.endianness.read_i128(self.inner.by_ref())
567    }
568
569    /// Reads a sequence of signed 128 bit integers from the underlying reader.
570    ///
571    /// The given buffer is either filled completely or an error is returned.
572    /// If an error is returned,
573    /// the contents of `dst` are unspecified.
574    ///
575    /// # Errors
576    ///
577    /// This method returns the same errors as [`Read::read_exact`].
578    ///
579    /// [`Read::read_exact`]: https://doc.rust-lang.org/std/io/trait.Read.html#method.read_exact
580    #[inline]
581    pub fn read_i128_into(&mut self, dst: &mut [i128]) -> IoResult<()> {
582        self.endianness.read_i128_into(self.inner.by_ref(), dst)
583    }
584
585    /// Reads an unsigned 16 bit integer from the underlying reader.
586    ///
587    /// # Errors
588    ///
589    /// This method returns the same errors as [`Read::read_exact`].
590    ///
591    /// [`Read::read_exact`]: https://doc.rust-lang.org/std/io/trait.Read.html#method.read_exact
592    #[inline]
593    pub fn read_u128(&mut self) -> IoResult<u128> {
594        self.endianness.read_u128(self.inner.by_ref())
595    }
596
597    /// Reads a sequence of unsigned 128 bit integers from the underlying reader.
598    ///
599    /// The given buffer is either filled completely or an error is returned.
600    /// If an error is returned,
601    /// the contents of `dst` are unspecified.
602    ///
603    /// # Errors
604    ///
605    /// This method returns the same errors as [`Read::read_exact`].
606    ///
607    /// [`Read::read_exact`]: https://doc.rust-lang.org/std/io/trait.Read.html#method.read_exact
608    #[inline]
609    pub fn read_u128_into(&mut self, dst: &mut [u128]) -> IoResult<()> {
610        self.endianness.read_u128_into(self.inner.by_ref(), dst)
611    }
612
613    /// Reads a IEEE754 single-precision (4 bytes) floating point number from
614    /// the underlying reader.
615    ///
616    /// # Errors
617    ///
618    /// This method returns the same errors as [`Read::read_exact`].
619    ///
620    /// [`Read::read_exact`]: https://doc.rust-lang.org/std/io/trait.Read.html#method.read_exact
621    #[inline]
622    pub fn read_f32(&mut self) -> IoResult<f32> {
623        self.endianness.read_f32(self.inner.by_ref())
624    }
625
626    /// Reads a sequence of IEEE754 single-precision (4 bytes) floating point numbers
627    /// from the underlying reader.
628    ///
629    /// The given buffer is either filled completely or an error is returned.
630    /// If an error is returned,
631    /// the contents of `dst` are unspecified.
632    ///
633    /// # Errors
634    ///
635    /// This method returns the same errors as [`Read::read_exact`].
636    ///
637    /// [`Read::read_exact`]: https://doc.rust-lang.org/std/io/trait.Read.html#method.read_exact
638    #[inline]
639    pub fn read_f32_into(&mut self, dst: &mut [f32]) -> IoResult<()> {
640        self.endianness.read_f32_into(self.inner.by_ref(), dst)
641    }
642
643    /// Reads a IEEE754 double-precision (8 bytes) floating point number from
644    /// the underlying reader.
645    ///
646    /// # Errors
647    ///
648    /// This method returns the same errors as [`Read::read_exact`].
649    ///
650    /// [`Read::read_exact`]: https://doc.rust-lang.org/std/io/trait.Read.html#method.read_exact
651    #[inline]
652    pub fn read_f64(&mut self) -> IoResult<f64> {
653        self.endianness.read_f64(self.inner.by_ref())
654    }
655
656    /// Reads a sequence of IEEE754 double-precision (8 bytes) floating point numbers
657    /// from the underlying reader.
658    ///
659    /// The given buffer is either filled completely or an error is returned.
660    /// If an error is returned,
661    /// the contents of `dst` are unspecified.
662    ///
663    /// # Errors
664    ///
665    /// This method returns the same errors as [`Read::read_exact`].
666    ///
667    /// [`Read::read_exact`]: https://doc.rust-lang.org/std/io/trait.Read.html#method.read_exact
668    #[inline]
669    pub fn read_f64_into(&mut self, dst: &mut [f64]) -> IoResult<()> {
670        self.endianness.read_f64_into(self.inner.by_ref(), dst)
671    }
672}
673
674impl<W, E> ByteOrdered<W, E>
675where
676    W: WriteBytesExt,
677    E: Endian,
678{
679    /// Writes a signed 8 bit integer to the underlying writer.
680    ///
681    /// Note that since this writes a single byte, no byte order conversions
682    /// are used. It is included for completeness.
683    ///
684    /// # Errors
685    ///
686    /// This method returns the same errors as [`Write::write_all`].
687    ///
688    /// [`Write::write_all`]: https://doc.rust-lang.org/std/io/trait.Write.html#method.write_all
689    #[inline]
690    pub fn write_i8(&mut self, x: i8) -> IoResult<()> {
691        self.inner.write_i8(x)
692    }
693
694    /// Writes an unsigned 8 bit integer to the underlying writer.
695    ///
696    /// Note that since this writes a single byte, no byte order conversions
697    /// are used. It is included for completeness.
698    ///
699    /// # Errors
700    ///
701    /// This method returns the same errors as [`Write::write_all`].
702    ///
703    /// [`Write::write_all`]: https://doc.rust-lang.org/std/io/trait.Write.html#method.write_all
704    #[inline]
705    pub fn write_u8(&mut self, x: u8) -> IoResult<()> {
706        self.inner.write_u8(x)
707    }
708
709    /// Writes a signed 16 bit integer to the underlying writer.
710    ///
711    /// # Errors
712    ///
713    /// This method returns the same errors as [`Write::write_all`].
714    ///
715    /// [`Write::write_all`]: https://doc.rust-lang.org/std/io/trait.Write.html#method.write_all
716    ///
717    /// # Examples
718    ///
719    /// Write signed 16 bit big-endian integers to a `Write`:
720    ///
721    /// ```rust
722    /// use byteordered::ByteOrdered;
723    ///
724    /// let mut wtr = ByteOrdered::be(Vec::new());
725    /// wtr.write_i16(193).unwrap();
726    /// wtr.write_i16(-132).unwrap();
727    /// assert_eq!(wtr.into_inner(), b"\x00\xc1\xff\x7c");
728    /// ```
729    #[inline]
730    pub fn write_i16(&mut self, x: i16) -> IoResult<()> {
731        self.endianness.write_i16(self.inner.by_ref(), x)
732    }
733
734    /// Writes an unsigned 16 bit integer to the underlying writer.
735    ///
736    /// # Errors
737    ///
738    /// This method returns the same errors as [`Write::write_all`].
739    ///
740    /// [`Write::write_all`]: https://doc.rust-lang.org/std/io/trait.Write.html#method.write_all
741    #[inline]
742    pub fn write_u16(&mut self, x: u16) -> IoResult<()> {
743        self.endianness.write_u16(self.inner.by_ref(), x)
744    }
745
746    /// Writes a signed 32 bit integer to the underlying writer.
747    ///
748    /// # Errors
749    ///
750    /// This method returns the same errors as [`Write::write_all`].
751    ///
752    /// [`Write::write_all`]: https://doc.rust-lang.org/std/io/trait.Write.html#method.write_all
753    #[inline]
754    pub fn write_i32(&mut self, x: i32) -> IoResult<()> {
755        self.endianness.write_i32(self.inner.by_ref(), x)
756    }
757
758    /// Writes an unsigned 32 bit integer to the underlying writer.
759    ///
760    /// # Errors
761    ///
762    /// This method returns the same errors as [`Write::write_all`].
763    ///
764    /// [`Write::write_all`]: https://doc.rust-lang.org/std/io/trait.Write.html#method.write_all
765    #[inline]
766    pub fn write_u32(&mut self, x: u32) -> IoResult<()> {
767        self.endianness.write_u32(self.inner.by_ref(), x)
768    }
769
770    /// Writes a signed 64 bit integer to the underlying writer.
771    ///
772    /// # Errors
773    ///
774    /// This method returns the same errors as [`Write::write_all`].
775    ///
776    /// [`Write::write_all`]: https://doc.rust-lang.org/std/io/trait.Write.html#method.write_all
777    #[inline]
778    pub fn write_i64(&mut self, x: i64) -> IoResult<()> {
779        self.endianness.write_i64(self.inner.by_ref(), x)
780    }
781
782    /// Writes an unsigned 64 bit integer to the underlying writer.
783    ///
784    /// # Errors
785    ///
786    /// This method returns the same errors as [`Write::write_all`].
787    ///
788    /// [`Write::write_all`]: https://doc.rust-lang.org/std/io/trait.Write.html#method.write_all
789    #[inline]
790    pub fn write_u64(&mut self, x: u64) -> IoResult<()> {
791        self.endianness.write_u64(self.inner.by_ref(), x)
792    }
793
794    /// Writes a signed 128 bit integer to the underlying writer.
795    ///
796    /// # Errors
797    ///
798    /// This method returns the same errors as [`Write::write_all`].
799    ///
800    /// [`Write::write_all`]: https://doc.rust-lang.org/std/io/trait.Write.html#method.write_all
801    #[inline]
802    pub fn write_i128(&mut self, x: i128) -> IoResult<()> {
803        self.endianness.write_i128(self.inner.by_ref(), x)
804    }
805
806    /// Writes an unsigned 128 bit integer to the underlying writer.
807    ///
808    /// # Errors
809    ///
810    /// This method returns the same errors as [`Write::write_all`].
811    ///
812    /// [`Write::write_all`]: https://doc.rust-lang.org/std/io/trait.Write.html#method.write_all
813    #[inline]
814    pub fn write_u128(&mut self, x: u128) -> IoResult<()> {
815        self.endianness.write_u128(self.inner.by_ref(), x)
816    }
817
818    /// Writes a IEEE754 single-precision (4 bytes) floating point number to
819    /// the underlying writer.
820    ///
821    /// # Errors
822    ///
823    /// This method returns the same errors as [`Write::write_all`].
824    ///
825    /// [`Write::write_all`]: https://doc.rust-lang.org/std/io/trait.Write.html#method.write_all
826    #[inline]
827    pub fn write_f32(&mut self, x: f32) -> IoResult<()> {
828        self.endianness.write_f32(self.inner.by_ref(), x)
829    }
830
831    /// Writes a IEEE754 double-precision (8 bytes) floating point number to
832    /// the underlying writer.
833    ///
834    /// # Errors
835    ///
836    /// This method returns the same errors as [`Write::write_all`].
837    ///
838    /// [`Write::write_all`]: https://doc.rust-lang.org/std/io/trait.Write.html#method.write_all
839    #[inline]
840    pub fn write_f64(&mut self, x: f64) -> IoResult<()> {
841        self.endianness.write_f64(self.inner.by_ref(), x)
842    }
843}
844
845impl<T, E> BufRead for ByteOrdered<T, E>
846where
847    T: BufRead,
848{
849    #[inline]
850    fn fill_buf(&mut self) -> IoResult<&[u8]> {
851        self.inner.fill_buf()
852    }
853
854    #[inline]
855    fn consume(&mut self, amt: usize) {
856        self.inner.consume(amt)
857    }
858
859    #[inline]
860    fn read_until(&mut self, byte: u8, buf: &mut Vec<u8>) -> IoResult<usize> {
861        self.inner.read_until(byte, buf)
862    }
863
864    #[inline]
865    fn read_line(&mut self, buf: &mut String) -> IoResult<usize> {
866        self.inner.read_line(buf)
867    }
868}
869
870impl<T, E> Seek for ByteOrdered<T, E>
871where
872    T: Seek,
873{
874    #[inline]
875    fn seek(&mut self, pos: SeekFrom) -> IoResult<u64> {
876        self.inner.seek(pos)
877    }
878}
879
880#[cfg(test)]
881mod tests {
882    // TODO test moar
883    use super::ByteOrdered;
884    use base::Endianness;
885    static TEST_BYTES: &'static [u8] = &[0x12, 0x34, 0x56, 0x78, 0x21, 0x43, 0x65, 0x87];
886
887    static TEST_U64DATA_LE: &'static [u64] = &[0x87654321_78563412];
888    static TEST_U64DATA_BE: &'static [u64] = &[0x12345678_21436587];
889
890    #[test]
891    fn test_read_u64() {
892        let mut data = TEST_BYTES;
893        let mut reader = ByteOrdered::le(&mut data);
894        let words = [reader.read_u64().unwrap()];
895        assert_eq!(words, TEST_U64DATA_LE);
896
897        let mut data = TEST_BYTES;
898        let mut reader = ByteOrdered::be(&mut data);
899        let words = [reader.read_u64().unwrap()];
900        assert_eq!(words, TEST_U64DATA_BE);
901
902        let mut data = TEST_BYTES;
903        let mut reader = ByteOrdered::runtime(&mut data, Endianness::Little);
904        let words = [reader.read_u64().unwrap()];
905        assert_eq!(words, TEST_U64DATA_LE);
906
907        let mut data = TEST_BYTES;
908        let mut reader = ByteOrdered::runtime(&mut data, Endianness::Big);
909        let words = [reader.read_u64().unwrap()];
910        assert_eq!(words, TEST_U64DATA_BE);
911    }
912
913    #[test]
914    fn test_write_u64() {
915        let mut writer = ByteOrdered::le(Vec::new());
916        for v in TEST_U64DATA_LE {
917            writer.write_u64(*v).unwrap();
918        }
919        assert_eq!(&*writer.into_inner(), TEST_BYTES);
920
921        let mut writer = ByteOrdered::be(Vec::new());
922        for v in TEST_U64DATA_BE {
923            writer.write_u64(*v).unwrap();
924        }
925        assert_eq!(&*writer.into_inner(), TEST_BYTES);
926
927        let mut writer = ByteOrdered::runtime(Vec::new(), Endianness::Little);
928        for v in TEST_U64DATA_LE {
929            writer.write_u64(*v).unwrap();
930        }
931        assert_eq!(&*writer.into_inner(), TEST_BYTES);
932
933        let mut writer = ByteOrdered::runtime(Vec::new(), Endianness::Big);
934        for v in TEST_U64DATA_BE {
935            writer.write_u64(*v).unwrap();
936        }
937        assert_eq!(&*writer.into_inner(), TEST_BYTES);
938    }
939
940    /// the test bytes as two u32s in little endian
941    static TEST_U32DATA_LE: &'static [u32] = &[0x7856_3412, 0x8765_4321];
942    /// the test bytes as two u32s in big endian
943    static TEST_U32DATA_BE: &'static [u32] = &[0x1234_5678, 0x2143_6587];
944
945    #[test]
946    fn test_read_u32_into() {
947        let mut data = TEST_BYTES;
948        let mut reader = ByteOrdered::le(&mut data);
949        let mut words = [0; 2];
950        reader.read_u32_into(&mut words).unwrap();
951        assert_eq!(words, TEST_U32DATA_LE);
952
953        let mut data = TEST_BYTES;
954        let mut reader = ByteOrdered::be(&mut data);
955        let mut words = [0; 2];
956        reader.read_u32_into(&mut words).unwrap();
957        assert_eq!(words, TEST_U32DATA_BE);
958
959        let mut data = TEST_BYTES;
960        let mut reader = ByteOrdered::runtime(&mut data, Endianness::Little);
961        let mut words = [0; 2];
962        reader.read_u32_into(&mut words).unwrap();
963        assert_eq!(words, TEST_U32DATA_LE);
964
965        let mut data = TEST_BYTES;
966        let mut reader = ByteOrdered::runtime(&mut data, Endianness::Big);
967        let mut words = [0; 2];
968        reader.read_u32_into(&mut words).unwrap();
969        assert_eq!(words, TEST_U32DATA_BE);
970    }
971
972    #[test]
973    fn test_read_u32_and_set_endianness() {
974        let mut data = TEST_BYTES;
975        let mut reader = ByteOrdered::runtime(&mut data, Endianness::Little);
976        let v1 = reader.read_u32().unwrap();
977        assert_eq!(v1, TEST_U32DATA_LE[0]);
978
979        // change to big endian
980        reader.set_endianness(Endianness::Big);
981        let v2 = reader.read_u32().unwrap();
982        assert_eq!(v2, TEST_U32DATA_BE[1]);
983    }
984}