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}