byteio/
lib.rs

1//! # byteio
2//!
3//! byteio is a simple crate that exposes lightweight abstractions for
4//! read/write operations on contiguous slices of memory.
5//!
6//! The crate is based around two core traits: [`ReadBytes`][readbytes] and
7//! [`WriteBytes`][writebytes]. Two extension traits which add functionality for
8//! reading and writing numbers also have blanket implementations for any types
9//! that implement the core traits.
10//!
11//! [readbytes]: trait.ReadBytes.html
12//! [writebytes]: trait.WriteBytes.html
13//!
14//! # Installation
15//!
16//! To start using `byteio` add it to your `Cargo.toml` like so:
17//!
18//! ```toml
19//! [dependencies]
20//! byteio = "0.2"
21//! ```
22//!
23//! By default this will active the `std` feature which enables functionality in
24//! the crate which is only available when compiling with the standard library.
25//!
26//! To use the crate in a `no_std` environment you just need to disable this
27//! feature. This can be done by adjusting your `Cargo.toml`:
28//!
29//! ```toml
30//! [dependencies]
31//! byteio = { version = "0.2", default-features = false }
32//! ```
33//!
34//! The crate has a final feature: `alloc`. This should be used when you are
35//! building in a `no_std` environment, have an allocator, and want
36//! functionality for working with `Vec<u8>`. You can activate this by adjusting
37//! your `Cargo.toml` again:
38//!
39//! ```toml
40//! [dependencies]
41//! byteio = { version = "0.2", default-features = false, features = ["alloc"] }
42//! ```
43//!
44//! # Usage
45//!
46//! Manual serialization and deserialization of a simple network packet:
47//!
48//! ```
49//! use std::convert::TryInto;
50//!
51//! use byteio::prelude::*; // ReadBytes, ReadBytesExt, WriteBytes, WriteBytesExt
52//!
53//! /// A packet whose payload is encoded as `[n_msb, n_lsb, b_0, b_1, ..., b_n-1]`.
54//! struct Packet<'a> {
55//!    payload: &'a [u8],
56//! }
57//!
58//! impl<'a> Packet<'a> {
59//!     fn decode<R: ReadBytes<'a>>(mut reader: R) -> byteio::Result<Self> {
60//!         let len: usize = reader.try_read_u16_be()?.into();
61//!         let payload = reader.try_read_exact(len)?;
62//!
63//!         Ok(Self { payload })
64//!     }
65//!
66//!     fn encode<W: WriteBytes>(&self, mut writer: W) -> byteio::Result<()> {
67//!         let len: u16 = self.payload.len().try_into().unwrap_or_else(|_| !0);
68//!
69//!         writer.try_write_u16_be(len)?;
70//!         writer.try_write_exact(&self.payload[..usize::from(len)])?;
71//!
72//!         Ok(())
73//!     }
74//! }
75//!
76//! # #[cfg(any(feature = "std", feature = "alloc"))]
77//! fn main() -> byteio::Result<()> {
78//!     let data = b"\x00\x0Chello, world";
79//!
80//!     let packet = Packet::decode(&data[..])?;
81//!     assert_eq!(packet.payload, b"hello, world");
82//!
83//!     let mut buf = Vec::new();
84//!     packet.encode(&mut buf)?;
85//!     assert_eq!(&*buf, data);
86//!
87//!     Ok(())
88//! }
89//!
90//! # #[cfg(all(not(feature = "std"), not(feature = "alloc")))]
91//! # fn main() {}
92//! ```
93
94#![no_std]
95#![allow(clippy::cast_possible_wrap, clippy::cast_sign_loss)]
96#![deny(missing_docs)]
97
98use core::{fmt, marker::PhantomData, mem};
99
100#[cfg(feature = "std")]
101extern crate std;
102
103#[cfg(feature = "alloc")]
104extern crate alloc;
105
106#[cfg(feature = "std")]
107use std::{error, io, vec::Vec};
108
109#[cfg(feature = "alloc")]
110use alloc::vec::Vec;
111
112pub mod prelude {
113    //! The `byteio` prelude.
114    //!
115    //! ```
116    //! use byteio::prelude::*;
117    //! ```
118    //!
119    //! The purpose of this module is to alleviate imports by adding a glob
120    //! `use` to the top of `byteio` heavy modules.
121
122    pub use crate::{ReadBytes, ReadBytesExt, WriteBytes, WriteBytesExt};
123}
124
125/// A specialized [`Result`][core-result-result] type for `byteio` operations.
126///
127/// This type alias is broadly used across `byteio` for operations that may
128/// produce an error, that is, overflow the underlying buffer.
129///
130/// As with [`std::io::Result`][std-io-result], it is not recommended to import
131/// this type directly and shadow [`core::result::Result`](core-result-result),
132/// but instead to use `byteio::Result` to make it easier to distinguish.
133///
134/// # Examples
135///
136/// Trying to decode a string from raw bytes:
137///
138/// ```
139/// use core::str::{self, Utf8Error};
140///
141/// use byteio::WriteBytes;
142///
143/// fn decode_str(buf: &[u8]) -> Result<&str, Utf8Error> {
144///     str::from_utf8(buf)
145/// }
146///
147/// fn main() -> byteio::Result<()> {
148///     let mut buf = [0; 5];
149///
150///     (&mut buf[..]).try_write_exact(b"hello")?;
151///
152///     match decode_str(&buf) {
153///         Ok(s) => println!("str from utf8 success!"),
154///         Err(e) => println!("str from utf8 failure: {}", e),
155///     }
156///
157///     Ok(())
158/// }
159/// ```
160///
161/// [core-result-result]: https://doc.rust-lang.org/core/result/enum.Result.html
162/// [std-io-result]: https://doc.rust-lang.org/std/io/type.Result.html
163pub type Result<T> = ::core::result::Result<T, Error>;
164
165/// The errors that can occur during `byteio` operations.
166///
167/// When using the `std` feature of `byteio`, this type implements
168/// [`Into<std::io::Error>`][core-convert-into], which allows you to yield
169/// `byteio` errors with the `?` operator in functions which return
170/// [`std::io::Result`][std-io-result].
171///
172/// # Non-exhaustive
173///
174/// This enum is non-exhaustive; additional variants may be added in the future.
175///
176/// [core-convert-into]: https://doc.rust-lang.org/core/convert/trait.Into.html
177/// [std-io-result]: https://doc.rust-lang.org/std/io/type.Result.html
178#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
179pub enum Error {
180    /// The error returned when a `byteio` operation would overflow the buffer.
181    ///
182    /// # Examples
183    ///
184    /// ```
185    /// use byteio::{Error, WriteBytes};
186    ///
187    /// fn main() {
188    ///     let mut buf = [0; 2];
189    ///
190    ///     let err = (&mut buf[..]).try_write_exact(&[1, 1, 1]).unwrap_err();
191    ///     assert_eq!(err, Error::EndOfStream);
192    /// }
193    /// ```
194    EndOfStream,
195    #[doc(hidden)]
196    #[allow(non_camel_case_types)]
197    _nonexhaustive(()),
198}
199
200impl fmt::Display for Error {
201    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
202        match *self {
203            Error::EndOfStream => f.write_str("unexpected end of stream"),
204            _ => unreachable!(),
205        }
206    }
207}
208
209#[cfg(feature = "std")]
210impl error::Error for Error {}
211
212#[cfg(feature = "std")]
213impl From<Error> for io::Error {
214    fn from(error: Error) -> Self {
215        match error {
216            Error::EndOfStream => io::ErrorKind::UnexpectedEof.into(),
217            _ => unreachable!(),
218        }
219    }
220}
221
222/*
223 *
224 * ReadBytes
225 *
226 */
227
228/// Read a slice of bytes from a buffer.
229///
230/// Readers can be thought of as cursors that only allow you to seek forward
231/// from the current position. They can be implemented with one method;
232/// [`read_exact`][read-exact]. This forcibly attempts to split the underlying
233/// buffer in order to extract a sub-slice with a given length, and advance the
234/// buffer forward such that the next call to [`read_exact`][read-exact] will
235/// return subsequent bytes in the buffer.
236///
237/// The lifetime of the slices extracted are tied to the underlying buffer. This
238/// allows you to compose structures borrowing from the underlying buffer.
239///
240/// `ReadBytes` uses [`AsRef<[u8]>`][as-ref-u8] as a supertrait. This means that
241/// a generic reader can obtain its current length or peek at the underlying
242/// bytes without advancing the cursor through read operations. Note that by
243/// using [`as_ref`][as-ref] on a reader you discard the lifetime information of
244/// the underlying buffer for the returned reference.
245///
246/// # Examples
247///
248/// Reading from a slice:
249///
250/// ```
251/// use byteio::ReadBytes;
252///
253/// fn main() {
254///     let mut buf = &[1, 2, 3, 4, 5][..];
255///
256///     let sub_slice = buf.read_exact(2);
257///     assert_eq!(sub_slice, &[1, 2][..]);
258///
259///     let sub_slice = buf.read_exact(3);
260///     assert_eq!(sub_slice, &[3, 4, 5][..]);
261///
262///     assert!(buf.is_empty());
263/// }
264/// ```
265///
266/// Building a structure using borrowed data:
267///
268/// ```
269/// use core::str;
270///
271/// use byteio::ReadBytes;
272///
273/// /// A packet whose payload is encoded as `[n, b0, b1, ..., bn-1]`.
274/// struct Packet<'a> {
275///     payload: &'a [u8],
276/// }
277///
278/// impl<'a> Packet<'a> {
279///     pub fn new<R: ReadBytes<'a>>(mut r: R) -> byteio::Result<Self> {
280///         let len: usize = r.try_read_exact(1)?[0].into();
281///         let payload = r.try_read_exact(len)?;
282///
283///         Ok(Self { payload })
284///     }
285/// }
286///
287/// fn main() -> byteio::Result<()> {
288///     let buf = b"\x05hello";
289///     
290///     let packet = Packet::new(&buf[..])?;
291///     assert_eq!(str::from_utf8(packet.payload).unwrap(), "hello");
292///
293///     Ok(())
294/// }
295/// ```
296///
297/// [read-exact]: trait.ReadBytes.html#tymethod.read_exact
298/// [as-ref-u8]: https://doc.rust-lang.org/core/convert/trait.AsRef.html
299/// [as-ref]: https://doc.rust-lang.org/core/convert/trait.AsRef.html#tymethod.as_ref
300pub trait ReadBytes<'a>: AsRef<[u8]> {
301    /// Forcibly attempts to read exactly `n` bytes from the buffer.
302    ///
303    /// # Panics
304    ///
305    /// Panics if there are not enough bytes in `self`.
306    fn read_exact(&mut self, n: usize) -> &'a [u8];
307
308    /// Attempts to read exactly `n` bytes from the buffer.
309    ///
310    /// If there are not enough bytes in `self` this function will return
311    /// `Error::EndOfStream`.
312    fn try_read_exact(&mut self, n: usize) -> crate::Result<&'a [u8]> {
313        if n > self.as_ref().len() {
314            Err(Error::EndOfStream)
315        } else {
316            Ok(self.read_exact(n))
317        }
318    }
319}
320
321impl<'a> ReadBytes<'a> for &'a [u8] {
322    fn read_exact(&mut self, n: usize) -> &'a [u8] {
323        let (a, b) = self.split_at(n);
324        *self = b;
325        a
326    }
327}
328
329impl<'a> ReadBytes<'a> for &'a mut [u8] {
330    fn read_exact(&mut self, n: usize) -> &'a [u8] {
331        let (a, b) = mem::replace(self, &mut []).split_at_mut(n);
332        *self = b;
333        a
334    }
335}
336
337impl<'a, R: ReadBytes<'a>> ReadBytes<'a> for &'_ mut R {
338    fn read_exact(&mut self, n: usize) -> &'a [u8] {
339        (**self).read_exact(n)
340    }
341
342    fn try_read_exact(&mut self, n: usize) -> crate::Result<&'a [u8]> {
343        (**self).try_read_exact(n)
344    }
345}
346
347/*
348 *
349 * ReadBytesExt
350 *
351 */
352
353macro_rules! impl_read {
354    ($doc:literal, $ty:ty, $fn:ident, $from_bytes:ident $( , )?) => {
355        #[doc = $doc]
356        #[inline]
357        fn $fn(&mut self) -> $ty {
358            <$ty>::$from_bytes(unsafe {
359                *(self.read_exact(mem::size_of::<$ty>()).as_ptr()
360                    as *const [u8; mem::size_of::<$ty>()])
361            })
362        }
363    }
364}
365
366macro_rules! impl_try_read {
367    ($doc:literal, $ty:ty, $fn:ident, $from_bytes:ident $( , )?) => {
368        #[doc = $doc]
369        #[inline]
370        fn $fn(&mut self) -> crate::Result<$ty> {
371            Ok(<$ty>::$from_bytes(unsafe {
372                *(self.try_read_exact(mem::size_of::<$ty>())?.as_ptr()
373                    as *const [u8; mem::size_of::<$ty>()])
374            }))
375        }
376    }
377}
378
379/// Extends `ReadBytes` with functions for reading numbers.
380///
381/// # Examples
382///
383/// Read a `u16` from a buffer using native endianness:
384///
385/// ```
386/// use byteio::ReadBytesExt;
387///
388/// fn main() {
389///     let mut buf: &[u8] = &[0, 1];
390///
391///     #[cfg(target_endian = "little")]
392///     let a = buf.read_u16_le();
393///     #[cfg(target_endian = "big")]
394///     let a = buf.read_u16_be();
395///
396///     assert!(buf.is_empty());
397/// }
398/// ```
399pub trait ReadBytesExt<'a>: ReadBytes<'a> {
400    /// Reads a `u8` from the underlying buffer.
401    ///
402    /// # Panics
403    ///
404    /// Panics if there are not enough bytes in `self`.
405    fn read_u8(&mut self) -> u8 {
406        self.read_exact(1)[0]
407    }
408
409    /// Attempts to read a `u8` from the underlying buffer.
410    ///
411    /// If there are not enough bytes in `self` this function will return
412    /// `Error::EndOfStream`.
413    fn try_read_u8(&mut self) -> crate::Result<u8> {
414        Ok(self.try_read_exact(1)?[0])
415    }
416
417    /// Reads an `i8` from the underlying buffer.
418    ///
419    /// # Panics
420    ///
421    /// Panics if there are not enough bytes in `self`.
422    fn read_i8(&mut self) -> i8 {
423        self.read_exact(1)[0] as _
424    }
425
426    /// Attempts to read an `i8` from the underlying buffer.
427    ///
428    /// If there are not enough bytes in `self` this function will return
429    /// `Error::EndOfStream`.
430    fn try_read_i8(&mut self) -> crate::Result<i8> {
431        Ok(self.try_read_exact(1)?[0] as _)
432    }
433
434    impl_read! {
435"Reads a little endian `u16` from the underlying buffer.
436
437# Panics
438
439Panics if there are not enough bytes in `self`.",
440        u16,
441        read_u16_le,
442        from_le_bytes,
443    }
444
445    impl_read! {
446"Reads a big endian `u16` from the underlying buffer.
447
448# Panics
449
450Panics if there are not enough bytes in `self`.",
451        u16,
452        read_u16_be,
453        from_be_bytes,
454    }
455
456    impl_try_read! {
457"Attempts to read a little endian `u16` from the underlying buffer.
458
459If there are not enough bytes in `self` this function will return `Error::EndOfStream`.",
460        u16,
461        try_read_u16_le,
462        from_le_bytes,
463    }
464
465    impl_try_read! {
466"Attempts to read a big endian `u16` from the underlying buffer.
467
468If there are not enough bytes in `self` this function will return `Error::EndOfStream`.",
469        u16,
470        try_read_u16_be,
471        from_be_bytes,
472    }
473
474    impl_read! {
475"Reads a little endian `i16` from the underlying buffer.
476
477# Panics
478
479Panics if there are not enough bytes in `self`.",
480        i16,
481        read_i16_le,
482        from_le_bytes,
483    }
484
485    impl_read! {
486"Reads a big endian `i16` from the underlying buffer.
487
488# Panics
489
490Panics if there are not enough bytes in `self`.",
491        i16,
492        read_i16_be,
493        from_be_bytes,
494    }
495
496    impl_try_read! {
497"Attempts to read a little endian `i16` from the underlying buffer.
498
499If there are not enough bytes in `self` this function will return `Error::EndOfStream`.",
500        i16,
501        try_read_i16_le,
502        from_le_bytes,
503    }
504
505    impl_try_read! {
506"Attempts to read a little endian `i16` from the underlying buffer.
507
508If there are not enough bytes in `self` this function will return `Error::EndOfStream`.",
509        i16,
510        try_read_i16_be,
511        from_be_bytes,
512    }
513
514    impl_read! {
515"Reads a little endian `u32` from the underlying buffer.
516
517# Panics
518
519Panics if there are not enough bytes in `self`.",
520        u32,
521        read_u32_le,
522        from_le_bytes,
523    }
524
525    impl_read! {
526"Reads a big endian `u32` from the underlying buffer.
527
528# Panics
529
530Panics if there are not enough bytes in `self`.",
531        u32,
532        read_u32_be,
533        from_be_bytes,
534    }
535
536    impl_try_read! {
537"Attempts to read a little endian `u32` from the underlying buffer.
538
539If there are not enough bytes in `self` this function will return `Error::EndOfStream`.",
540        u32,
541        try_read_u32_le,
542        from_le_bytes,
543    }
544
545    impl_try_read! {
546"Attempts to read a big endian `u32` from the underlying buffer.
547
548If there are not enough bytes in `self` this function will return `Error::EndOfStream`.",
549        u32,
550        try_read_u32_be,
551        from_be_bytes,
552    }
553
554    impl_read! {
555"Reads a little endian `i32` from the underlying buffer.
556
557# Panics
558
559Panics if there are not enough bytes in `self`.",
560        i32,
561        read_i32_le,
562        from_le_bytes,
563    }
564
565    impl_read! {
566"Reads a big endian `i32` from the underlying buffer.
567
568# Panics
569
570Panics if there are not enough bytes in `self`.",
571        i32,
572        read_i32_be,
573        from_be_bytes,
574    }
575
576    impl_try_read! {
577"Attempts to read a little endian `i32` from the underlying buffer.
578
579If there are not enough bytes in `self` this function will return `Error::EndOfStream`.",
580        i32,
581        try_read_i32_le,
582        from_le_bytes,
583    }
584
585    impl_try_read! {
586"Attempts to read a big endian `i32` from the underlying buffer.
587
588If there are not enough bytes in `self` this function will return `Error::EndOfStream`.",
589        i32,
590        try_read_i32_be,
591        from_be_bytes,
592    }
593
594    impl_read! {
595"Reads a little endian `u64` from the underlying buffer.
596
597# Panics
598
599Panics if there are not enough bytes in `self`.",
600        u64,
601        read_u64_le,
602        from_le_bytes,
603    }
604
605    impl_read! {
606"Reads a big endian `u64` from the underlying buffer.
607
608# Panics
609
610Panics if there are not enough bytes in `self`.",
611        u64,
612        read_u64_be,
613        from_be_bytes,
614    }
615
616    impl_try_read! {
617"Attempts to read a little endian `u64` from the underlying buffer.
618
619If there are not enough bytes in `self` this function will return `Error::EndOfStream`.",
620        u64,
621        try_read_u64_le,
622        from_le_bytes,
623    }
624
625    impl_try_read! {
626"Attempts to read a big endian `u64` from the underlying buffer.
627
628If there are not enough bytes in `self` this function will return `Error::EndOfStream`.",
629        u64,
630        try_read_u64_be,
631        from_be_bytes,
632    }
633
634    impl_read! {
635"Reads a little endian `i64` from the underlying buffer.
636
637# Panics
638
639Panics if there are not enough bytes in `self`.",
640        i64,
641        read_i64_le,
642        from_le_bytes,
643    }
644
645    impl_read! {
646"Reads a big endian `i64` from the underlying buffer.
647
648# Panics
649
650Panics if there are not enough bytes in `self`.",
651        i64,
652        read_i64_be,
653        from_be_bytes,
654    }
655
656    impl_try_read! {
657"Attempts to read a little endian `i64` from the underlying buffer.
658
659If there are not enough bytes in `self` this function will return `Error::EndOfStream`.",
660        i64,
661        try_read_i64_le,
662        from_le_bytes,
663    }
664
665    impl_try_read! {
666"Attempts to read a big endian `i64` from the underlying buffer.
667
668If there are not enough bytes in `self` this function will return `Error::EndOfStream`.",
669        i64,
670        try_read_i64_be,
671        from_be_bytes,
672    }
673
674    impl_read! {
675"Reads a little endian `u128` from the underlying buffer.
676
677# Panics
678
679Panics if there are not enough bytes in `self`.",
680        u128,
681        read_u128_le,
682        from_le_bytes,
683    }
684
685    impl_read! {
686"Reads a big endian `u128` from the underlying buffer.
687
688# Panics
689
690Panics if there are not enough bytes in `self`.",
691        u128,
692        read_u128_be,
693        from_be_bytes,
694    }
695
696    impl_try_read! {
697"Attempts to read a little endian `u128` from the underlying buffer.
698
699If there are not enough bytes in `self` this function will return `Error::EndOfStream`.",
700        u128,
701        try_read_u128_le,
702        from_le_bytes,
703    }
704
705    impl_try_read! {
706"Attempts to read a big endian `u128` from the underlying buffer.
707
708If there are not enough bytes in `self` this function will return `Error::EndOfStream`.",
709        u128,
710        try_read_u128_be,
711        from_be_bytes,
712    }
713
714    impl_read! {
715"Reads a little endian `i128` from the underlying buffer.
716
717# Panics
718
719Panics if there are not enough bytes in `self`.",
720        i128,
721        read_i128_le,
722        from_le_bytes,
723    }
724
725    impl_read! {
726"Reads a big endian `i128` from the underlying buffer.
727
728# Panics
729
730Panics if there are not enough bytes in `self`.",
731        i128,
732        read_i128_be,
733        from_be_bytes,
734    }
735
736    impl_try_read! {
737"Attempts to read a little endian `i128` from the underlying buffer.
738
739If there are not enough bytes in `self` this function will return `Error::EndOfStream`.",
740        i128,
741        try_read_i128_le,
742        from_le_bytes,
743    }
744
745    impl_try_read! {
746"Attempts to read a big endian `i128` from the underlying buffer.
747
748If there are not enough bytes in `self` this function will return `Error::EndOfStream`.",
749        i128,
750        try_read_i128_be,
751        from_be_bytes,
752    }
753
754    /// Reads a little endian IEEE754 `f32` from the underlying buffer.
755    ///
756    /// # Panics
757    ///
758    /// Panics if there are not enough bytes in `self`.
759    fn read_f32_le(&mut self) -> f32 {
760        f32::from_bits(self.read_u32_le())
761    }
762
763    /// Reads a big endian IEEE754 `f32` from the underlying buffer.
764    ///
765    /// # Panics
766    ///
767    /// Panics if there are not enough bytes in `self`.
768    fn read_f32_be(&mut self) -> f32 {
769        f32::from_bits(self.read_u32_be())
770    }
771
772    /// Attempts to read a little endian IEEE754 `f32` from the underlying
773    /// buffer.
774    ///
775    /// If there are not enough bytes in `self` this function will return
776    /// `Error::EndOfStream`.
777    fn try_read_f32_le(&mut self) -> crate::Result<f32> {
778        Ok(f32::from_bits(self.try_read_u32_le()?))
779    }
780
781    /// Attempts to read a big endian IEEE754 `f32` from the underlying buffer.
782    ///
783    /// If there are not enough bytes in `self` this function will return
784    /// `Error::EndOfStream`.
785    fn try_read_f32_be(&mut self) -> crate::Result<f32> {
786        Ok(f32::from_bits(self.try_read_u32_be()?))
787    }
788
789    /// Reads a little endian IEEE754 `f64` from the underlying buffer.
790    ///
791    /// # Panics
792    ///
793    /// Panics if there are not enough bytes in `self`.
794    fn read_f64_le(&mut self) -> f64 {
795        f64::from_bits(self.read_u64_le())
796    }
797
798    /// Reads a big endian IEEE754 `f64` from the underlying buffer.
799    ///
800    /// # Panics
801    ///
802    /// Panics if there are not enough bytes in `self`.
803    fn read_f64_be(&mut self) -> f64 {
804        f64::from_bits(self.read_u64_be())
805    }
806
807    /// Attempts to read a little endian IEEE754 `f64` from the underlying
808    /// buffer.
809    ///
810    /// If there are not enough bytes in `self` this function will return
811    /// `Error::EndOfStream`.
812    fn try_read_f64_le(&mut self) -> crate::Result<f64> {
813        Ok(f64::from_bits(self.try_read_u64_le()?))
814    }
815
816    /// Attempts to read a big endian IEEE754 `f64` from the underlying buffer.
817    ///
818    /// If there are not enough bytes in `self` this function will return
819    /// `Error::EndOfStream`.
820    fn try_read_f64_be(&mut self) -> crate::Result<f64> {
821        Ok(f64::from_bits(self.try_read_u64_be()?))
822    }
823}
824
825impl<'a, R: ReadBytes<'a>> ReadBytesExt<'a> for R {}
826
827/*
828 *
829 * Reader
830 *
831 */
832
833/// A convenience structure used for counting the number of bytes read.
834///
835/// This structure wraps an implementation of [`ReadBytes`][readbytes]. It
836/// forwards read operations to the inner type while also maintaining a count
837/// of the number of bytes that pass through it.
838///
839/// When you have finished with it, you can return the original type via the
840/// [`into_inner`][into-inner] method.
841///
842/// When compiled with the `std` feature this structure implements
843/// [`Read`][std-io-read].
844///
845/// [std-io-read]: https://doc.rust-lang.org/std/io/trait.Read.html
846///
847/// # Examples
848///
849/// ```
850/// use byteio::{ReadBytes, ReadBytesExt, Reader};
851///
852/// fn main() -> byteio::Result<()> {
853///     let buf: &[u8] = &[1, 0, 2, 0, 0, 0, 3];
854///
855///     let mut reader = Reader::new(buf);
856///
857///     assert_eq!(reader.try_read_u8()?, 1);
858///     assert_eq!(reader.try_read_u16_be()?, 2);
859///     assert_eq!(reader.try_read_u32_be()?, 3);
860///
861///     assert_eq!(reader.num_bytes_read(), 7);
862///
863///     let inner = reader.into_inner();
864///     assert!(inner.is_empty());
865///
866///     Ok(())
867/// }
868/// ```
869///
870/// [readbytes]: trait.ReadBytes.html
871/// [into-inner]: struct.Reader.html#method.into_inner
872#[derive(Debug, Clone, Eq, PartialEq)]
873pub struct Reader<'a, R: ReadBytes<'a>>(R, usize, PhantomData<&'a ()>);
874
875impl<'a, R: ReadBytes<'a>> Reader<'a, R> {
876    /// Creates a new `Reader` by wrapping a [`ReadBytes`][readbytes]
877    /// implementor.
878    ///
879    /// # Examples
880    ///
881    /// ```
882    /// use byteio::Reader;
883    ///
884    /// let buf = [0_u8; 2];
885    /// let mut reader = Reader::new(&buf[..]);
886    /// ```
887    ///
888    /// [readbytes]: trait.ReadBytes.html
889    #[inline]
890    pub fn new(reader: R) -> Self {
891        Self(reader, 0, PhantomData)
892    }
893
894    /// Retrieves the number of bytes that have been read by this `Reader`.
895    ///
896    /// # Examples
897    ///
898    /// ```
899    /// use byteio::{ReadBytes, Reader};
900    ///
901    /// let buf = [0_u8; 2];
902    /// let mut reader = Reader::new(&buf[..]);
903    /// let _ = reader.read_exact(1);
904    /// let _ = reader.read_exact(1);
905    ///
906    /// assert_eq!(reader.num_bytes_read(), 2);
907    /// ```
908    #[inline]
909    pub fn num_bytes_read(&self) -> usize {
910        self.1
911    }
912
913    /// Consumes this `Reader` and returns the original [`ReadBytes`][readbytes]
914    /// implementor.
915    ///
916    /// # Examples
917    ///
918    /// ```
919    /// use byteio::{ReadBytes, Reader};
920    ///
921    /// let buf = [0_u8; 2];
922    /// let mut reader = Reader::new(&buf[..]);
923    /// let _ = reader.read_exact(1);
924    /// let inner = reader.into_inner();
925    ///
926    /// assert_eq!(inner.len(), 1); // the reader consumed one byte from its view of the slice
927    /// ```
928    ///
929    /// [readbytes]: trait.ReadBytes.html
930    #[inline]
931    pub fn into_inner(self) -> R {
932        self.0
933    }
934}
935
936impl<'a, R: ReadBytes<'a>> AsRef<[u8]> for Reader<'a, R> {
937    fn as_ref(&self) -> &[u8] {
938        self.0.as_ref()
939    }
940}
941
942impl<'a, R: ReadBytes<'a>> ReadBytes<'a> for Reader<'a, R> {
943    fn read_exact(&mut self, n: usize) -> &'a [u8] {
944        self.1 += n;
945        self.0.read_exact(n)
946    }
947
948    fn try_read_exact(&mut self, n: usize) -> crate::Result<&'a [u8]> {
949        match self.0.try_read_exact(n) {
950            res @ Ok(_) => {
951                self.1 += n;
952                res
953            }
954            res @ Err(_) => res,
955        }
956    }
957}
958
959#[cfg(feature = "std")]
960impl<'a, R: ReadBytes<'a>> io::Read for Reader<'a, R> {
961    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
962        let n = ::core::cmp::min(buf.len(), self.as_ref().len());
963        buf[..n].copy_from_slice(<Self as ReadBytes>::read_exact(self, n));
964
965        Ok(n)
966    }
967}
968
969/*
970 *
971 * WriteBytes
972 *
973 */
974
975/// Write a slice of bytes into a buffer.
976///
977/// Writers can be thought of as mutable cursors that only allow you to seek
978/// forward from the current position. They can be implemented with one method;
979/// [`write_exact`][write-exact]. This forcibly attempts to writer the bytes
980/// to the underlying buffer, and advance the buffer forward such that the next
981/// call to [`write_exact`][write-exact] will commit the bytes directly after
982/// those previously written.
983///
984/// `WriteBytes` uses [`AsMut<[u8]>`][as-mut-u8] as a supertrait. This means
985/// that a generic writer can obtain its current length or mutably peek at the
986/// underlying bytes without advancing the cursor through write operations.
987///
988/// # Examples
989///
990/// Writing into a slice:
991///
992/// ```
993/// use byteio::WriteBytes;
994///
995/// fn main() -> byteio::Result<()> {
996///     let mut buf = [0; 8];
997///
998///     {
999///         let mut buf = &mut buf[..];
1000///
1001///         buf.try_write_exact(&[1, 2])?;
1002///         assert_eq!(buf.len(), 6);
1003///
1004///         buf.try_write_exact(&[3, 4, 5, 6, 7])?;
1005///         assert_eq!(buf.len(), 1);
1006///
1007///         buf.try_write_exact(&[8])?;
1008///         assert!(buf.is_empty());
1009///     }
1010///
1011///     assert_eq!(buf, [1, 2, 3, 4, 5, 6, 7, 8]);
1012///     Ok(())
1013/// }
1014/// ```
1015///
1016/// [write-exact]: trait.WriteBytes.html#tymethod.write_exact
1017/// [as-mut-u8]: https://doc.rust-lang.org/core/convert/trait.AsMut.html
1018pub trait WriteBytes: AsMut<[u8]> {
1019    /// Forcibly attempts to write the exact slice into the buffer.
1020    ///
1021    /// # Panics
1022    ///
1023    /// Panics if there are not enough bytes in `self`.
1024    fn write_exact(&mut self, buf: &[u8]);
1025
1026    /// Attempts to write the exact slice into the buffer.
1027    ///
1028    /// If there are not enough bytes in `self` this function will return
1029    /// `Error::EndOfStream`.
1030    fn try_write_exact(&mut self, buf: &[u8]) -> crate::Result<()> {
1031        if buf.len() > self.as_mut().len() {
1032            Err(Error::EndOfStream)
1033        } else {
1034            self.write_exact(buf);
1035            Ok(())
1036        }
1037    }
1038}
1039
1040impl WriteBytes for &'_ mut [u8] {
1041    fn write_exact(&mut self, buf: &[u8]) {
1042        let (a, b) = mem::replace(self, &mut []).split_at_mut(buf.len());
1043        a.copy_from_slice(&buf);
1044        *self = b;
1045    }
1046}
1047
1048#[cfg(any(feature = "std", feature = "alloc"))]
1049impl WriteBytes for Vec<u8> {
1050    fn write_exact(&mut self, buf: &[u8]) {
1051        self.extend_from_slice(buf);
1052    }
1053
1054    fn try_write_exact(&mut self, buf: &[u8]) -> crate::Result<()> {
1055        self.write_exact(buf);
1056        Ok(())
1057    }
1058}
1059
1060impl<W: WriteBytes> WriteBytes for &'_ mut W {
1061    fn write_exact(&mut self, buf: &[u8]) {
1062        (**self).write_exact(buf)
1063    }
1064
1065    fn try_write_exact(&mut self, buf: &[u8]) -> crate::Result<()> {
1066        (**self).try_write_exact(buf)
1067    }
1068}
1069
1070/*
1071 *
1072 * WriteBytesExt
1073 *
1074 */
1075
1076macro_rules! impl_write {
1077    ($doc:literal, $ty:ty, $fn:ident, $to_bytes:ident $( , )?) => {
1078        #[doc = $doc]
1079        #[inline]
1080        fn $fn(&mut self, n: $ty) {
1081            self.write_exact(&n.$to_bytes()[..]);
1082        }
1083    }
1084}
1085
1086macro_rules! impl_try_write {
1087    ($doc:literal, $ty:ty, $fn:ident, $to_bytes:ident $( , )?) => {
1088        #[doc = $doc]
1089        #[inline]
1090        fn $fn(&mut self, n: $ty) -> crate::Result<()> {
1091            self.try_write_exact(&n.$to_bytes()[..])?;
1092            Ok(())
1093        }
1094    }
1095}
1096
1097/// Extends `WriteBytes` with functions for writing numbers.
1098///
1099/// # Examples
1100///
1101/// Write a `u16` into a buffer using native endianness:
1102///
1103/// ```
1104/// use byteio::WriteBytesExt;
1105///
1106/// fn main() {
1107///     let mut buf = [0; 2];
1108///
1109///     {
1110///         let mut buf: &mut [u8] = &mut buf;
1111///
1112///         #[cfg(target_endian = "little")]
1113///         buf.write_u16_le(256);
1114///         #[cfg(target_endian = "big")]
1115///         buf.write_u16_be(256);
1116///
1117///         assert!(buf.is_empty());
1118///     }
1119/// }
1120/// ```
1121pub trait WriteBytesExt: WriteBytes {
1122    /// Writes a `u8` into the underlying buffer.
1123    ///
1124    /// # Panics
1125    ///
1126    /// Panics if there are not enough bytes in `self`.
1127    #[inline]
1128    fn write_u8(&mut self, n: u8) {
1129        self.write_exact(&[n]);
1130    }
1131
1132    /// Attempts to write a `u8` into the underlying buffer.
1133    ///
1134    /// If there are not enough bytes in `self` this function will return
1135    /// `Error::EndOfStream`.
1136    #[inline]
1137    fn try_write_u8(&mut self, n: u8) -> crate::Result<()> {
1138        self.try_write_exact(&[n])?;
1139        Ok(())
1140    }
1141
1142    /// Writes an `i8` into the underlying buffer.
1143    ///
1144    /// # Panics
1145    ///
1146    /// Panics if there are not enough bytes in `self`.
1147    #[inline]
1148    fn write_i8(&mut self, n: i8) {
1149        self.write_exact(&[n as _]);
1150    }
1151
1152    /// Attempts to write an `i8` into the underlying buffer.
1153    ///
1154    /// If there are not enough bytes in `self` this function will return
1155    /// `Error::EndOfStream`.
1156    #[inline]
1157    fn try_write_i8(&mut self, n: i8) -> crate::Result<()> {
1158        self.try_write_exact(&[n as _])?;
1159        Ok(())
1160    }
1161
1162    impl_write! {
1163"Writes a `u16` into the underlying buffer in little endian byte order.
1164
1165# Panics
1166
1167Panics if there are not enough bytes in `self`.",
1168        u16,
1169        write_u16_le,
1170        to_le_bytes,
1171    }
1172
1173    impl_write! {
1174"Writes a `u16` into the underlying buffer in big endian byte order.
1175
1176# Panics
1177
1178Panics if there are not enough bytes in `self`.",
1179        u16,
1180        write_u16_be,
1181        to_be_bytes,
1182    }
1183
1184    impl_try_write! {
1185"Attempts to write a `u16` into the underlying buffer in little endian byte order.
1186
1187If there are not enough bytes in `self` this function will return `Error::EndOfStream`.",
1188        u16,
1189        try_write_u16_le,
1190        to_le_bytes,
1191    }
1192
1193    impl_try_write! {
1194"Attempts to write a `u16` into the underlying buffer in big endian byte order.
1195
1196If there are not enough bytes in `self` this function will return `Error::EndOfStream`.",
1197        u16,
1198        try_write_u16_be,
1199        to_be_bytes,
1200    }
1201
1202    impl_write! {
1203"Writes an `i16` into the underlying buffer in little endian byte order.
1204
1205# Panics
1206
1207Panics if there are not enough bytes in `self`.",
1208        i16,
1209        write_i16_le,
1210        to_le_bytes,
1211    }
1212
1213    impl_write! {
1214"Writes an `i16` into the underlying buffer in big endian byte order.
1215
1216# Panics
1217
1218Panics if there are not enough bytes in `self`.",
1219        i16,
1220        write_i16_be,
1221        to_be_bytes,
1222    }
1223
1224    impl_try_write! {
1225"Attempts to write an `i16` into the underlying buffer in little endian byte order.
1226
1227If there are not enough bytes in `self` this function will return `Error::EndOfStream`.",
1228        i16,
1229        try_write_i16_le,
1230        to_le_bytes,
1231    }
1232
1233    impl_try_write! {
1234"Attempts to write an `i16` into the underlying buffer in big endian byte order.
1235
1236If there are not enough bytes in `self` this function will return `Error::EndOfStream`.",
1237        i16,
1238        try_write_i16_be,
1239        to_be_bytes,
1240    }
1241
1242    impl_write! {
1243"Writes a `u32` into the underlying buffer in little endian byte order.
1244
1245# Panics
1246
1247Panics if there are not enough bytes in `self`.",
1248        u32,
1249        write_u32_le,
1250        to_le_bytes,
1251    }
1252
1253    impl_write! {
1254"Writes a `u32` into the underlying buffer in big endian byte order.
1255
1256# Panics
1257
1258Panics if there are not enough bytes in `self`.",
1259        u32,
1260        write_u32_be,
1261        to_be_bytes,
1262    }
1263
1264    impl_try_write! {
1265"Attempts to write a `u32` into the underlying buffer in little endian byte order.
1266
1267If there are not enough bytes in `self` this function will return `Error::EndOfStream`.",
1268        u32,
1269        try_write_u32_le,
1270        to_le_bytes,
1271    }
1272
1273    impl_try_write! {
1274"Attempts to write a `u32` into the underlying buffer in big endian byte order.
1275
1276If there are not enough bytes in `self` this function will return `Error::EndOfStream`.",
1277        u32,
1278        try_write_u32_be,
1279        to_be_bytes,
1280    }
1281
1282    impl_write! {
1283"Writes an `i32` into the underlying buffer in little endian byte order.
1284
1285# Panics
1286
1287Panics if there are not enough bytes in `self`.",
1288        i32,
1289        write_i32_le,
1290        to_le_bytes,
1291    }
1292
1293    impl_write! {
1294"Writes an `i32` into the underlying buffer in big endian byte order.
1295
1296# Panics
1297
1298Panics if there are not enough bytes in `self`.",
1299        i32,
1300        write_i32_be,
1301        to_be_bytes,
1302    }
1303
1304    impl_try_write! {
1305"Attempts to write an `i32` into the underlying buffer in little endian byte order.
1306
1307If there are not enough bytes in `self` this function will return `Error::EndOfStream`.",
1308        i32,
1309        try_write_i32_le,
1310        to_le_bytes,
1311    }
1312
1313    impl_try_write! {
1314"Attempts to write an `i32` into the underlying buffer in big endian byte order.
1315
1316If there are not enough bytes in `self` this function will return `Error::EndOfStream`.",
1317        i32,
1318        try_write_i32_be,
1319        to_be_bytes,
1320    }
1321
1322    impl_write! {
1323"Writes a `u64` into the underlying buffer in little endian byte order.
1324
1325# Panics
1326
1327Panics if there are not enough bytes in `self`.",
1328        u64,
1329        write_u64_le,
1330        to_le_bytes,
1331    }
1332
1333    impl_write! {
1334"Writes a `u64` into the underlying buffer in big endian byte order.
1335
1336# Panics
1337
1338Panics if there are not enough bytes in `self`.",
1339        u64,
1340        write_u64_be,
1341        to_be_bytes,
1342    }
1343
1344    impl_try_write! {
1345"Attempts to write a `u64` into the underlying buffer in little endian byte order.
1346
1347If there are not enough bytes in `self` this function will return `Error::EndOfStream`.",
1348        u64,
1349        try_write_u64_le,
1350        to_le_bytes,
1351    }
1352
1353    impl_try_write! {
1354"Attempts to write a `u64` into the underlying buffer in big endian byte order.
1355
1356If there are not enough bytes in `self` this function will return `Error::EndOfStream`.",
1357        u64,
1358        try_write_u64_be,
1359        to_be_bytes,
1360    }
1361
1362    impl_write! {
1363"Writes an `i64` into the underlying buffer in little endian byte order.
1364
1365# Panics
1366
1367Panics if there are not enough bytes in `self`.",
1368        i64,
1369        write_i64_le,
1370        to_le_bytes,
1371    }
1372
1373    impl_write! {
1374"Writes an `i64` into the underlying buffer in big endian byte order.
1375
1376# Panics
1377
1378Panics if there are not enough bytes in `self`.",
1379        i64,
1380        write_i64_be,
1381        to_be_bytes,
1382    }
1383
1384    impl_try_write! {
1385"Attempts to write an `i64` into the underlying buffer in little endian byte order.
1386
1387If there are not enough bytes in `self` this function will return `Error::EndOfStream`.",
1388        i64,
1389        try_write_i64_le,
1390        to_le_bytes,
1391    }
1392
1393    impl_try_write! {
1394"Attempts to write an `i64` into the underlying buffer in big endian byte order.
1395
1396If there are not enough bytes in `self` this function will return `Error::EndOfStream`.",
1397        i64,
1398        try_write_i64_be,
1399        to_be_bytes,
1400    }
1401
1402    impl_write! {
1403"Writes a `u128` into the underlying buffer in little endian byte order.
1404
1405# Panics
1406
1407Panics if there are not enough bytes in `self`.",
1408        u128,
1409        write_u128_le,
1410        to_le_bytes,
1411    }
1412
1413    impl_write! {
1414"Writes a `u128` into the underlying buffer in big endian byte order.
1415
1416# Panics
1417
1418Panics if there are not enough bytes in `self`.",
1419        u128,
1420        write_u128_be,
1421        to_be_bytes,
1422    }
1423
1424    impl_try_write! {
1425"Attempts to write a `u128` into the underlying buffer in little endian byte order.
1426
1427If there are not enough bytes in `self` this function will return `Error::EndOfStream`.",
1428        u128,
1429        try_write_u128_le,
1430        to_le_bytes,
1431    }
1432
1433    impl_try_write! {
1434"Attempts to write a `u128` into the underlying buffer in big endian byte order.
1435
1436If there are not enough bytes in `self` this function will return `Error::EndOfStream`.",
1437        u128,
1438        try_write_u128_be,
1439        to_be_bytes,
1440    }
1441
1442    impl_write! {
1443"Writes an `i128` into the underlying buffer in little endian byte order.
1444
1445# Panics
1446
1447Panics if there are not enough bytes in `self`.",
1448        i128,
1449        write_i128_le,
1450        to_le_bytes,
1451    }
1452
1453    impl_write! {
1454"Writes an `i128` into the underlying buffer in big endian byte order.
1455
1456# Panics
1457
1458Panics if there are not enough bytes in `self`.",
1459        i128,
1460        write_i128_be,
1461        to_be_bytes,
1462    }
1463
1464    impl_try_write! {
1465"Attempts to write an `i128` into the underlying buffer in little endian byte order.
1466
1467If there are not enough bytes in `self` this function will return `Error::EndOfStream`.",
1468        i128,
1469        try_write_i128_le,
1470        to_le_bytes,
1471    }
1472
1473    impl_try_write! {
1474"Attempts to write an `i128` into the underlying buffer in big endian byte order.
1475
1476If there are not enough bytes in `self` this function will return `Error::EndOfStream`.",
1477        i128,
1478        try_write_i128_be,
1479        to_be_bytes,
1480    }
1481
1482    /// Writes an IEEE754 `f32` into the underlying buffer in little endian byte
1483    /// order.
1484    ///
1485    /// # Panics
1486    ///
1487    /// Panics if there are not enough bytes in `self`.
1488    fn write_f32_le(&mut self, n: f32) {
1489        self.write_u32_le(n.to_bits());
1490    }
1491
1492    /// Writes an IEEE754 `f32` into the underlying buffer in big endian byte
1493    /// order.
1494    ///
1495    /// # Panics
1496    ///
1497    /// Panics if there are not enough bytes in `self`.
1498    fn write_f32_be(&mut self, n: f32) {
1499        self.write_u32_be(n.to_bits());
1500    }
1501
1502    /// Attempts to write an IEEE754 `f32` into the underlying buffer.
1503    ///
1504    /// If there are not enough bytes in `self` this function will return
1505    /// `Error::EndOfStream`.
1506    fn try_write_f32_le(&mut self, n: f32) -> crate::Result<()> {
1507        self.try_write_u32_le(n.to_bits())
1508    }
1509
1510    /// Attempts to write an IEEE754 `f32` into the underlying buffer in big
1511    /// endian byte order.
1512    ///
1513    /// If there are not enough bytes in `self` this function will return
1514    /// `Error::EndOfStream`.
1515    fn try_write_f32_be(&mut self, n: f32) -> crate::Result<()> {
1516        self.try_write_u32_be(n.to_bits())
1517    }
1518
1519    /// Writes an IEEE754 `f64` into the underlying buffer in little endian byte
1520    /// order.
1521    ///
1522    /// # Panics
1523    ///
1524    /// Panics if there are not enough bytes in `self`.
1525    fn write_f64_le(&mut self, n: f64) {
1526        self.write_u64_le(n.to_bits());
1527    }
1528
1529    /// Writes an IEEE754 `f64` into the underlying buffer in big endian byte
1530    /// order.
1531    ///
1532    /// # Panics
1533    ///
1534    /// Panics if there are not enough bytes in `self`.
1535    fn write_f64_be(&mut self, n: f64) {
1536        self.write_u64_be(n.to_bits());
1537    }
1538
1539    /// Attempts to write an IEEE754 `f64` into the underlying buffer.
1540    ///
1541    /// If there are not enough bytes in `self` this function will return
1542    /// `Error::EndOfStream`.
1543    fn try_write_f64_le(&mut self, n: f64) -> crate::Result<()> {
1544        self.try_write_u64_le(n.to_bits())
1545    }
1546
1547    /// Attempts to write an IEEE754 `f64` into the underlying buffer in big
1548    /// endian byte order.
1549    ///
1550    /// If there are not enough bytes in `self` this function will return
1551    /// `Error::EndOfStream`.
1552    fn try_write_f64_be(&mut self, n: f64) -> crate::Result<()> {
1553        self.try_write_u64_be(n.to_bits())
1554    }
1555}
1556
1557impl<W: WriteBytes> WriteBytesExt for W {}
1558
1559/*
1560 *
1561 * Writer
1562 *
1563 */
1564
1565/// A convenience structure used for counting the number of bytes written.
1566///
1567/// This structure wraps an implementation of [`WriteBytes`][writebytes]. It
1568/// forwards write operations to the inner type while also maintaining a count
1569/// of the number of bytes that pass through it.
1570///
1571/// When you have finished with it, you can return the original type via the
1572/// [`into_inner`][into-inner] method.
1573///
1574/// When compiled with the `std` feature this structure implements
1575/// [`Write`][std-io-write].
1576///
1577/// [std-io-write]: https://doc.rust-lang.org/std/io/trait.Write.html
1578///
1579/// # Examples
1580///
1581/// ```
1582/// use byteio::{WriteBytes, WriteBytesExt, Writer};
1583///
1584/// fn main() -> byteio::Result<()> {
1585///     let mut buf = [0; 7];
1586///
1587///     {
1588///         let mut writer = Writer::new(&mut buf[..]);
1589///
1590///         writer.try_write_u8(1)?;
1591///         writer.try_write_u16_be(2)?;
1592///         writer.try_write_u32_be(3)?;
1593///
1594///         assert_eq!(writer.num_bytes_written(), 7);
1595///
1596///         let inner = writer.into_inner();
1597///         assert!(inner.is_empty());
1598///     }
1599///
1600///     assert_eq!(buf, [1, 0, 2, 0, 0, 0, 3]);
1601///
1602///     Ok(())
1603/// }
1604/// ```
1605///
1606/// [writebytes]: trait.WriteBytes.html
1607/// [into-inner]: struct.Writer.html#method.into_inner
1608#[derive(Debug, Clone, Eq, PartialEq, Hash)]
1609pub struct Writer<W: WriteBytes>(W, usize);
1610
1611impl<W: WriteBytes> Writer<W> {
1612    /// Creates a new `Writer` by wrapping a [`WriteBytes`][writebytes]
1613    /// implementor.
1614    ///
1615    /// # Examples
1616    ///
1617    /// ```
1618    /// use byteio::Writer;
1619    ///
1620    /// let mut buf = [0_u8; 2];
1621    /// let mut writer = Writer::new(&mut buf[..]);
1622    /// ```
1623    ///
1624    /// [writebytes]: trait.WriteBytes.html
1625    #[inline]
1626    pub fn new(writer: W) -> Self {
1627        Self(writer, 0)
1628    }
1629
1630    /// Retrieves the number of bytes that have been written by this `Writer`.
1631    ///
1632    /// # Examples
1633    ///
1634    /// ```
1635    /// use byteio::{WriteBytes, Writer};
1636    ///
1637    /// let mut buf = [0_u8; 2];
1638    /// let mut writer = Writer::new(&mut buf[..]);
1639    /// writer.write_exact(&[1]);
1640    /// writer.write_exact(&[1]);
1641    ///
1642    /// assert_eq!(writer.num_bytes_written(), 2);
1643    /// ```
1644    #[inline]
1645    pub fn num_bytes_written(&self) -> usize {
1646        self.1
1647    }
1648
1649    /// Consumes this `Writer` and returns the original
1650    /// [`WriteBytes`][writebytes] implementor.
1651    ///
1652    /// ```
1653    /// use byteio::{WriteBytes, Writer};
1654    ///
1655    /// let mut buf = [0_u8; 2];
1656    /// let mut writer = Writer::new(&mut buf[..]);
1657    /// writer.write_exact(&[1]);
1658    /// let inner = writer.into_inner();
1659    ///
1660    /// assert_eq!(inner.len(), 1); // the writer consumed one byte from its view of the slice
1661    /// ```
1662    ///
1663    /// [writebytes]: trait.WriteBytes.html
1664    #[inline]
1665    pub fn into_inner(self) -> W {
1666        self.0
1667    }
1668}
1669
1670impl<W: WriteBytes> AsMut<[u8]> for Writer<W> {
1671    fn as_mut(&mut self) -> &mut [u8] {
1672        self.0.as_mut()
1673    }
1674}
1675
1676impl<W: WriteBytes> WriteBytes for Writer<W> {
1677    fn write_exact(&mut self, buf: &[u8]) {
1678        self.0.write_exact(buf);
1679        self.1 += buf.len();
1680    }
1681
1682    fn try_write_exact(&mut self, buf: &[u8]) -> crate::Result<()> {
1683        match self.0.try_write_exact(buf) {
1684            res @ Ok(_) => {
1685                self.1 += buf.len();
1686                res
1687            }
1688            res @ Err(_) => res,
1689        }
1690    }
1691}
1692
1693#[cfg(feature = "std")]
1694impl<W: WriteBytes> io::Write for Writer<W> {
1695    fn write(&mut self, data: &[u8]) -> io::Result<usize> {
1696        let n = ::core::cmp::min(data.len(), self.as_mut().len());
1697        <Self as WriteBytes>::write_exact(self, &data[..n]);
1698
1699        Ok(n)
1700    }
1701
1702    fn flush(&mut self) -> io::Result<()> {
1703        Ok(())
1704    }
1705}
1706
1707/*
1708 *
1709 * Unit tests
1710 *
1711 * For the full test suite, see $CARGO_MANIFEST_DIR/tests
1712 *
1713 */
1714
1715#[cfg(test)]
1716mod test {
1717    #![allow(unused_imports)]
1718
1719    use super::*;
1720
1721    #[cfg(feature = "std")]
1722    #[test]
1723    fn io_error_from_error_end_of_stream() {
1724        let err: io::Error = Error::EndOfStream.into();
1725        assert_eq!(err.kind(), io::ErrorKind::UnexpectedEof);
1726    }
1727
1728    #[cfg(feature = "std")]
1729    #[test]
1730    #[should_panic]
1731    fn io_error_from_error_nonexhaustive() {
1732        let _: io::Error = Error::_nonexhaustive(()).into();
1733    }
1734
1735    #[cfg(feature = "std")]
1736    #[test]
1737    fn display_error_end_of_stream() {
1738        use std::string::ToString;
1739
1740        assert_eq!(Error::EndOfStream.to_string(), "unexpected end of stream");
1741    }
1742
1743    #[cfg(feature = "std")]
1744    #[test]
1745    #[should_panic]
1746    fn display_error_nonexhaustive() {
1747        use std::string::ToString;
1748
1749        let _ = Error::_nonexhaustive(()).to_string();
1750    }
1751}