diff --git a/src/buf/buf_impl.rs b/src/buf/buf_impl.rs index 843db718f..2ada29d80 100644 --- a/src/buf/buf_impl.rs +++ b/src/buf/buf_impl.rs @@ -1,29 +1,49 @@ -use core::{cmp, ptr, mem}; +use core::{cmp, ptr, mem, fmt}; #[cfg(feature = "std")] use std::io::IoSlice; use alloc::{boxed::Box}; +/// An error which occurred while attempting +/// to get a value from a [`Buf`](trait.Buf.html). +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub enum TryGetError { + /// Indicates that there were not enough remaining + /// bytes in the buffer to read a value. + NotEnoughBytes, +} + +impl fmt::Display for TryGetError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> { + match self { + TryGetError::NotEnoughBytes => write!(f, "Not enough bytes in buffer to read value"), + } + } +} + +#[cfg(feature = "std")] +impl std::error::Error for TryGetError {} + macro_rules! buf_get_impl { ($this:ident, $typ:tt::$conv:tt) => ({ const SIZE: usize = mem::size_of::<$typ>(); - // try to convert directly from the bytes - // this Option trick is to avoid keeping a borrow on self - // when advance() is called (mut borrow) and to call bytes() only once - let ret = $this.bytes().get(..SIZE).map(|src| unsafe { + // Try to convert directly from the bytes. + // This Option trick is to avoid keeping a borrow on self + // when advance() is called (mut borrow) and to call bytes() only once + let ret = $this.bytes().get(..SIZE).map(|src| unsafe { $typ::$conv(*(src as *const _ as *const [_; SIZE])) }); if let Some(ret) = ret { - // if the direct conversion was possible, advance and return + // if the direct conversion was possible, advance and return $this.advance(SIZE); - return ret; + ret } else { // if not we copy the bytes in a temp buffer then convert let mut buf = [0; SIZE]; $this.copy_to_slice(&mut buf); // (do the advance) - return $typ::$conv(buf); + $typ::$conv(buf) } }); (le => $this:ident, $typ:tt, $len_to_read:expr) => ({ @@ -33,15 +53,25 @@ macro_rules! buf_get_impl { // It seems to be linked to the way the method is optimised by the compiler let mut buf = [0; (mem::size_of::<$typ>())]; $this.copy_to_slice(&mut buf[..($len_to_read)]); - return $typ::from_le_bytes(buf); + $typ::from_le_bytes(buf) }); - (be => $this:ident, $typ:tt, $len_to_read:expr) => {{ + (be => $this:ident, $typ:tt, $len_to_read:expr) => ({ debug_assert!(mem::size_of::<$typ>() >= $len_to_read); let mut buf = [0; (mem::size_of::<$typ>())]; $this.copy_to_slice(&mut buf[mem::size_of::<$typ>()-($len_to_read)..]); - return $typ::from_be_bytes(buf); - }}; + $typ::from_be_bytes(buf) + }); +} + +macro_rules! buf_try_get_impl { + ($this:ident, $typ:tt::$conv:tt) => ({ + if $this.remaining() < mem::size_of::<$typ>() { + Err(TryGetError::NotEnoughBytes) + } else { + Ok(buf_get_impl!($this, $typ::$conv)) + } + }); } /// Read bytes from a buffer. @@ -54,6 +84,11 @@ macro_rules! buf_get_impl { /// /// The simplest `Buf` is a `&[u8]`. /// +/// Two sets of methods are provided for reading values: +/// `get_*` and `try_get_*`. When there are not enough +/// remaining bytes in the buffer to read a value, the `get_*` +/// methods panic, while the `try_get_*` methods return a [`TryGetError`](enum.TryGetError.html). +/// /// ``` /// use bytes::Buf; /// @@ -97,8 +132,9 @@ pub trait Buf { fn remaining(&self) -> usize; /// Returns a slice starting at the current position and of length between 0 - /// and `Buf::remaining()`. Note that this *can* return shorter slice (this allows - /// non-continuous internal representation). + /// and `Buf::remaining()`. Note that while this *can* return a shorter slice + /// (this allows non-continuous internal representation) it should not return + /// an empty slice unless there are no bytes remaining. /// /// This is a lower level function. Most operations are done with other /// functions. @@ -251,8 +287,7 @@ pub trait Buf { let src = self.bytes(); cnt = cmp::min(src.len(), dst.len() - off); - ptr::copy_nonoverlapping( - src.as_ptr(), dst[off..].as_mut_ptr(), cnt); + ptr::copy_nonoverlapping(src.as_ptr(), dst[off..].as_mut_ptr(), cnt); off += cnt; } @@ -324,7 +359,7 @@ pub trait Buf { /// /// This function panics if there is not enough remaining data in `self`. fn get_u16(&mut self) -> u16 { - buf_get_impl!(self, u16::from_be_bytes); + buf_get_impl!(self, u16::from_be_bytes) } /// Gets an unsigned 16 bit integer from `self` in little-endian byte order. @@ -344,7 +379,7 @@ pub trait Buf { /// /// This function panics if there is not enough remaining data in `self`. fn get_u16_le(&mut self) -> u16 { - buf_get_impl!(self, u16::from_le_bytes); + buf_get_impl!(self, u16::from_le_bytes) } /// Gets a signed 16 bit integer from `self` in big-endian byte order. @@ -364,7 +399,7 @@ pub trait Buf { /// /// This function panics if there is not enough remaining data in `self`. fn get_i16(&mut self) -> i16 { - buf_get_impl!(self, i16::from_be_bytes); + buf_get_impl!(self, i16::from_be_bytes) } /// Gets a signed 16 bit integer from `self` in little-endian byte order. @@ -384,7 +419,7 @@ pub trait Buf { /// /// This function panics if there is not enough remaining data in `self`. fn get_i16_le(&mut self) -> i16 { - buf_get_impl!(self, i16::from_le_bytes); + buf_get_impl!(self, i16::from_le_bytes) } /// Gets an unsigned 32 bit integer from `self` in the big-endian byte order. @@ -404,7 +439,7 @@ pub trait Buf { /// /// This function panics if there is not enough remaining data in `self`. fn get_u32(&mut self) -> u32 { - buf_get_impl!(self, u32::from_be_bytes); + buf_get_impl!(self, u32::from_be_bytes) } /// Gets an unsigned 32 bit integer from `self` in the little-endian byte order. @@ -424,7 +459,7 @@ pub trait Buf { /// /// This function panics if there is not enough remaining data in `self`. fn get_u32_le(&mut self) -> u32 { - buf_get_impl!(self, u32::from_le_bytes); + buf_get_impl!(self, u32::from_le_bytes) } /// Gets a signed 32 bit integer from `self` in big-endian byte order. @@ -444,7 +479,7 @@ pub trait Buf { /// /// This function panics if there is not enough remaining data in `self`. fn get_i32(&mut self) -> i32 { - buf_get_impl!(self, i32::from_be_bytes); + buf_get_impl!(self, i32::from_be_bytes) } /// Gets a signed 32 bit integer from `self` in little-endian byte order. @@ -464,7 +499,7 @@ pub trait Buf { /// /// This function panics if there is not enough remaining data in `self`. fn get_i32_le(&mut self) -> i32 { - buf_get_impl!(self, i32::from_le_bytes); + buf_get_impl!(self, i32::from_le_bytes) } /// Gets an unsigned 64 bit integer from `self` in big-endian byte order. @@ -484,7 +519,7 @@ pub trait Buf { /// /// This function panics if there is not enough remaining data in `self`. fn get_u64(&mut self) -> u64 { - buf_get_impl!(self, u64::from_be_bytes); + buf_get_impl!(self, u64::from_be_bytes) } /// Gets an unsigned 64 bit integer from `self` in little-endian byte order. @@ -504,7 +539,7 @@ pub trait Buf { /// /// This function panics if there is not enough remaining data in `self`. fn get_u64_le(&mut self) -> u64 { - buf_get_impl!(self, u64::from_le_bytes); + buf_get_impl!(self, u64::from_le_bytes) } /// Gets a signed 64 bit integer from `self` in big-endian byte order. @@ -524,7 +559,7 @@ pub trait Buf { /// /// This function panics if there is not enough remaining data in `self`. fn get_i64(&mut self) -> i64 { - buf_get_impl!(self, i64::from_be_bytes); + buf_get_impl!(self, i64::from_be_bytes) } /// Gets a signed 64 bit integer from `self` in little-endian byte order. @@ -544,7 +579,7 @@ pub trait Buf { /// /// This function panics if there is not enough remaining data in `self`. fn get_i64_le(&mut self) -> i64 { - buf_get_impl!(self, i64::from_le_bytes); + buf_get_impl!(self, i64::from_le_bytes) } /// Gets an unsigned 128 bit integer from `self` in big-endian byte order. @@ -564,7 +599,7 @@ pub trait Buf { /// /// This function panics if there is not enough remaining data in `self`. fn get_u128(&mut self) -> u128 { - buf_get_impl!(self, u128::from_be_bytes); + buf_get_impl!(self, u128::from_be_bytes) } /// Gets an unsigned 128 bit integer from `self` in little-endian byte order. @@ -584,7 +619,7 @@ pub trait Buf { /// /// This function panics if there is not enough remaining data in `self`. fn get_u128_le(&mut self) -> u128 { - buf_get_impl!(self, u128::from_le_bytes); + buf_get_impl!(self, u128::from_le_bytes) } /// Gets a signed 128 bit integer from `self` in big-endian byte order. @@ -604,7 +639,7 @@ pub trait Buf { /// /// This function panics if there is not enough remaining data in `self`. fn get_i128(&mut self) -> i128 { - buf_get_impl!(self, i128::from_be_bytes); + buf_get_impl!(self, i128::from_be_bytes) } /// Gets a signed 128 bit integer from `self` in little-endian byte order. @@ -624,7 +659,7 @@ pub trait Buf { /// /// This function panics if there is not enough remaining data in `self`. fn get_i128_le(&mut self) -> i128 { - buf_get_impl!(self, i128::from_le_bytes); + buf_get_impl!(self, i128::from_le_bytes) } /// Gets an unsigned n-byte integer from `self` in big-endian byte order. @@ -644,7 +679,7 @@ pub trait Buf { /// /// This function panics if there is not enough remaining data in `self`. fn get_uint(&mut self, nbytes: usize) -> u64 { - buf_get_impl!(be => self, u64, nbytes); + buf_get_impl!(be => self, u64, nbytes) } /// Gets an unsigned n-byte integer from `self` in little-endian byte order. @@ -664,7 +699,7 @@ pub trait Buf { /// /// This function panics if there is not enough remaining data in `self`. fn get_uint_le(&mut self, nbytes: usize) -> u64 { - buf_get_impl!(le => self, u64, nbytes); + buf_get_impl!(le => self, u64, nbytes) } /// Gets a signed n-byte integer from `self` in big-endian byte order. @@ -684,7 +719,7 @@ pub trait Buf { /// /// This function panics if there is not enough remaining data in `self`. fn get_int(&mut self, nbytes: usize) -> i64 { - buf_get_impl!(be => self, i64, nbytes); + buf_get_impl!(be => self, i64, nbytes) } /// Gets a signed n-byte integer from `self` in little-endian byte order. @@ -704,7 +739,7 @@ pub trait Buf { /// /// This function panics if there is not enough remaining data in `self`. fn get_int_le(&mut self, nbytes: usize) -> i64 { - buf_get_impl!(le => self, i64, nbytes); + buf_get_impl!(le => self, i64, nbytes) } /// Gets an IEEE754 single-precision (4 bytes) floating point number from @@ -791,6 +826,780 @@ pub trait Buf { f64::from_bits(Self::get_u64_le(self)) } + /// Copies bytes from `self` into `dst`. + /// + /// If the operation succeeds, the + /// cursor is advanced by the number of bytes copied. + /// + /// Returns `Err(TryGetError::NotEnoughBytes)` when there are + /// not enough remaining bytes to fill `dst`. In this event, + /// `dst` is not mutated. + /// + /// # Examples + /// + /// ``` + /// use bytes::Buf; + /// + /// let mut buf = &b"hello world"[..]; + /// let mut dst = [0; 5]; + /// + /// buf.try_copy_to_slice(&mut dst).unwrap(); + /// assert_eq!(&b"hello"[..], &dst); + /// assert_eq!(6, buf.remaining()); + /// ``` + /// + /// ``` + /// use bytes::Buf; + /// let mut buf = &b"he"[..]; + /// let mut dst = [0; 5]; + /// + /// assert!(buf.try_copy_to_slice(&mut dst).is_err()); + /// ``` + fn try_copy_to_slice(&mut self, dst: &mut [u8]) -> Result<(), TryGetError> { + if self.remaining() < dst.len() { + Err(TryGetError::NotEnoughBytes) + } else { + Ok(self.copy_to_slice(dst)) + } + } + + /// Gets an unsigned 8 bit integer from `self`. + /// + /// Returns `Err(TryGetError::NotEnoughBytes)` when there are not enough + /// remaining bytes to read the value. + /// + /// If the operation succeeds, the current position is advanced by 1. + /// + /// # Examples + /// + /// ``` + /// use bytes::Buf; + /// + /// let mut buf = &b"\x08 hello"[..]; + /// assert_eq!(8, buf.try_get_u8().unwrap()); + /// ``` + /// + /// ``` + /// use bytes::Buf; + /// + /// let mut buf: &[u8] = &[]; + /// assert!(buf.try_get_u8().is_err()); + /// ``` + fn try_get_u8(&mut self) -> Result { + if !self.has_remaining() { + Err(TryGetError::NotEnoughBytes) + } else { + Ok(self.get_u8()) + } + } + + /// Gets a signed 8 bit integer from `self`. + /// + /// Returns `Err(TryGetError::NotEnoughBytes)` when there are not enough + /// remaining bytes to read the value. + /// + /// If the operation succeeds, the current position is advanced by 1. + /// + /// # Examples + /// + /// ``` + /// use bytes::Buf; + /// + /// let mut buf = &b"\x08 hello"[..]; + /// assert_eq!(8, buf.try_get_i8().unwrap()); + /// ``` + /// + /// ``` + /// use bytes::Buf; + /// + /// let mut buf: &[u8] = &[]; + /// assert!(buf.try_get_i8().is_err()); + /// ``` + fn try_get_i8(&mut self) -> Result { + if !self.has_remaining() { + Err(TryGetError::NotEnoughBytes) + } else { + Ok(self.get_i8()) + } + } + + /// Gets an unsigned 16 bit integer from `self` in big-endian + /// byte order. + /// + /// Returns `Err(TryGetError::NotEnoughBytes)` when there are not enough + /// remaining bytes to read the value. + /// + /// If the operation succeeds, the current position is advanced by 2. + /// + /// # Examples + /// + /// ``` + /// use bytes::{Buf, TryGetError}; + /// + /// let mut buf = &b"\x08\x09 hello"[..]; + /// assert_eq!(0x0809, buf.try_get_u16().unwrap()); + /// ``` + /// + /// ``` + /// use bytes::Buf; + /// + /// let mut buf: &[u8] = &[2]; + /// assert!(buf.try_get_u16().is_err()); + /// ``` + fn try_get_u16(&mut self) -> Result { + buf_try_get_impl!(self, u16::from_be_bytes) + } + + /// Gets an unsigned 16 bit integer from `self` in little-endian + /// byte order. + /// + /// Returns `Err(TryGetError::NotEnoughBytes)` when there are not enough + /// remaining bytes to read the value. + /// + /// If the operation succeeds, the current position is advanced by 2. + /// + /// # Examples + /// + /// ``` + /// use bytes::{Buf, TryGetError}; + /// + /// let mut buf = &b"\x09\x08 hello"[..]; + /// assert_eq!(0x0809, buf.try_get_u16_le().unwrap()); + /// ``` + /// + /// ``` + /// use bytes::Buf; + /// + /// let mut buf: &[u8] = &[2]; + /// assert!(buf.try_get_u16_le().is_err()); + /// ``` + fn try_get_u16_le(&mut self) -> Result { + buf_try_get_impl!(self, u16::from_le_bytes) + } + + /// Gets a signed 16 bit integer from `self` in big-endian + /// byte order. + /// + /// Returns `Err(TryGetError::NotEnoughBytes)` when there are not enough + /// remaining bytes to read the value. + /// + /// If the operation succeeds, the current position is advanced by 2. + /// + /// # Examples + /// + /// ``` + /// use bytes::{Buf, TryGetError}; + /// + /// let mut buf = &b"\x08\x09 hello"[..]; + /// assert_eq!(0x0809, buf.try_get_i16().unwrap()); + /// ``` + /// + /// ``` + /// use bytes::Buf; + /// + /// let mut buf: &[u8] = &[2]; + /// assert!(buf.try_get_i16().is_err()); + /// ``` + fn try_get_i16(&mut self) -> Result { + buf_try_get_impl!(self, i16::from_be_bytes) + } + + /// Gets a signed 16 bit integer from `self` in little-endian + /// byte order. + /// + /// Returns `Err(TryGetError::NotEnoughBytes)` when there are not enough + /// remaining bytes to read the value. + /// + /// If the operation succeeds, the current position is advanced by 2. + /// + /// # Examples + /// + /// ``` + /// use bytes::{Buf, TryGetError}; + /// + /// let mut buf = &b"\x09\x08 hello"[..]; + /// assert_eq!(0x0809, buf.try_get_i16_le().unwrap()); + /// ``` + /// + /// ``` + /// use bytes::Buf; + /// + /// let mut buf: &[u8] = &[2]; + /// assert!(buf.try_get_i16_le().is_err()); + /// ``` + fn try_get_i16_le(&mut self) -> Result { + buf_try_get_impl!(self, i16::from_le_bytes) + } + + /// Gets an unsigned 32 bit integer from `self` in big-endian + /// byte order. + /// + /// Returns `Err(TryGetError::NotEnoughBytes)` when there are not enough + /// remaining bytes to read the value. + /// + /// If the operation succeeds, the current position is advanced by 4. + /// + /// # Examples + /// + /// ``` + /// use bytes::{Buf, TryGetError}; + /// + /// let mut buf = &b"\x08\x09\xA0\xA1 hello"[..]; + /// assert_eq!(0x0809A0A1, buf.try_get_u32().unwrap()); + /// ``` + /// + /// ``` + /// use bytes::Buf; + /// + /// let mut buf: &[u8] = &[1, 2, 3]; + /// assert!(buf.try_get_u32().is_err()); + /// ``` + fn try_get_u32(&mut self) -> Result { + buf_try_get_impl!(self, u32::from_be_bytes) + } + + /// Gets an unsigned 32 bit integer from `self` in little-endian + /// byte order. + /// + /// Returns `Err(TryGetError::NotEnoughBytes)` when there are not enough + /// remaining bytes to read the value. + /// + /// If the operation succeeds, the current position is advanced by 4. + /// + /// # Examples + /// + /// ``` + /// use bytes::{Buf, TryGetError}; + /// + /// let mut buf = &b"\xA1\xA0\x09\x08 hello"[..]; + /// assert_eq!(0x0809A0A1, buf.try_get_u32_le().unwrap()); + /// ``` + /// + /// ``` + /// use bytes::Buf; + /// + /// let mut buf: &[u8] = &[1, 2, 3]; + /// assert!(buf.try_get_u32_le().is_err()); + /// ``` + fn try_get_u32_le(&mut self) -> Result { + buf_try_get_impl!(self, u32::from_le_bytes) + } + + /// Gets a signed 32 bit integer from `self` in big-endian + /// byte order. + /// + /// Returns `Err(TryGetError::NotEnoughBytes)` when there are not enough + /// remaining bytes to read the value. + /// + /// If the operation succeeds, the current position is advanced by 4. + /// + /// # Examples + /// + /// ``` + /// use bytes::{Buf, TryGetError}; + /// + /// let mut buf = &b"\x08\x09\xA0\xA1 hello"[..]; + /// assert_eq!(0x0809A0A1, buf.try_get_i32().unwrap()); + /// ``` + /// + /// ``` + /// use bytes::Buf; + /// + /// let mut buf: &[u8] = &[1, 2, 3]; + /// assert!(buf.try_get_i32().is_err()); + /// ``` + fn try_get_i32(&mut self) -> Result { + buf_try_get_impl!(self, i32::from_be_bytes) + } + + /// Gets a signed 32 bit integer from `self` in little-endian + /// byte order. + /// + /// Returns `Err(TryGetError::NotEnoughBytes)` when there are not enough + /// remaining bytes to read the value. + /// + /// If the operation succeeds, the current position is advanced by 4. + /// + /// # Examples + /// + /// ``` + /// use bytes::{Buf, TryGetError}; + /// + /// let mut buf = &b"\xA1\xA0\x09\x08 hello"[..]; + /// assert_eq!(0x0809A0A1, buf.try_get_i32_le().unwrap()); + /// ``` + /// + /// ``` + /// use bytes::Buf; + /// + /// let mut buf: &[u8] = &[1, 2, 3]; + /// assert!(buf.try_get_i32_le().is_err()); + /// ``` + fn try_get_i32_le(&mut self) -> Result { + buf_try_get_impl!(self, i32::from_le_bytes) + } + + + /// Gets an unsigned 64 bit integer from `self` in big-endian + /// byte order. + /// + /// Returns `Err(TryGetError::NotEnoughBytes)` when there are not enough + /// remaining bytes to read the value. + /// + /// If the operation succeeds, the current position is advanced by 8. + /// + /// # Examples + /// + /// ``` + /// use bytes::{Buf, TryGetError}; + /// + /// let mut buf = &b"\x01\x02\x03\x04\x05\x06\x07\x08 hello"[..]; + /// assert_eq!(0x0102030405060708, buf.try_get_u64().unwrap()); + /// ``` + /// + /// ``` + /// use bytes::Buf; + /// + /// let mut buf: &[u8] = &[1, 2, 3, 4, 5, 6, 7]; + /// assert!(buf.try_get_u64().is_err()); + /// ``` + fn try_get_u64(&mut self) -> Result { + buf_try_get_impl!(self, u64::from_be_bytes) + } + + /// Gets an unsigned 64 bit integer from `self` in little-endian + /// byte order. + /// + /// Returns `Err(TryGetError::NotEnoughBytes)` when there are not enough + /// remaining bytes to read the value. + /// + /// If the operation succeeds, the current position is advanced by 8. + /// + /// # Examples + /// + /// ``` + /// use bytes::{Buf, TryGetError}; + /// + /// let mut buf = &b"\x08\x07\x06\x05\x04\x03\x02\x01 hello"[..]; + /// assert_eq!(0x0102030405060708, buf.try_get_u64_le().unwrap()); + /// ``` + /// + /// ``` + /// use bytes::Buf; + /// + /// let mut buf: &[u8] = &[1, 2, 3, 4, 5, 6, 7]; + /// assert!(buf.try_get_u64_le().is_err()); + /// ``` + fn try_get_u64_le(&mut self) -> Result { + buf_try_get_impl!(self, u64::from_le_bytes) + } + + /// Gets a signed 64 bit integer from `self` in big-endian + /// byte order. + /// + /// Returns `Err(TryGetError::NotEnoughBytes)` when there are not enough + /// remaining bytes to read the value. + /// + /// If the operation succeeds, the current position is advanced by 8. + /// + /// # Examples + /// + /// ``` + /// use bytes::{Buf, TryGetError}; + /// + /// let mut buf = &b"\x01\x02\x03\x04\x05\x06\x07\x08 hello"[..]; + /// assert_eq!(0x0102030405060708, buf.try_get_i64().unwrap()); + /// ``` + /// + /// ``` + /// use bytes::Buf; + /// + /// let mut buf: &[u8] = &[1, 2, 3, 4, 5, 6, 7]; + /// assert!(buf.try_get_i64().is_err()); + /// ``` + fn try_get_i64(&mut self) -> Result { + buf_try_get_impl!(self, i64::from_be_bytes) + } + + /// Gets a signed 64 bit integer from `self` in little-endian + /// byte order. + /// + /// Returns `Err(TryGetError::NotEnoughBytes)` when there are not enough + /// remaining bytes to read the value. + /// + /// If the operation succeeds, the current position is advanced by 8. + /// + /// # Examples + /// + /// ``` + /// use bytes::{Buf, TryGetError}; + /// + /// let mut buf = &b"\x08\x07\x06\x05\x04\x03\x02\x01 hello"[..]; + /// assert_eq!(0x0102030405060708, buf.try_get_i64_le().unwrap()); + /// ``` + /// + /// ``` + /// use bytes::Buf; + /// + /// let mut buf: &[u8] = &[1, 2, 3, 4, 5, 6, 7]; + /// assert!(buf.try_get_i64_le().is_err()); + /// ``` + fn try_get_i64_le(&mut self) -> Result { + buf_try_get_impl!(self, i64::from_le_bytes) + } + + /// Gets an unsigned 128 bit integer from `self` in big-endian + /// byte order. + /// + /// **NOTE:** This method requires the `i128` feature. + /// + /// Returns `Err(TryGetError::NotEnoughBytes)` when there are not enough + /// remaining bytes to read the value. + /// + /// If the operation succeeds, the current position is advanced by 16. + /// + /// # Examples + /// + /// ``` + /// use bytes::{Buf, TryGetError}; + /// + /// let mut buf = &b"\x01\x02\x03\x04\x05\x06\x07\x08\x09\x10\x11\x12\x13\x14\x15\x16 hello"[..]; + /// assert_eq!(0x01020304050607080910111213141516, buf.try_get_u128().unwrap()); + /// ``` + /// + /// ``` + /// use bytes::Buf; + /// + /// let mut buf: &[u8] = &[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]; + /// assert!(buf.try_get_u128().is_err()); + /// ``` + #[cfg(feature = "i128")] + fn try_get_u128(&mut self) -> Result { + buf_try_get_impl!(self, u128::from_be_bytes) + } + + /// Gets an unsigned 128 bit integer from `self` in little-endian + /// byte order. + /// + /// **NOTE:** This method requires the `i128` feature. + /// + /// Returns `Err(TryGetError::NotEnoughBytes)` when there are not enough + /// remaining bytes to read the value. + /// + /// If the operation succeeds, the current position is advanced by 16. + /// + /// # Examples + /// + /// ``` + /// use bytes::{Buf, TryGetError}; + /// + /// let mut buf = &b"\x16\x15\x14\x13\x12\x11\x10\x09\x08\x07\x06\x05\x04\x03\x02\x01 hello"[..]; + /// assert_eq!(0x01020304050607080910111213141516, buf.try_get_u128_le().unwrap()); + /// ``` + /// + /// ``` + /// use bytes::Buf; + /// + /// let mut buf: &[u8] = &[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]; + /// assert!(buf.try_get_u128_le().is_err()); + /// ``` + #[cfg(feature = "i128")] + fn try_get_u128_le(&mut self) -> Result { + buf_try_get_impl!(self, u128::from_le_bytes) + } + + /// Gets a signed 128 bit integer from `self` in big-endian + /// byte order. + /// + /// **NOTE:** This method requires the `i128` feature. + /// + /// Returns `Err(TryGetError::NotEnoughBytes)` when there are not enough + /// remaining bytes to read the value. + /// + /// If the operation succeeds, the current position is advanced by 16. + /// + /// # Examples + /// + /// ``` + /// use bytes::{Buf, TryGetError}; + /// + /// let mut buf = &b"\x01\x02\x03\x04\x05\x06\x07\x08\x09\x10\x11\x12\x13\x14\x15\x16 hello"[..]; + /// assert_eq!(0x01020304050607080910111213141516, buf.try_get_i128().unwrap()); + /// ``` + /// + /// ``` + /// use bytes::Buf; + /// + /// let mut buf: &[u8] = &[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]; + /// assert!(buf.try_get_i128().is_err()); + /// ``` + #[cfg(feature = "i128")] + fn try_get_i128(&mut self) -> Result { + buf_try_get_impl!(self, i128::from_be_bytes) + } + + /// Gets a signed 128 bit integer from `self` in little-endian + /// byte order. + /// + /// **NOTE:** This method requires the `i128` feature. + /// + /// Returns `Err(TryGetError::NotEnoughBytes)` when there are not enough + /// remaining bytes to read the value. + /// + /// If the operation succeeds, the current position is advanced by 16. + /// + /// # Examples + /// + /// ``` + /// use bytes::{Buf, TryGetError}; + /// + /// let mut buf = &b"\x16\x15\x14\x13\x12\x11\x10\x09\x08\x07\x06\x05\x04\x03\x02\x01 hello"[..]; + /// assert_eq!(0x01020304050607080910111213141516, buf.try_get_i128_le().unwrap()); + /// ``` + /// + /// ``` + /// use bytes::Buf; + /// + /// let mut buf: &[u8] = &[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]; + /// assert!(buf.try_get_i128_le().is_err()); + /// ``` + #[cfg(feature = "i128")] + fn try_get_i128_le(&mut self) -> Result { + buf_try_get_impl!(self, i128::from_le_bytes) + } + + /// Gets an unsigned n-byte integer from `self` in big-endian + /// byte order. + /// + /// Returns `Err(TryGetError::NotEnoughBytes)` when there are not enough + /// remaining bytes to read the value. + /// + /// If the operation succeeds, the current position is advanced by `nbytes`. + /// + /// # Examples + /// + /// ``` + /// use bytes::{Buf, TryGetError}; + /// + /// let mut buf = &b"\x01\x02\x03 hello"[..]; + /// assert_eq!(0x010203, buf.try_get_uint(3).unwrap()); + /// ``` + /// + /// ``` + /// use bytes::Buf; + /// + /// let mut buf: &[u8] = &[1, 2]; + /// assert!(buf.try_get_uint(3).is_err()); + /// ``` + fn try_get_uint(&mut self, nbytes: usize) -> Result { + if self.remaining() < nbytes { + Err(TryGetError::NotEnoughBytes) + } else { + Ok(self.get_uint(nbytes)) + } + } + + /// Gets an unsigned n-byte integer from `self` in little-endian + /// byte order. + /// + /// Returns `Err(TryGetError::NotEnoughBytes)` when there are not enough + /// remaining bytes to read the value. + /// + /// If the operation succeeds, the current position is advanced by `nbytes`. + /// + /// # Examples + /// + /// ``` + /// use bytes::{Buf, TryGetError}; + /// + /// let mut buf = &b"\x03\x02\x01 hello"[..]; + /// assert_eq!(0x010203, buf.try_get_uint_le(3).unwrap()); + /// ``` + /// + /// ``` + /// use bytes::Buf; + /// + /// let mut buf: &[u8] = &[1, 2]; + /// assert!(buf.try_get_uint_le(3).is_err()); + /// ``` + fn try_get_uint_le(&mut self, nbytes: usize) -> Result { + if self.remaining() < nbytes { + Err(TryGetError::NotEnoughBytes) + } else { + Ok(self.get_uint_le(nbytes)) + } + } + + /// Gets a signed n-byte integer from `self` in big-endian + /// byte order. + /// + /// Returns `Err(TryGetError::NotEnoughBytes)` when there are not enough + /// remaining bytes to read the value. + /// + /// If the operation succeeds, the current position is advanced by `nbytes`. + /// + /// # Examples + /// + /// ``` + /// use bytes::{Buf, TryGetError}; + /// + /// let mut buf = &b"\x01\x02\x03 hello"[..]; + /// assert_eq!(0x010203, buf.try_get_int(3).unwrap()); + /// ``` + /// + /// ``` + /// use bytes::Buf; + /// + /// let mut buf: &[u8] = &[1, 2]; + /// assert!(buf.try_get_int(3).is_err()); + /// ``` + fn try_get_int(&mut self, nbytes: usize) -> Result { + if self.remaining() < nbytes { + Err(TryGetError::NotEnoughBytes) + } else { + Ok(self.get_int(nbytes)) + } + } + + /// Gets a signed n-byte integer from `self` in little-endian + /// byte order. + /// + /// Returns `Err(TryGetError::NotEnoughBytes)` when there are not enough + /// remaining bytes to read the value. + /// + /// If the operation succeeds, the current position is advanced by `nbytes`. + /// + /// # Examples + /// + /// ``` + /// use bytes::{Buf, TryGetError}; + /// + /// let mut buf = &b"\x03\x02\x01 hello"[..]; + /// assert_eq!(0x010203, buf.try_get_int_le(3).unwrap()); + /// ``` + /// + /// ``` + /// use bytes::Buf; + /// + /// let mut buf: &[u8] = &[1, 2]; + /// assert!(buf.try_get_int_le(3).is_err()); + /// ``` + fn try_get_int_le(&mut self, nbytes: usize) -> Result { + if self.remaining() < nbytes { + Err(TryGetError::NotEnoughBytes) + } else { + Ok(self.get_int_le(nbytes)) + } + } + + /// Gets an IEEE754 single-precision (4 bytes) floating point number from + /// `self` in big-endian byte order. + /// + /// Returns `Err(TryGetError::NotEnoughBytes)` when there are not enough + /// remaining bytes to read the value. + /// + /// If the operation succeeds, the current position is advanced by 4. + /// + /// # Examples + /// + /// ``` + /// use bytes::Buf; + /// + /// let mut buf = &b"\x3F\x99\x99\x9A hello"[..]; + /// assert_eq!(1.2f32, buf.try_get_f32().unwrap()); + /// ``` + /// + /// ``` + /// use bytes::Buf; + /// + /// let mut buf: &[u8] = &[0, 1, 2]; + /// assert!(buf.try_get_f32().is_err()); + /// ``` + fn try_get_f32(&mut self) -> Result { + Self::try_get_u32(self).map(f32::from_bits) + } + + /// Gets an IEEE754 single-precision (4 bytes) floating point number from + /// `self` in little-endian byte order. + /// + /// Returns `Err(TryGetError::NotEnoughBytes)` when there are not enough + /// remaining bytes to read the value. + /// + /// If the operation succeeds, the current position is advanced by 4. + /// + /// # Examples + /// + /// ``` + /// use bytes::Buf; + /// + /// let mut buf = &b"\x9A\x99\x99\x3F hello"[..]; + /// assert_eq!(1.2f32, buf.try_get_f32_le().unwrap()); + /// ``` + /// + /// ``` + /// use bytes::Buf; + /// + /// let mut buf: &[u8] = &[0, 1, 2]; + /// assert!(buf.try_get_f32_le().is_err()); + /// ``` + fn try_get_f32_le(&mut self) -> Result { + Self::try_get_u32_le(self).map(f32::from_bits) + } + + /// Gets an IEEE754 double-precision (8 bytes) floating point number from + /// `self` in big-endian byte order. + /// + /// Returns `Err(TryGetError::NotEnoughBytes)` when there are not enough + /// remaining bytes to read the value. + /// + /// If the operation succeeds, the current position is advanced by 8. + /// + /// # Examples + /// + /// ``` + /// use bytes::Buf; + /// + /// let mut buf = &b"\x3F\xF3\x33\x33\x33\x33\x33\x33 hello"[..]; + /// assert_eq!(1.2f64, buf.try_get_f64().unwrap()); + /// ``` + /// + /// ``` + /// use bytes::Buf; + /// + /// let mut buf: &[u8] = &[0, 1, 2]; + /// assert!(buf.try_get_f64().is_err()); + /// ``` + fn try_get_f64(&mut self) -> Result { + Self::try_get_u64(self).map(f64::from_bits) + } + + /// Gets an IEEE754 double-precision (8 bytes) floating point number from + /// `self` in little-endian byte order. + /// + /// Returns `Err(TryGetError::NotEnoughBytes)` when there are not enough + /// remaining bytes to read the value. + /// + /// If the operation succeeds, the current position is advanced by 8. + /// + /// # Examples + /// + /// ``` + /// use bytes::Buf; + /// + /// let mut buf = &b"\x33\x33\x33\x33\x33\x33\xF3\x3F hello"[..]; + /// assert_eq!(1.2f64, buf.try_get_f64_le().unwrap()); + /// ``` + /// + /// ``` + /// use bytes::Buf; + /// + /// let mut buf: &[u8] = &[0, 1, 2]; + /// assert!(buf.try_get_f64_le().is_err()); + /// ``` + fn try_get_f64_le(&mut self) -> Result { + Self::try_get_u64_le(self).map(f64::from_bits) + } + /// Consumes remaining bytes inside self and returns new instance of `Bytes` /// /// # Examples @@ -950,7 +1759,8 @@ impl Buf for Option<[u8; 1]> { } fn bytes(&self) -> &[u8] { - self.as_ref().map(AsRef::as_ref) + self.as_ref() + .map(AsRef::as_ref) .unwrap_or(Default::default()) } diff --git a/src/buf/mod.rs b/src/buf/mod.rs index d4538f21e..28311e207 100644 --- a/src/buf/mod.rs +++ b/src/buf/mod.rs @@ -22,7 +22,7 @@ pub mod ext; mod iter; mod vec_deque; -pub use self::buf_impl::Buf; +pub use self::buf_impl::{Buf, TryGetError}; pub use self::buf_mut::BufMut; pub use self::ext::{BufExt, BufMutExt}; #[cfg(feature = "std")] diff --git a/src/lib.rs b/src/lib.rs index a61e3476a..661d652f3 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -82,6 +82,7 @@ pub mod buf; pub use crate::buf::{ Buf, BufMut, + TryGetError, }; mod bytes_mut;