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 {}