tokio_byteorder/
lib.rs

1/*!
2This crate provides convenience methods for encoding and decoding numbers in
3either [big-endian or little-endian order] on top of asynchronous I/O streams.
4It owes everything to the magnificent [`byteorder`] crate. This crate only
5provides a shim to [`AsyncRead`] and [`AsyncWrite`].
6
7The organization of the crate mirrors that of `byteorder`. A trait, [`ByteOrder`], specifies
8byte conversion methods for each type of number in Rust (sans numbers that have
9a platform dependent size like `usize` and `isize`). Two types, [`BigEndian`]
10and [`LittleEndian`] implement these methods. Finally, [`AsyncReadBytesExt`] and
11[`AsyncWriteBytesExt`] provide convenience methods available to all types that
12implement [`Read`] and [`Write`].
13
14An alias, [`NetworkEndian`], for [`BigEndian`] is provided to help improve
15code clarity.
16
17An additional alias, [`NativeEndian`], is provided for the endianness of the
18local platform. This is convenient when serializing data for use and
19conversions are not desired.
20
21# Examples
22
23Read unsigned 16 bit big-endian integers from an [`AsyncRead`] type:
24
25```rust
26use std::io::Cursor;
27use tokio_byteorder::{BigEndian, AsyncReadBytesExt};
28
29#[tokio::main]
30async fn main() {
31    let mut rdr = Cursor::new(vec![2, 5, 3, 0]);
32    // Note that we use type parameters to indicate which kind of byte order
33    // we want!
34    assert_eq!(517, rdr.read_u16::<BigEndian>().await.unwrap());
35    assert_eq!(768, rdr.read_u16::<BigEndian>().await.unwrap());
36}
37```
38
39Write unsigned 16 bit little-endian integers to a [`AsyncWrite`] type:
40
41```rust
42use tokio_byteorder::{LittleEndian, AsyncWriteBytesExt};
43
44#[tokio::main]
45async fn main() {
46    let mut wtr = vec![];
47    wtr.write_u16::<LittleEndian>(517).await.unwrap();
48    wtr.write_u16::<LittleEndian>(768).await.unwrap();
49    assert_eq!(wtr, vec![5, 2, 0, 3]);
50}
51```
52
53# Alternatives
54
55Note that as of Rust 1.32, the standard numeric types provide built-in methods
56like `to_le_bytes` and `from_le_bytes`, which support some of the same use
57cases.
58
59[big-endian or little-endian order]: https://en.wikipedia.org/wiki/Endianness
60[`byteorder`]: https://github.com/BurntSushi/byteorder/
61[`ByteOrder`]: trait.ByteOrder.html
62[`BigEndian`]: enum.BigEndian.html
63[`LittleEndian`]: enum.LittleEndian.html
64[`AsyncReadBytesExt`]: trait.AsyncReadBytesExt.html
65[`AsyncWriteBytesExt`]: trait.AsyncWriteBytesExt.html
66[`NetworkEndian`]: type.NetworkEndian.html
67[`NativeEndian`]: type.NativeEndian.html
68[`AsyncRead`]: https://docs.rs/tokio/0.2.0-alpha.4/tokio/io/trait.AsyncRead.html
69[`AsyncWrite`]: https://docs.rs/tokio/0.2.0-alpha.4/tokio/io/trait.AsyncWrite.html
70*/
71
72#![deny(missing_docs)]
73#![warn(rust_2018_idioms)]
74
75use byteorder::ByteOrder;
76use core::future::Future;
77use core::marker::{PhantomData, Unpin};
78use core::mem::size_of;
79use core::pin::Pin;
80use core::task::{Context, Poll};
81use tokio::io;
82
83pub use byteorder::{BigEndian, LittleEndian, NativeEndian, NetworkEndian};
84
85macro_rules! reader {
86    ($name:ident, $ty:ty, $reader:ident) => {
87        reader!($name, $ty, $reader, size_of::<$ty>());
88    };
89    ($name:ident, $ty:ty, $reader:ident, $bytes:expr) => {
90        #[doc(hidden)]
91        pub struct $name<R, T> {
92            buf: [u8; $bytes],
93            read: u8,
94            src: R,
95            bo: PhantomData<T>,
96        }
97
98        impl<R, T> $name<R, T> {
99            fn new(r: R) -> Self {
100                $name {
101                    buf: [0; $bytes],
102                    read: 0,
103                    src: r,
104                    bo: PhantomData,
105                }
106            }
107        }
108
109        impl<R, T> Future for $name<R, T>
110        where
111            R: io::AsyncRead,
112            T: ByteOrder,
113        {
114            type Output = io::Result<$ty>;
115            fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
116                if self.read == $bytes as u8 {
117                    return Poll::Ready(Ok(T::$reader(&self.buf[..])));
118                }
119
120                // we need this so that we can mutably borrow multiple fields
121                // it is safe as long as we never take &mut to src (since it has been pinned)
122                // unless it is to place it in a Pin itself like below.
123                let mut this = unsafe { self.get_unchecked_mut() };
124                let mut src = unsafe { Pin::new_unchecked(&mut this.src) };
125
126                while this.read < $bytes as u8 {
127                    let mut buf = ::tokio::io::ReadBuf::new(&mut this.buf[this.read as usize..]);
128                    this.read += match src.as_mut().poll_read(cx, &mut buf) {
129                        Poll::Pending => return Poll::Pending,
130                        Poll::Ready(Err(e)) => return Poll::Ready(Err(e.into())),
131                        Poll::Ready(Ok(())) if buf.filled().is_empty() => {
132                            return Poll::Ready(Err(io::Error::new(
133                                io::ErrorKind::UnexpectedEof,
134                                "failed to fill whole buffer",
135                            )));
136                        }
137                        Poll::Ready(Ok(())) => buf.filled().len() as u8,
138                    };
139                }
140                Poll::Ready(Ok(T::$reader(&this.buf[..])))
141            }
142        }
143    };
144}
145
146macro_rules! reader8 {
147    ($name:ident, $ty:ty) => {
148        #[doc(hidden)]
149        pub struct $name<R>(R);
150        impl<R> Future for $name<R>
151        where
152            R: io::AsyncRead,
153        {
154            type Output = io::Result<$ty>;
155            fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
156                let src = unsafe { self.map_unchecked_mut(|t| &mut t.0) };
157                let mut buf = [0; 1];
158                let mut buf = ::tokio::io::ReadBuf::new(&mut buf[..]);
159                match src.poll_read(cx, &mut buf) {
160                    Poll::Pending => Poll::Pending,
161                    Poll::Ready(Err(e)) => Poll::Ready(Err(e.into())),
162                    Poll::Ready(Ok(())) if buf.filled().is_empty() => Poll::Ready(Err(
163                        io::Error::new(io::ErrorKind::UnexpectedEof, "failed to fill whole buffer"),
164                    )),
165                    Poll::Ready(Ok(())) if buf.filled().len() == 1 => {
166                        Poll::Ready(Ok(buf.filled()[0] as $ty))
167                    }
168                    Poll::Ready(Ok(_)) => unreachable!(),
169                }
170            }
171        }
172    };
173}
174
175reader8!(ReadU8, u8);
176reader8!(ReadI8, i8);
177
178reader!(ReadF32, f32, read_f32);
179reader!(ReadF64, f64, read_f64);
180reader!(ReadU16, u16, read_u16);
181reader!(ReadU24, u32, read_u24, 3);
182reader!(ReadU32, u32, read_u32);
183reader!(ReadU48, u64, read_u48, 6);
184reader!(ReadU64, u64, read_u64);
185reader!(ReadU128, u128, read_u128);
186reader!(ReadI16, i16, read_i16);
187reader!(ReadI24, i32, read_i24, 3);
188reader!(ReadI32, i32, read_i32);
189reader!(ReadI48, i64, read_i48, 6);
190reader!(ReadI64, i64, read_i64);
191reader!(ReadI128, i128, read_i128);
192
193macro_rules! read_impl {
194    (
195        $(#[$outer:meta])*
196        fn $name:ident(&mut self) -> $($fut:tt)*
197    ) => {
198        $(#[$outer])*
199        #[inline]
200        fn $name<'a, T: ByteOrder>(&'a mut self) -> $($fut)*<&'a mut Self, T> where Self: Unpin {
201            $($fut)*::new(self)
202        }
203    }
204}
205
206/// Extends [`AsyncRead`] with methods for reading numbers.
207///
208/// Most of the methods defined here have an unconstrained type parameter that
209/// must be explicitly instantiated. Typically, it is instantiated with either
210/// the [`BigEndian`] or [`LittleEndian`] types defined in this crate.
211///
212/// # Examples
213///
214/// Read unsigned 16 bit big-endian integers from a [`Read`]:
215///
216/// ```rust
217/// use std::io::Cursor;
218/// use tokio_byteorder::{BigEndian, AsyncReadBytesExt};
219///
220/// #[tokio::main]
221/// async fn main() {
222///     let mut rdr = Cursor::new(vec![2, 5, 3, 0]);
223///     assert_eq!(517, rdr.read_u16::<BigEndian>().await.unwrap());
224///     assert_eq!(768, rdr.read_u16::<BigEndian>().await.unwrap());
225/// }
226/// ```
227///
228/// [`BigEndian`]: enum.BigEndian.html
229/// [`LittleEndian`]: enum.LittleEndian.html
230/// [`AsyncRead`]: https://docs.rs/tokio/0.2.0-alpha.4/tokio/io/trait.AsyncRead.html
231pub trait AsyncReadBytesExt: io::AsyncRead {
232    /// Reads an unsigned 8 bit integer from the underlying reader.
233    ///
234    /// Note that since this reads a single byte, no byte order conversions
235    /// are used. It is included for completeness.
236    ///
237    /// # Errors
238    ///
239    /// This method returns the same errors as [`Read::read_exact`].
240    ///
241    /// [`Read::read_exact`]: https://doc.rust-lang.org/std/io/trait.Read.html#method.read_exact
242    ///
243    /// # Examples
244    ///
245    /// Read unsigned 8 bit integers from a `Read`:
246    ///
247    /// ```rust
248    /// use std::io::Cursor;
249    /// use tokio_byteorder::AsyncReadBytesExt;
250    ///
251    /// #[tokio::main]
252    /// async fn main() {
253    ///     let mut rdr = Cursor::new(vec![2, 5]);
254    ///     assert_eq!(2, rdr.read_u8().await.unwrap());
255    ///     assert_eq!(5, rdr.read_u8().await.unwrap());
256    /// }
257    /// ```
258    #[inline]
259    fn read_u8<'a>(&'a mut self) -> ReadU8<&'a mut Self>
260    where
261        Self: Unpin,
262    {
263        ReadU8(self)
264    }
265
266    /// Reads a signed 8 bit integer from the underlying reader.
267    ///
268    /// Note that since this reads a single byte, no byte order conversions
269    /// are used. It is included for completeness.
270    ///
271    /// # Errors
272    ///
273    /// This method returns the same errors as [`Read::read_exact`].
274    ///
275    /// [`Read::read_exact`]: https://doc.rust-lang.org/std/io/trait.Read.html#method.read_exact
276    ///
277    /// # Examples
278    ///
279    /// Read signed 8 bit integers from a `Read`:
280    ///
281    /// ```rust
282    /// use std::io::Cursor;
283    /// use tokio_byteorder::AsyncReadBytesExt;
284    ///
285    /// #[tokio::main]
286    /// async fn main() {
287    ///     let mut rdr = Cursor::new(vec![0x02, 0xfb]);
288    ///     assert_eq!(2, rdr.read_i8().await.unwrap());
289    ///     assert_eq!(-5, rdr.read_i8().await.unwrap());
290    /// }
291    /// ```
292    #[inline]
293    fn read_i8<'a>(&'a mut self) -> ReadI8<&'a mut Self>
294    where
295        Self: Unpin,
296    {
297        ReadI8(self)
298    }
299
300    read_impl! {
301        /// Reads an unsigned 16 bit integer from the underlying reader.
302        ///
303        /// # Errors
304        ///
305        /// This method returns the same errors as [`Read::read_exact`].
306        ///
307        /// [`Read::read_exact`]: https://doc.rust-lang.org/std/io/trait.Read.html#method.read_exact
308        ///
309        /// # Examples
310        ///
311        /// Read unsigned 16 bit big-endian integers from a `Read`:
312        ///
313        /// ```rust
314        /// use std::io::Cursor;
315        /// use tokio_byteorder::{BigEndian, AsyncReadBytesExt};
316        ///
317        /// #[tokio::main]
318        /// async fn main() {
319        ///     let mut rdr = Cursor::new(vec![2, 5, 3, 0]);
320        ///     assert_eq!(517, rdr.read_u16::<BigEndian>().await.unwrap());
321        ///     assert_eq!(768, rdr.read_u16::<BigEndian>().await.unwrap());
322        /// }
323        /// ```
324        fn read_u16(&mut self) -> ReadU16
325    }
326
327    read_impl! {
328        /// Reads a signed 16 bit integer from the underlying reader.
329        ///
330        /// # Errors
331        ///
332        /// This method returns the same errors as [`Read::read_exact`].
333        ///
334        /// [`Read::read_exact`]: https://doc.rust-lang.org/std/io/trait.Read.html#method.read_exact
335        ///
336        /// # Examples
337        ///
338        /// Read signed 16 bit big-endian integers from a `Read`:
339        ///
340        /// ```rust
341        /// use std::io::Cursor;
342        /// use tokio_byteorder::{BigEndian, AsyncReadBytesExt};
343        ///
344        /// #[tokio::main]
345        /// async fn main() {
346        ///     let mut rdr = Cursor::new(vec![0x00, 0xc1, 0xff, 0x7c]);
347        ///     assert_eq!(193, rdr.read_i16::<BigEndian>().await.unwrap());
348        ///     assert_eq!(-132, rdr.read_i16::<BigEndian>().await.unwrap());
349        /// }
350        /// ```
351        fn read_i16(&mut self) -> ReadI16
352    }
353
354    read_impl! {
355        /// Reads an unsigned 24 bit integer from the underlying reader.
356        ///
357        /// # Errors
358        ///
359        /// This method returns the same errors as [`Read::read_exact`].
360        ///
361        /// [`Read::read_exact`]: https://doc.rust-lang.org/std/io/trait.Read.html#method.read_exact
362        ///
363        /// # Examples
364        ///
365        /// Read unsigned 24 bit big-endian integers from a `Read`:
366        ///
367        /// ```rust
368        /// use std::io::Cursor;
369        /// use tokio_byteorder::{BigEndian, AsyncReadBytesExt};
370        ///
371        /// #[tokio::main]
372        /// async fn main() {
373        ///     let mut rdr = Cursor::new(vec![0x00, 0x01, 0x0b]);
374        ///     assert_eq!(267, rdr.read_u24::<BigEndian>().await.unwrap());
375        /// }
376        /// ```
377        fn read_u24(&mut self) -> ReadU24
378    }
379
380    read_impl! {
381        /// Reads a signed 24 bit integer from the underlying reader.
382        ///
383        /// # Errors
384        ///
385        /// This method returns the same errors as [`Read::read_exact`].
386        ///
387        /// [`Read::read_exact`]: https://doc.rust-lang.org/std/io/trait.Read.html#method.read_exact
388        ///
389        /// # Examples
390        ///
391        /// Read signed 24 bit big-endian integers from a `Read`:
392        ///
393        /// ```rust
394        /// use std::io::Cursor;
395        /// use tokio_byteorder::{BigEndian, AsyncReadBytesExt};
396        ///
397        /// #[tokio::main]
398        /// async fn main() {
399        ///     let mut rdr = Cursor::new(vec![0xff, 0x7a, 0x33]);
400        ///     assert_eq!(-34253, rdr.read_i24::<BigEndian>().await.unwrap());
401        /// }
402        /// ```
403        fn read_i24(&mut self) -> ReadI24
404    }
405
406    read_impl! {
407        /// Reads an unsigned 32 bit integer from the underlying reader.
408        ///
409        /// # Errors
410        ///
411        /// This method returns the same errors as [`Read::read_exact`].
412        ///
413        /// [`Read::read_exact`]: https://doc.rust-lang.org/std/io/trait.Read.html#method.read_exact
414        ///
415        /// # Examples
416        ///
417        /// Read unsigned 32 bit big-endian integers from a `Read`:
418        ///
419        /// ```rust
420        /// use std::io::Cursor;
421        /// use tokio_byteorder::{BigEndian, AsyncReadBytesExt};
422        ///
423        /// #[tokio::main]
424        /// async fn main() {
425        ///     let mut rdr = Cursor::new(vec![0x00, 0x00, 0x01, 0x0b]);
426        ///     assert_eq!(267, rdr.read_u32::<BigEndian>().await.unwrap());
427        /// }
428        /// ```
429        fn read_u32(&mut self) -> ReadU32
430    }
431
432    read_impl! {
433        /// Reads a signed 32 bit integer from the underlying reader.
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        ///
441        /// # Examples
442        ///
443        /// Read signed 32 bit big-endian integers from a `Read`:
444        ///
445        /// ```rust
446        /// use std::io::Cursor;
447        /// use tokio_byteorder::{BigEndian, AsyncReadBytesExt};
448        ///
449        /// #[tokio::main]
450        /// async fn main() {
451        ///     let mut rdr = Cursor::new(vec![0xff, 0xff, 0x7a, 0x33]);
452        ///     assert_eq!(-34253, rdr.read_i32::<BigEndian>().await.unwrap());
453        /// }
454        /// ```
455        fn read_i32(&mut self) -> ReadI32
456    }
457
458    read_impl! {
459        /// Reads an unsigned 48 bit integer from the underlying reader.
460        ///
461        /// # Errors
462        ///
463        /// This method returns the same errors as [`Read::read_exact`].
464        ///
465        /// [`Read::read_exact`]: https://doc.rust-lang.org/std/io/trait.Read.html#method.read_exact
466        ///
467        /// # Examples
468        ///
469        /// Read unsigned 48 bit big-endian integers from a `Read`:
470        ///
471        /// ```rust
472        /// use std::io::Cursor;
473        /// use tokio_byteorder::{BigEndian, AsyncReadBytesExt};
474        ///
475        /// #[tokio::main]
476        /// async fn main() {
477        ///     let mut rdr = Cursor::new(vec![0xb6, 0x71, 0x6b, 0xdc, 0x2b, 0x31]);
478        ///     assert_eq!(200598257150769, rdr.read_u48::<BigEndian>().await.unwrap());
479        /// }
480        /// ```
481        fn read_u48(&mut self) -> ReadU48
482    }
483
484    read_impl! {
485        /// Reads a signed 48 bit integer from the underlying reader.
486        ///
487        /// # Errors
488        ///
489        /// This method returns the same errors as [`Read::read_exact`].
490        ///
491        /// [`Read::read_exact`]: https://doc.rust-lang.org/std/io/trait.Read.html#method.read_exact
492        ///
493        /// # Examples
494        ///
495        /// Read signed 48 bit big-endian integers from a `Read`:
496        ///
497        /// ```rust
498        /// use std::io::Cursor;
499        /// use tokio_byteorder::{BigEndian, AsyncReadBytesExt};
500        ///
501        /// #[tokio::main]
502        /// async fn main() {
503        ///     let mut rdr = Cursor::new(vec![0x9d, 0x71, 0xab, 0xe7, 0x97, 0x8f]);
504        ///     assert_eq!(-108363435763825, rdr.read_i48::<BigEndian>().await.unwrap());
505        /// }
506        /// ```
507        fn read_i48(&mut self) -> ReadI48
508    }
509
510    read_impl! {
511        /// Reads an unsigned 64 bit integer from the underlying reader.
512        ///
513        /// # Errors
514        ///
515        /// This method returns the same errors as [`Read::read_exact`].
516        ///
517        /// [`Read::read_exact`]: https://doc.rust-lang.org/std/io/trait.Read.html#method.read_exact
518        ///
519        /// # Examples
520        ///
521        /// Read an unsigned 64 bit big-endian integer from a `Read`:
522        ///
523        /// ```rust
524        /// use std::io::Cursor;
525        /// use tokio_byteorder::{BigEndian, AsyncReadBytesExt};
526        ///
527        /// #[tokio::main]
528        /// async fn main() {
529        ///     let mut rdr = Cursor::new(vec![0x00, 0x03, 0x43, 0x95, 0x4d, 0x60, 0x86, 0x83]);
530        ///     assert_eq!(918733457491587, rdr.read_u64::<BigEndian>().await.unwrap());
531        /// }
532        /// ```
533        fn read_u64(&mut self) -> ReadU64
534    }
535
536    read_impl! {
537        /// Reads a signed 64 bit integer from the underlying reader.
538        ///
539        /// # Errors
540        ///
541        /// This method returns the same errors as [`Read::read_exact`].
542        ///
543        /// [`Read::read_exact`]: https://doc.rust-lang.org/std/io/trait.Read.html#method.read_exact
544        ///
545        /// # Examples
546        ///
547        /// Read a signed 64 bit big-endian integer from a `Read`:
548        ///
549        /// ```rust
550        /// use std::io::Cursor;
551        /// use tokio_byteorder::{BigEndian, AsyncReadBytesExt};
552        ///
553        /// #[tokio::main]
554        /// async fn main() {
555        ///     let mut rdr = Cursor::new(vec![0x80, 0, 0, 0, 0, 0, 0, 0]);
556        ///     assert_eq!(i64::min_value(), rdr.read_i64::<BigEndian>().await.unwrap());
557        /// }
558        /// ```
559        fn read_i64(&mut self) -> ReadI64
560    }
561
562    read_impl! {
563        /// Reads an unsigned 128 bit integer from the underlying reader.
564        ///
565        /// # Errors
566        ///
567        /// This method returns the same errors as [`Read::read_exact`].
568        ///
569        /// [`Read::read_exact`]: https://doc.rust-lang.org/std/io/trait.Read.html#method.read_exact
570        ///
571        /// # Examples
572        ///
573        /// Read an unsigned 128 bit big-endian integer from a `Read`:
574        ///
575        /// ```rust
576        /// use std::io::Cursor;
577        /// use tokio_byteorder::{BigEndian, AsyncReadBytesExt};
578        ///
579        /// #[tokio::main]
580        /// async fn main() {
581        ///     let mut rdr = Cursor::new(vec![
582        ///         0x00, 0x03, 0x43, 0x95, 0x4d, 0x60, 0x86, 0x83,
583        ///         0x00, 0x03, 0x43, 0x95, 0x4d, 0x60, 0x86, 0x83
584        ///     ]);
585        ///     assert_eq!(16947640962301618749969007319746179, rdr.read_u128::<BigEndian>().await.unwrap());
586        /// }
587        /// ```
588        fn read_u128(&mut self) -> ReadU128
589    }
590
591    read_impl! {
592        /// Reads a signed 128 bit integer from the underlying reader.
593        ///
594        /// # Errors
595        ///
596        /// This method returns the same errors as [`Read::read_exact`].
597        ///
598        /// [`Read::read_exact`]: https://doc.rust-lang.org/std/io/trait.Read.html#method.read_exact
599        ///
600        /// # Examples
601        ///
602        /// Read a signed 128 bit big-endian integer from a `Read`:
603        ///
604        /// ```rust
605        /// use std::io::Cursor;
606        /// use tokio_byteorder::{BigEndian, AsyncReadBytesExt};
607        ///
608        /// #[tokio::main]
609        /// async fn main() {
610        ///     let mut rdr = Cursor::new(vec![0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
611        ///     assert_eq!(i128::min_value(), rdr.read_i128::<BigEndian>().await.unwrap());
612        /// }
613        /// ```
614        fn read_i128(&mut self) -> ReadI128
615    }
616
617    // TODO: read_*int
618
619    read_impl! {
620        /// Reads a IEEE754 single-precision (4 bytes) floating point number from
621        /// the underlying reader.
622        ///
623        /// # Errors
624        ///
625        /// This method returns the same errors as [`Read::read_exact`].
626        ///
627        /// [`Read::read_exact`]: https://doc.rust-lang.org/std/io/trait.Read.html#method.read_exact
628        ///
629        /// # Examples
630        ///
631        /// Read a big-endian single-precision floating point number from a `Read`:
632        ///
633        /// ```rust
634        /// use std::f32;
635        /// use std::io::Cursor;
636        /// use tokio_byteorder::{BigEndian, AsyncReadBytesExt};
637        ///
638        /// #[tokio::main]
639        /// async fn main() {
640        ///     let mut rdr = Cursor::new(vec![
641        ///         0x40, 0x49, 0x0f, 0xdb,
642        ///     ]);
643        ///     assert_eq!(f32::consts::PI, rdr.read_f32::<BigEndian>().await.unwrap());
644        /// }
645        /// ```
646        fn read_f32(&mut self) -> ReadF32
647    }
648
649    read_impl! {
650        /// Reads a IEEE754 double-precision (8 bytes) floating point number from
651        /// the underlying reader.
652        ///
653        /// # Errors
654        ///
655        /// This method returns the same errors as [`Read::read_exact`].
656        ///
657        /// [`Read::read_exact`]: https://doc.rust-lang.org/std/io/trait.Read.html#method.read_exact
658        ///
659        /// # Examples
660        ///
661        /// Read a big-endian double-precision floating point number from a `Read`:
662        ///
663        /// ```rust
664        /// use std::f64;
665        /// use std::io::Cursor;
666        /// use tokio_byteorder::{BigEndian, AsyncReadBytesExt};
667        ///
668        /// #[tokio::main]
669        /// async fn main() {
670        ///     let mut rdr = Cursor::new(vec![
671        ///         0x40, 0x09, 0x21, 0xfb, 0x54, 0x44, 0x2d, 0x18,
672        ///     ]);
673        ///     assert_eq!(f64::consts::PI, rdr.read_f64::<BigEndian>().await.unwrap());
674        /// }
675        /// ```
676    fn read_f64(&mut self) -> ReadF64
677    }
678
679    // TODO: read_*_into
680}
681
682/// All types that implement `AsyncRead` get methods defined in `AsyncReadBytesExt`
683/// for free.
684impl<R: io::AsyncRead + ?Sized> AsyncReadBytesExt for R {}
685
686macro_rules! writer {
687    ($name:ident, $ty:ty, $writer:ident) => {
688        writer!($name, $ty, $writer, size_of::<$ty>());
689    };
690    ($name:ident, $ty:ty, $writer:ident, $bytes:expr) => {
691        #[doc(hidden)]
692        pub struct $name<W> {
693            buf: [u8; $bytes],
694            written: u8,
695            dst: W,
696        }
697
698        impl<W> $name<W> {
699            fn new<T: ByteOrder>(w: W, value: $ty) -> Self {
700                let mut writer = $name {
701                    buf: [0; $bytes],
702                    written: 0,
703                    dst: w,
704                };
705                T::$writer(&mut writer.buf[..], value);
706                writer
707            }
708        }
709
710        impl<W> Future for $name<W>
711        where
712            W: io::AsyncWrite,
713        {
714            type Output = io::Result<()>;
715            fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
716                if self.written == $bytes as u8 {
717                    return Poll::Ready(Ok(()));
718                }
719
720                // we need this so that we can mutably borrow multiple fields
721                // it is safe as long as we never take &mut to dst (since it has been pinned)
722                // unless it is to place it in a Pin itself like below.
723                let mut this = unsafe { self.get_unchecked_mut() };
724                let mut dst = unsafe { Pin::new_unchecked(&mut this.dst) };
725
726                while this.written < $bytes as u8 {
727                    this.written += match dst
728                        .as_mut()
729                        .poll_write(cx, &this.buf[this.written as usize..])
730                    {
731                        Poll::Pending => return Poll::Pending,
732                        Poll::Ready(Err(e)) => return Poll::Ready(Err(e.into())),
733                        Poll::Ready(Ok(n)) => n as u8,
734                    };
735                }
736                Poll::Ready(Ok(()))
737            }
738        }
739    };
740}
741
742macro_rules! writer8 {
743    ($name:ident, $ty:ty) => {
744        #[doc(hidden)]
745        pub struct $name<W>(W, $ty);
746        impl<W> Future for $name<W>
747        where
748            W: io::AsyncWrite,
749        {
750            type Output = io::Result<()>;
751            fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
752                let this = unsafe { self.get_unchecked_mut() };
753                let dst = unsafe { Pin::new_unchecked(&mut this.0) };
754                let buf = [this.1 as u8];
755                match dst.poll_write(cx, &buf[..]) {
756                    Poll::Pending => Poll::Pending,
757                    Poll::Ready(Err(e)) => Poll::Ready(Err(e.into())),
758                    Poll::Ready(Ok(0)) => Poll::Pending,
759                    Poll::Ready(Ok(1)) => Poll::Ready(Ok(())),
760                    Poll::Ready(Ok(_)) => unreachable!(),
761                }
762            }
763        }
764    };
765}
766
767writer8!(WriteU8, u8);
768writer8!(WriteI8, i8);
769
770writer!(WriteF32, f32, write_f32);
771writer!(WriteF64, f64, write_f64);
772writer!(WriteU16, u16, write_u16);
773writer!(WriteU24, u32, write_u24, 3);
774writer!(WriteU32, u32, write_u32);
775writer!(WriteU48, u64, write_u48, 6);
776writer!(WriteU64, u64, write_u64);
777writer!(WriteU128, u128, write_u128);
778writer!(WriteI16, i16, write_i16);
779writer!(WriteI24, i32, write_i24, 3);
780writer!(WriteI32, i32, write_i32);
781writer!(WriteI48, i64, write_i48, 6);
782writer!(WriteI64, i64, write_i64);
783writer!(WriteI128, i128, write_i128);
784
785macro_rules! write_impl {
786    (
787        $(#[$outer:meta])*
788        fn $name:ident(&mut self, n: $ty:ty) -> $($fut:tt)*
789    ) => {
790        $(#[$outer])*
791        #[inline]
792        fn $name<'a, T: ByteOrder>(&'a mut self, n: $ty) -> $($fut)*<&'a mut Self> where Self: Unpin {
793            $($fut)*::new::<T>(self, n)
794        }
795    }
796}
797
798/// Extends [`AsyncWrite`] with methods for writing numbers.
799///
800/// Most of the methods defined here have an unconstrained type parameter that
801/// must be explicitly instantiated. Typically, it is instantiated with either
802/// the [`BigEndian`] or [`LittleEndian`] types defined in this crate.
803///
804/// # Examples
805///
806/// Write unsigned 16 bit big-endian integers to a [`Write`]:
807///
808/// ```rust
809/// use tokio_byteorder::{BigEndian, AsyncWriteBytesExt};
810///
811/// #[tokio::main]
812/// async fn main() {
813///     let mut wtr = vec![];
814///     wtr.write_u16::<BigEndian>(517).await.unwrap();
815///     wtr.write_u16::<BigEndian>(768).await.unwrap();
816///     assert_eq!(wtr, vec![2, 5, 3, 0]);
817/// }
818/// ```
819///
820/// [`BigEndian`]: enum.BigEndian.html
821/// [`LittleEndian`]: enum.LittleEndian.html
822/// [`AsyncWrite`]: https://docs.rs/tokio/0.2.0-alpha.4/tokio/io/trait.AsyncWrite.html
823pub trait AsyncWriteBytesExt: io::AsyncWrite {
824    /// Writes an unsigned 8 bit integer to the underlying writer.
825    ///
826    /// Note that since this writes a single byte, no byte order conversions
827    /// are used. It is included for completeness.
828    ///
829    /// # Errors
830    ///
831    /// This method returns the same errors as [`Write::write_all`].
832    ///
833    /// [`Write::write_all`]: https://doc.rust-lang.org/std/io/trait.Write.html#method.write_all
834    ///
835    /// # Examples
836    ///
837    /// Write unsigned 8 bit integers to a `Write`:
838    ///
839    /// ```rust
840    /// use tokio_byteorder::{AsyncWriteBytesExt};
841    ///
842    /// #[tokio::main]
843    /// async fn main() {
844    ///     let mut wtr = Vec::new();
845    ///     wtr.write_u8(2).await.unwrap();
846    ///     wtr.write_u8(5).await.unwrap();
847    ///     assert_eq!(wtr, b"\x02\x05");
848    /// }
849    /// ```
850    #[inline]
851    fn write_u8<'a>(&'a mut self, n: u8) -> WriteU8<&'a mut Self>
852    where
853        Self: Unpin,
854    {
855        WriteU8(self, n)
856    }
857
858    /// Writes a signed 8 bit integer to the underlying writer.
859    ///
860    /// Note that since this writes a single byte, no byte order conversions
861    /// are used. It is included for completeness.
862    ///
863    /// # Errors
864    ///
865    /// This method returns the same errors as [`Write::write_all`].
866    ///
867    /// [`Write::write_all`]: https://doc.rust-lang.org/std/io/trait.Write.html#method.write_all
868    ///
869    /// # Examples
870    ///
871    /// Write signed 8 bit integers to a `Write`:
872    ///
873    /// ```rust
874    /// use tokio_byteorder::{AsyncWriteBytesExt};
875    ///
876    /// #[tokio::main]
877    /// async fn main() {
878    ///     let mut wtr = Vec::new();
879    ///     wtr.write_i8(2).await.unwrap();
880    ///     wtr.write_i8(-5).await.unwrap();
881    ///     assert_eq!(wtr, b"\x02\xfb");
882    /// }
883    /// ```
884    #[inline]
885    fn write_i8<'a>(&'a mut self, n: i8) -> WriteI8<&'a mut Self>
886    where
887        Self: Unpin,
888    {
889        WriteI8(self, n)
890    }
891
892    write_impl! {
893        /// Writes an unsigned 16 bit integer to the underlying writer.
894        ///
895        /// # Errors
896        ///
897        /// This method returns the same errors as [`Write::write_all`].
898        ///
899        /// [`Write::write_all`]: https://doc.rust-lang.org/std/io/trait.Write.html#method.write_all
900        ///
901        /// # Examples
902        ///
903        /// Write unsigned 16 bit big-endian integers to a `Write`:
904        ///
905        /// ```rust
906        /// use tokio_byteorder::{BigEndian, AsyncWriteBytesExt};
907        ///
908        /// #[tokio::main]
909        /// async fn main() {
910        ///     let mut wtr = Vec::new();
911        ///     wtr.write_u16::<BigEndian>(517).await.unwrap();
912        ///     wtr.write_u16::<BigEndian>(768).await.unwrap();
913        ///     assert_eq!(wtr, b"\x02\x05\x03\x00");
914        /// }
915        /// ```
916        fn write_u16(&mut self, n: u16) -> WriteU16
917    }
918
919    write_impl! {
920        /// Writes a signed 16 bit integer to the underlying writer.
921        ///
922        /// # Errors
923        ///
924        /// This method returns the same errors as [`Write::write_all`].
925        ///
926        /// [`Write::write_all`]: https://doc.rust-lang.org/std/io/trait.Write.html#method.write_all
927        ///
928        /// # Examples
929        ///
930        /// Write signed 16 bit big-endian integers to a `Write`:
931        ///
932        /// ```rust
933        /// use tokio_byteorder::{BigEndian, AsyncWriteBytesExt};
934        ///
935        /// #[tokio::main]
936        /// async fn main() {
937        ///     let mut wtr = Vec::new();
938        ///     wtr.write_i16::<BigEndian>(193).await.unwrap();
939        ///     wtr.write_i16::<BigEndian>(-132).await.unwrap();
940        ///     assert_eq!(wtr, b"\x00\xc1\xff\x7c");
941        /// }
942        /// ```
943        fn write_i16(&mut self, n: i16) -> WriteI16
944    }
945
946    write_impl! {
947        /// Writes an unsigned 24 bit integer to the underlying writer.
948        ///
949        /// # Errors
950        ///
951        /// This method returns the same errors as [`Write::write_all`].
952        ///
953        /// [`Write::write_all`]: https://doc.rust-lang.org/std/io/trait.Write.html#method.write_all
954        ///
955        /// # Examples
956        ///
957        /// Write unsigned 24 bit big-endian integers to a `Write`:
958        ///
959        /// ```rust
960        /// use tokio_byteorder::{BigEndian, AsyncWriteBytesExt};
961        ///
962        /// #[tokio::main]
963        /// async fn main() {
964        ///     let mut wtr = Vec::new();
965        ///     wtr.write_u24::<BigEndian>(267).await.unwrap();
966        ///     wtr.write_u24::<BigEndian>(120111).await.unwrap();
967        ///     assert_eq!(wtr, b"\x00\x01\x0b\x01\xd5\x2f");
968        /// }
969        /// ```
970        fn write_u24(&mut self, n: u32) -> WriteU24
971    }
972
973    write_impl! {
974        /// Writes a signed 24 bit integer to the underlying writer.
975        ///
976        /// # Errors
977        ///
978        /// This method returns the same errors as [`Write::write_all`].
979        ///
980        /// [`Write::write_all`]: https://doc.rust-lang.org/std/io/trait.Write.html#method.write_all
981        ///
982        /// # Examples
983        ///
984        /// Write signed 24 bit big-endian integers to a `Write`:
985        ///
986        /// ```rust
987        /// use tokio_byteorder::{BigEndian, AsyncWriteBytesExt};
988        ///
989        /// #[tokio::main]
990        /// async fn main() {
991        ///     let mut wtr = Vec::new();
992        ///     wtr.write_i24::<BigEndian>(-34253).await.unwrap();
993        ///     wtr.write_i24::<BigEndian>(120111).await.unwrap();
994        ///     assert_eq!(wtr, b"\xff\x7a\x33\x01\xd5\x2f");
995        /// }
996        /// ```
997        fn write_i24(&mut self, n: i32) -> WriteI24
998    }
999
1000    write_impl! {
1001        /// Writes an unsigned 32 bit integer to the underlying writer.
1002        ///
1003        /// # Errors
1004        ///
1005        /// This method returns the same errors as [`Write::write_all`].
1006        ///
1007        /// [`Write::write_all`]: https://doc.rust-lang.org/std/io/trait.Write.html#method.write_all
1008        ///
1009        /// # Examples
1010        ///
1011        /// Write unsigned 32 bit big-endian integers to a `Write`:
1012        ///
1013        /// ```rust
1014        /// use tokio_byteorder::{BigEndian, AsyncWriteBytesExt};
1015        ///
1016        /// #[tokio::main]
1017        /// async fn main() {
1018        ///     let mut wtr = Vec::new();
1019        ///     wtr.write_u32::<BigEndian>(267).await.unwrap();
1020        ///     wtr.write_u32::<BigEndian>(1205419366).await.unwrap();
1021        ///     assert_eq!(wtr, b"\x00\x00\x01\x0b\x47\xd9\x3d\x66");
1022        /// }
1023        /// ```
1024        fn write_u32(&mut self, n: u32) -> WriteU32
1025    }
1026
1027    write_impl! {
1028        /// Writes a signed 32 bit integer to the underlying writer.
1029        ///
1030        /// # Errors
1031        ///
1032        /// This method returns the same errors as [`Write::write_all`].
1033        ///
1034        /// [`Write::write_all`]: https://doc.rust-lang.org/std/io/trait.Write.html#method.write_all
1035        ///
1036        /// # Examples
1037        ///
1038        /// Write signed 32 bit big-endian integers to a `Write`:
1039        ///
1040        /// ```rust
1041        /// use tokio_byteorder::{BigEndian, AsyncWriteBytesExt};
1042        ///
1043        /// #[tokio::main]
1044        /// async fn main() {
1045        ///     let mut wtr = Vec::new();
1046        ///     wtr.write_i32::<BigEndian>(-34253).await.unwrap();
1047        ///     wtr.write_i32::<BigEndian>(1205419366).await.unwrap();
1048        ///     assert_eq!(wtr, b"\xff\xff\x7a\x33\x47\xd9\x3d\x66");
1049        /// }
1050        /// ```
1051        fn write_i32(&mut self, n: i32) -> WriteI32
1052    }
1053
1054    write_impl! {
1055        /// Writes an unsigned 48 bit integer to the underlying writer.
1056        ///
1057        /// # Errors
1058        ///
1059        /// This method returns the same errors as [`Write::write_all`].
1060        ///
1061        /// [`Write::write_all`]: https://doc.rust-lang.org/std/io/trait.Write.html#method.write_all
1062        ///
1063        /// # Examples
1064        ///
1065        /// Write unsigned 48 bit big-endian integers to a `Write`:
1066        ///
1067        /// ```rust
1068        /// use tokio_byteorder::{BigEndian, AsyncWriteBytesExt};
1069        ///
1070        /// #[tokio::main]
1071        /// async fn main() {
1072        ///     let mut wtr = Vec::new();
1073        ///     wtr.write_u48::<BigEndian>(52360336390828).await.unwrap();
1074        ///     wtr.write_u48::<BigEndian>(541).await.unwrap();
1075        ///     assert_eq!(wtr, b"\x2f\x9f\x17\x40\x3a\xac\x00\x00\x00\x00\x02\x1d");
1076        /// }
1077        /// ```
1078        fn write_u48(&mut self, n: u64) -> WriteU48
1079    }
1080
1081    write_impl! {
1082        /// Writes a signed 48 bit integer to the underlying writer.
1083        ///
1084        /// # Errors
1085        ///
1086        /// This method returns the same errors as [`Write::write_all`].
1087        ///
1088        /// [`Write::write_all`]: https://doc.rust-lang.org/std/io/trait.Write.html#method.write_all
1089        ///
1090        /// # Examples
1091        ///
1092        /// Write signed 48 bit big-endian integers to a `Write`:
1093        ///
1094        /// ```rust
1095        /// use tokio_byteorder::{BigEndian, AsyncWriteBytesExt};
1096        ///
1097        /// #[tokio::main]
1098        /// async fn main() {
1099        ///     let mut wtr = Vec::new();
1100        ///     wtr.write_i48::<BigEndian>(-108363435763825).await.unwrap();
1101        ///     wtr.write_i48::<BigEndian>(77).await.unwrap();
1102        ///     assert_eq!(wtr, b"\x9d\x71\xab\xe7\x97\x8f\x00\x00\x00\x00\x00\x4d");
1103        /// }
1104        /// ```
1105        fn write_i48(&mut self, n: i64) -> WriteI48
1106    }
1107
1108    write_impl! {
1109        /// Writes an unsigned 64 bit integer to the underlying writer.
1110        ///
1111        /// # Errors
1112        ///
1113        /// This method returns the same errors as [`Write::write_all`].
1114        ///
1115        /// [`Write::write_all`]: https://doc.rust-lang.org/std/io/trait.Write.html#method.write_all
1116        ///
1117        /// # Examples
1118        ///
1119        /// Write unsigned 64 bit big-endian integers to a `Write`:
1120        ///
1121        /// ```rust
1122        /// use tokio_byteorder::{BigEndian, AsyncWriteBytesExt};
1123        ///
1124        /// #[tokio::main]
1125        /// async fn main() {
1126        ///     let mut wtr = Vec::new();
1127        ///     wtr.write_u64::<BigEndian>(918733457491587).await.unwrap();
1128        ///     wtr.write_u64::<BigEndian>(143).await.unwrap();
1129        ///     assert_eq!(wtr, b"\x00\x03\x43\x95\x4d\x60\x86\x83\x00\x00\x00\x00\x00\x00\x00\x8f");
1130        /// }
1131        /// ```
1132        fn write_u64(&mut self, n: u64) -> WriteU64
1133    }
1134
1135    write_impl! {
1136        /// Writes a signed 64 bit integer to the underlying writer.
1137        ///
1138        /// # Errors
1139        ///
1140        /// This method returns the same errors as [`Write::write_all`].
1141        ///
1142        /// [`Write::write_all`]: https://doc.rust-lang.org/std/io/trait.Write.html#method.write_all
1143        ///
1144        /// # Examples
1145        ///
1146        /// Write signed 64 bit big-endian integers to a `Write`:
1147        ///
1148        /// ```rust
1149        /// use tokio_byteorder::{BigEndian, AsyncWriteBytesExt};
1150        ///
1151        /// #[tokio::main]
1152        /// async fn main() {
1153        ///     let mut wtr = Vec::new();
1154        ///     wtr.write_i64::<BigEndian>(i64::min_value()).await.unwrap();
1155        ///     wtr.write_i64::<BigEndian>(i64::max_value()).await.unwrap();
1156        ///     assert_eq!(wtr, b"\x80\x00\x00\x00\x00\x00\x00\x00\x7f\xff\xff\xff\xff\xff\xff\xff");
1157        /// }
1158        /// ```
1159        fn write_i64(&mut self, n: i64) -> WriteI64
1160    }
1161
1162    write_impl! {
1163        /// Writes an unsigned 128 bit integer to the underlying writer.
1164        fn write_u128(&mut self, n: u128) -> WriteU128
1165    }
1166
1167    write_impl! {
1168        /// Writes a signed 128 bit integer to the underlying writer.
1169        fn write_i128(&mut self, n: i128) -> WriteI128
1170    }
1171
1172    // TODO: write_*int
1173
1174    write_impl! {
1175        /// Writes a IEEE754 single-precision (4 bytes) floating point number to
1176        /// the underlying writer.
1177        ///
1178        /// # Errors
1179        ///
1180        /// This method returns the same errors as [`Write::write_all`].
1181        ///
1182        /// [`Write::write_all`]: https://doc.rust-lang.org/std/io/trait.Write.html#method.write_all
1183        ///
1184        /// # Examples
1185        ///
1186        /// Write a big-endian single-precision floating point number to a `Write`:
1187        ///
1188        /// ```rust
1189        /// use std::f32;
1190        /// use tokio_byteorder::{BigEndian, AsyncWriteBytesExt};
1191        ///
1192        /// #[tokio::main]
1193        /// async fn main() {
1194        ///     let mut wtr = Vec::new();
1195        ///     wtr.write_f32::<BigEndian>(f32::consts::PI).await.unwrap();
1196        ///     assert_eq!(wtr, b"\x40\x49\x0f\xdb");
1197        /// }
1198        /// ```
1199        fn write_f32(&mut self, n: f32) -> WriteF32
1200    }
1201
1202    write_impl! {
1203        /// Writes a IEEE754 double-precision (8 bytes) floating point number to
1204        /// the underlying writer.
1205        ///
1206        /// # Errors
1207        ///
1208        /// This method returns the same errors as [`Write::write_all`].
1209        ///
1210        /// [`Write::write_all`]: https://doc.rust-lang.org/std/io/trait.Write.html#method.write_all
1211        ///
1212        /// # Examples
1213        ///
1214        /// Write a big-endian double-precision floating point number to a `Write`:
1215        ///
1216        /// ```rust
1217        /// use std::f64;
1218        /// use tokio_byteorder::{BigEndian, AsyncWriteBytesExt};
1219        ///
1220        /// #[tokio::main]
1221        /// async fn main() {
1222        ///     let mut wtr = Vec::new();
1223        ///     wtr.write_f64::<BigEndian>(f64::consts::PI).await.unwrap();
1224        ///     assert_eq!(wtr, b"\x40\x09\x21\xfb\x54\x44\x2d\x18");
1225        /// }
1226        /// ```
1227        fn write_f64(&mut self, n: f64) -> WriteF64
1228    }
1229}
1230
1231/// All types that implement `Write` get methods defined in `WriteBytesExt`
1232/// for free.
1233impl<W: io::AsyncWrite + ?Sized> AsyncWriteBytesExt for W {}