smol-bytes 0.1.7

High-performance, clone-efficient byte buffers optimized for small data.
Documentation
macro_rules! method_forward {
  ($repr:tt { $(
    $(#[$meta:meta])*
    fn $name:ident($( $arg:ident : $arg_ty:ty ),*) $(-> $ret:ty)?
  );+$(;)? }) => {
    $(
      $(#[$meta])*
      #[cfg_attr(not(coverage), inline(always))]
      fn $name(&mut self, $( $arg : $arg_ty ),*) $(-> $ret)? {
        match &mut self.$repr {
          Repr::Inline(buffer) => buffer.$name($( $arg ),*),
          Repr::Heap(bytes) => bytes.$name($( $arg ),*),
        }
      }
    )*
  };
  ($(
    $(#[$meta:meta])*
    fn $name:ident($($arg:ident : $arg_ty:ty ),*) $(-> $ret:ty)?
  );+$(;)?) => {
    $(
      $(#[$meta])*
      #[cfg_attr(not(coverage), inline(always))]
      fn $name(&mut self, $( $arg : $arg_ty ),*) $(-> $ret)? {
        Self::$name(self, $( $arg ),*)
      }
    )*
  };
}

macro_rules! forward_buf {
  ($repr:tt { $($suffix:ident), +$(,)? }) => {
    paste::paste! {
      $(
        $crate::macros::method_forward! { $repr {
          fn [< get_ $suffix >]() -> $suffix;
          fn [< get_ $suffix _le >]() -> $suffix;
          fn [< get_ $suffix _ne >]() -> $suffix;
          fn [< try_get_ $suffix >]() -> Result<$suffix, $crate::TryGetError>;
          fn [< try_get_ $suffix _le >]() -> Result<$suffix, $crate::TryGetError>;
          fn [< try_get_ $suffix _ne >]() -> Result<$suffix, $crate::TryGetError>;
        }}
      )*

      $crate::macros::method_forward! {$repr {
        fn get_i8() -> i8;
        fn get_u8() -> u8;
        fn try_get_i8() -> Result<i8, $crate::TryGetError>;
        fn try_get_u8() -> Result<u8, $crate::TryGetError>;

      }}

      #[cfg_attr(not(coverage), inline(always))]
      fn get_uint(&mut self, nbytes: usize) -> u64 {
        $crate::buffer::assert_uint_width(nbytes);
        match &mut self.$repr {
          Repr::Inline(buffer) => buffer.get_uint(nbytes),
          Repr::Heap(bytes) => bytes.get_uint(nbytes),
        }
      }

      #[cfg_attr(not(coverage), inline(always))]
      fn get_uint_le(&mut self, nbytes: usize) -> u64 {
        $crate::buffer::assert_uint_width(nbytes);
        match &mut self.$repr {
          Repr::Inline(buffer) => buffer.get_uint_le(nbytes),
          Repr::Heap(bytes) => bytes.get_uint_le(nbytes),
        }
      }

      #[cfg_attr(not(coverage), inline(always))]
      fn get_uint_ne(&mut self, nbytes: usize) -> u64 {
        $crate::buffer::assert_uint_width(nbytes);
        match &mut self.$repr {
          Repr::Inline(buffer) => buffer.get_uint_ne(nbytes),
          Repr::Heap(bytes) => bytes.get_uint_ne(nbytes),
        }
      }

      #[cfg_attr(not(coverage), inline(always))]
      fn try_get_uint(&mut self, nbytes: usize) -> Result<u64, $crate::TryGetError> {
        $crate::buffer::assert_uint_width(nbytes);
        match &mut self.$repr {
          Repr::Inline(buffer) => buffer.try_get_uint(nbytes),
          Repr::Heap(bytes) => bytes.try_get_uint(nbytes),
        }
      }

      #[cfg_attr(not(coverage), inline(always))]
      fn try_get_uint_le(&mut self, nbytes: usize) -> Result<u64, $crate::TryGetError> {
        $crate::buffer::assert_uint_width(nbytes);
        match &mut self.$repr {
          Repr::Inline(buffer) => buffer.try_get_uint_le(nbytes),
          Repr::Heap(bytes) => bytes.try_get_uint_le(nbytes),
        }
      }

      #[cfg_attr(not(coverage), inline(always))]
      fn try_get_uint_ne(&mut self, nbytes: usize) -> Result<u64, $crate::TryGetError> {
        $crate::buffer::assert_uint_width(nbytes);
        match &mut self.$repr {
          Repr::Inline(buffer) => buffer.try_get_uint_ne(nbytes),
          Repr::Heap(bytes) => bytes.try_get_uint_ne(nbytes),
        }
      }

      #[cfg_attr(not(coverage), inline(always))]
      fn get_int(&mut self, nbytes: usize) -> i64 {
        $crate::buffer::assert_uint_width(nbytes);
        $crate::buffer::sign_extend(self.get_uint(nbytes), nbytes)
      }

      #[cfg_attr(not(coverage), inline(always))]
      fn get_int_le(&mut self, nbytes: usize) -> i64 {
        $crate::buffer::assert_uint_width(nbytes);
        $crate::buffer::sign_extend(self.get_uint_le(nbytes), nbytes)
      }

      #[cfg_attr(not(coverage), inline(always))]
      fn get_int_ne(&mut self, nbytes: usize) -> i64 {
        $crate::buffer::assert_uint_width(nbytes);
        if cfg!(target_endian = "big") {
          self.get_int(nbytes)
        } else {
          self.get_int_le(nbytes)
        }
      }

      #[cfg_attr(not(coverage), inline(always))]
      fn try_get_int(&mut self, nbytes: usize) -> Result<i64, $crate::TryGetError> {
        $crate::buffer::assert_uint_width(nbytes);
        self
          .try_get_uint(nbytes)
          .map(|value| $crate::buffer::sign_extend(value, nbytes))
      }

      #[cfg_attr(not(coverage), inline(always))]
      fn try_get_int_le(&mut self, nbytes: usize) -> Result<i64, $crate::TryGetError> {
        $crate::buffer::assert_uint_width(nbytes);
        self
          .try_get_uint_le(nbytes)
          .map(|value| $crate::buffer::sign_extend(value, nbytes))
      }

      #[cfg_attr(not(coverage), inline(always))]
      fn try_get_int_ne(&mut self, nbytes: usize) -> Result<i64, $crate::TryGetError> {
        $crate::buffer::assert_uint_width(nbytes);
        if cfg!(target_endian = "big") {
          self.try_get_int(nbytes)
        } else {
          self.try_get_int_le(nbytes)
        }
      }
    }
  };
  ($($suffix:ident), +$(,)?) => {
    paste::paste! {
      $(
        $crate::macros::method_forward! {
          fn [< get_ $suffix >]() -> $suffix;
          fn [< get_ $suffix _le >]() -> $suffix;
          fn [< get_ $suffix _ne >]() -> $suffix;
          fn [< try_get_ $suffix >]() -> Result<$suffix, $crate::TryGetError>;
          fn [< try_get_ $suffix _le >]() -> Result<$suffix, $crate::TryGetError>;
          fn [< try_get_ $suffix _ne >]() -> Result<$suffix, $crate::TryGetError>;
        }
      )*

      $crate::macros::method_forward! {
        fn get_i8() -> i8;
        fn get_u8() -> u8;
        fn try_get_i8() -> Result<i8, $crate::TryGetError>;
        fn try_get_u8() -> Result<u8, $crate::TryGetError>;

      }

      #[cfg_attr(not(coverage), inline(always))]
      fn get_uint(&mut self, nbytes: usize) -> u64 {
        $crate::buffer::assert_uint_width(nbytes);
        Self::get_uint(self, nbytes)
      }

      #[cfg_attr(not(coverage), inline(always))]
      fn get_uint_le(&mut self, nbytes: usize) -> u64 {
        $crate::buffer::assert_uint_width(nbytes);
        Self::get_uint_le(self, nbytes)
      }

      #[cfg_attr(not(coverage), inline(always))]
      fn get_uint_ne(&mut self, nbytes: usize) -> u64 {
        $crate::buffer::assert_uint_width(nbytes);
        Self::get_uint_ne(self, nbytes)
      }

      #[cfg_attr(not(coverage), inline(always))]
      fn try_get_uint(&mut self, nbytes: usize) -> Result<u64, $crate::TryGetError> {
        $crate::buffer::assert_uint_width(nbytes);
        Self::try_get_uint(self, nbytes)
      }

      #[cfg_attr(not(coverage), inline(always))]
      fn try_get_uint_le(&mut self, nbytes: usize) -> Result<u64, $crate::TryGetError> {
        $crate::buffer::assert_uint_width(nbytes);
        Self::try_get_uint_le(self, nbytes)
      }

      #[cfg_attr(not(coverage), inline(always))]
      fn try_get_uint_ne(&mut self, nbytes: usize) -> Result<u64, $crate::TryGetError> {
        $crate::buffer::assert_uint_width(nbytes);
        Self::try_get_uint_ne(self, nbytes)
      }

      #[cfg_attr(not(coverage), inline(always))]
      fn get_int(&mut self, nbytes: usize) -> i64 {
        $crate::buffer::assert_uint_width(nbytes);
        $crate::buffer::sign_extend(self.get_uint(nbytes), nbytes)
      }

      #[cfg_attr(not(coverage), inline(always))]
      fn get_int_le(&mut self, nbytes: usize) -> i64 {
        $crate::buffer::assert_uint_width(nbytes);
        $crate::buffer::sign_extend(self.get_uint_le(nbytes), nbytes)
      }

      #[cfg_attr(not(coverage), inline(always))]
      fn get_int_ne(&mut self, nbytes: usize) -> i64 {
        $crate::buffer::assert_uint_width(nbytes);
        if cfg!(target_endian = "big") {
          self.get_int(nbytes)
        } else {
          self.get_int_le(nbytes)
        }
      }

      #[cfg_attr(not(coverage), inline(always))]
      fn try_get_int(&mut self, nbytes: usize) -> Result<i64, $crate::TryGetError> {
        $crate::buffer::assert_uint_width(nbytes);
        self
          .try_get_uint(nbytes)
          .map(|value| $crate::buffer::sign_extend(value, nbytes))
      }

      #[cfg_attr(not(coverage), inline(always))]
      fn try_get_int_le(&mut self, nbytes: usize) -> Result<i64, $crate::TryGetError> {
        $crate::buffer::assert_uint_width(nbytes);
        self
          .try_get_uint_le(nbytes)
          .map(|value| $crate::buffer::sign_extend(value, nbytes))
      }

      #[cfg_attr(not(coverage), inline(always))]
      fn try_get_int_ne(&mut self, nbytes: usize) -> Result<i64, $crate::TryGetError> {
        $crate::buffer::assert_uint_width(nbytes);
        if cfg!(target_endian = "big") {
          self.try_get_int(nbytes)
        } else {
          self.try_get_int_le(nbytes)
        }
      }
    }
  };
}

macro_rules! forward_buf_mut {
  ($repr:tt { $($suffix:ident), +$(,)? }) => {
    paste::paste! {
      $(
        $crate::macros::method_forward! { $repr {
          fn [< put_ $suffix >](val: $suffix);
          fn [< put_ $suffix _le >](val: $suffix);
          fn [< put_ $suffix _ne >](val: $suffix);
        }}
      )*

      $crate::macros::method_forward! {$repr {
        fn put_i8(val: i8);
        fn put_u8(val: u8);

        fn put_uint(n: u64, nbytes: usize);
        fn put_uint_le(n: u64, nbytes: usize);
        fn put_uint_ne(n: u64, nbytes: usize);
        fn put_int(n: i64, nbytes: usize);
        fn put_int_le(n: i64, nbytes: usize);
        fn put_int_ne(n: i64, nbytes: usize);
      }}
    }
  };
  ($($suffix:ident), +$(,)?) => {
    paste::paste! {
      $(
        $crate::macros::method_forward! {
          fn [< put_ $suffix >](val: $suffix);
          fn [< put_ $suffix _le >](val: $suffix);
          fn [< put_ $suffix _ne >](val: $suffix);
        }
      )*

      $crate::macros::method_forward! {
        fn put_i8(val: i8);
        fn put_u8(val: u8);

        fn put_uint(n: u64, nbytes: usize);
        fn put_uint_le(n: u64, nbytes: usize);
        fn put_uint_ne(n: u64, nbytes: usize);

        fn put_int(n: i64, nbytes: usize);
        fn put_int_le(n: i64, nbytes: usize);
        fn put_int_ne(n: i64, nbytes: usize);
      }
    }
  };
}

pub(super) use forward_buf;
pub(super) use forward_buf_mut;
pub(super) use method_forward;

/// Formats arguments into the default shared [`Utf8Bytes`](crate::Utf8Bytes).
///
/// This is similar to `format!`, but returns a value that retains heap storage
/// when later shortened. Use `format_compact_utf8bytes!` when short results
/// should use inline storage.
///
/// # Examples
///
/// ```
/// use smol_bytes::{format_utf8bytes, Utf8Bytes};
///
/// let name = "Ada";
/// let greeting: Utf8Bytes = format_utf8bytes!("hello, {name}!");
/// assert_eq!(greeting.as_str(), "hello, Ada!");
/// ```
#[macro_export]
macro_rules! format_utf8bytes {
  ($($tt:tt)*) => {{
    let mut value = $crate::Utf8BytesMut::new();
    ::core::fmt::Write::write_fmt(&mut value, ::core::format_args!($($tt)*))
      .expect("a formatting trait implementation returned an error");
    value.freeze_shared()
  }};
}

/// Formats arguments into compact [`Utf8Bytes`](crate::compact::Utf8Bytes).
///
/// This is similar to `format!`, but returns a value that uses inline storage
/// when its contents fit, including after a larger value is later shortened.
/// Use `format_utf8bytes!` when retaining heap storage after shrinking is preferred.
///
/// # Examples
///
/// ```
/// use smol_bytes::{compact, format_compact_utf8bytes};
///
/// let name = "Ada";
/// let greeting: compact::Utf8Bytes = format_compact_utf8bytes!("hello, {name}!");
/// assert_eq!(greeting.as_str(), "hello, Ada!");
/// ```
#[macro_export]
macro_rules! format_compact_utf8bytes {
  ($($tt:tt)*) => {{
    let mut value = $crate::Utf8BytesMut::new();
    ::core::fmt::Write::write_fmt(&mut value, ::core::format_args!($($tt)*))
      .expect("a formatting trait implementation returned an error");
    value.freeze_compact()
  }};
}