diff options
Diffstat (limited to '')
-rw-r--r-- | third_party/rust/scroll/src/greater.rs | 169 |
1 files changed, 169 insertions, 0 deletions
diff --git a/third_party/rust/scroll/src/greater.rs b/third_party/rust/scroll/src/greater.rs new file mode 100644 index 0000000000..353aab7c4c --- /dev/null +++ b/third_party/rust/scroll/src/greater.rs @@ -0,0 +1,169 @@ +use core::ops::{Index, IndexMut, RangeFrom}; + +use crate::ctx::{FromCtx, IntoCtx}; + +/// Core-read - core, no_std friendly trait for reading basic traits from byte buffers. Cannot fail +/// unless the buffer is too small, in which case an assert fires and the program panics. +/// +/// If your type implements [FromCtx](ctx/trait.FromCtx.html) then you can `cread::<YourType>(offset)`. +/// +/// # Example +/// +/// ```rust +/// use scroll::{ctx, Cread, LE}; +/// +/// #[repr(packed)] +/// struct Bar { +/// foo: i32, +/// bar: u32, +/// } +/// +/// impl ctx::FromCtx<scroll::Endian> for Bar { +/// fn from_ctx(bytes: &[u8], ctx: scroll::Endian) -> Self { +/// use scroll::Cread; +/// Bar { foo: bytes.cread_with(0, ctx), bar: bytes.cread_with(4, ctx) } +/// } +/// } +/// +/// let bytes = [0xff, 0xff, 0xff, 0xff, 0xef,0xbe,0xad,0xde,]; +/// let bar = bytes.cread_with::<Bar>(0, LE); +/// // Remember that you need to copy out fields from packed structs +/// // with a `{}` block instead of borrowing them directly +/// // ref: https://github.com/rust-lang/rust/issues/46043 +/// assert_eq!({bar.foo}, -1); +/// assert_eq!({bar.bar}, 0xdeadbeef); +/// ``` +pub trait Cread<Ctx, I = usize>: Index<I> + Index<RangeFrom<I>> +where + Ctx: Copy, +{ + /// Reads a value from `Self` at `offset` with `ctx`. Cannot fail. + /// If the buffer is too small for the value requested, this will panic. + /// + /// # Example + /// + /// ```rust + /// use scroll::{Cread, BE, LE}; + /// use std::i64::MAX; + /// + /// let bytes = [0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff, 0xef,0xbe,0xad,0xde,]; + /// let foo = bytes.cread_with::<i64>(0, BE); + /// let bar = bytes.cread_with::<u32>(8, LE); + /// assert_eq!(foo, MAX); + /// assert_eq!(bar, 0xdeadbeef); + /// ``` + #[inline] + fn cread_with<N: FromCtx<Ctx, <Self as Index<RangeFrom<I>>>::Output>>( + &self, + offset: I, + ctx: Ctx, + ) -> N { + N::from_ctx(&self[offset..], ctx) + } + /// Reads a value implementing `FromCtx` from `Self` at `offset`, + /// with the **target machine**'s endianness. + /// For the primitive types, this will be the **target machine**'s endianness. + /// + /// # Example + /// + /// ```rust + /// use scroll::Cread; + /// + /// let bytes = [0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0xef,0xbe,0x00,0x00,]; + /// let foo = bytes.cread::<i64>(0); + /// let bar = bytes.cread::<u32>(8); + /// #[cfg(target_endian = "little")] + /// assert_eq!(foo, 1); + /// #[cfg(target_endian = "big")] + /// assert_eq!(foo, 0x100_0000_0000_0000); + /// + /// #[cfg(target_endian = "little")] + /// assert_eq!(bar, 0xbeef); + /// #[cfg(target_endian = "big")] + /// assert_eq!(bar, 0xefbe0000); + /// ``` + #[inline] + fn cread<N: FromCtx<Ctx, <Self as Index<RangeFrom<I>>>::Output>>(&self, offset: I) -> N + where + Ctx: Default, + { + let ctx = Ctx::default(); + N::from_ctx(&self[offset..], ctx) + } +} + +impl<Ctx: Copy, I, R: ?Sized + Index<I> + Index<RangeFrom<I>>> Cread<Ctx, I> for R {} + +/// Core-write - core, no_std friendly trait for writing basic types into byte buffers. Cannot fail +/// unless the buffer is too small, in which case an assert fires and the program panics. +/// Similar to [Cread](trait.Cread.html), if your type implements [IntoCtx](ctx/trait.IntoCtx.html) +/// then you can `cwrite(your_type, offset)`. +/// +/// # Example +/// +/// ```rust +/// use scroll::{ctx, Cwrite}; +/// +/// #[repr(packed)] +/// struct Bar { +/// foo: i32, +/// bar: u32, +/// } +/// +/// impl ctx::IntoCtx<scroll::Endian> for Bar { +/// fn into_ctx(self, bytes: &mut [u8], ctx: scroll::Endian) { +/// use scroll::Cwrite; +/// bytes.cwrite_with(self.foo, 0, ctx); +/// bytes.cwrite_with(self.bar, 4, ctx); +/// } +/// } +/// +/// let bar = Bar { foo: -1, bar: 0xdeadbeef }; +/// let mut bytes = [0x0; 16]; +/// bytes.cwrite::<Bar>(bar, 0); +/// ``` +pub trait Cwrite<Ctx: Copy, I = usize>: Index<I> + IndexMut<RangeFrom<I>> { + /// Writes `n` into `Self` at `offset`; uses default context. + /// For the primitive types, this will be the **target machine**'s endianness. + /// + /// # Example + /// + /// ``` + /// use scroll::{Cwrite, Cread}; + /// let mut bytes = [0x0; 16]; + /// bytes.cwrite::<i64>(42, 0); + /// bytes.cwrite::<u32>(0xdeadbeef, 8); + /// + /// assert_eq!(bytes.cread::<i64>(0), 42); + /// assert_eq!(bytes.cread::<u32>(8), 0xdeadbeef); + #[inline] + fn cwrite<N: IntoCtx<Ctx, <Self as Index<RangeFrom<I>>>::Output>>(&mut self, n: N, offset: I) + where + Ctx: Default, + { + let ctx = Ctx::default(); + n.into_ctx(self.index_mut(offset..), ctx) + } + /// Writes `n` into `Self` at `offset` with `ctx` + /// + /// # Example + /// + /// ``` + /// use scroll::{Cwrite, Cread, LE, BE}; + /// let mut bytes = [0x0; 0x10]; + /// bytes.cwrite_with::<i64>(42, 0, LE); + /// bytes.cwrite_with::<u32>(0xdeadbeef, 8, BE); + /// assert_eq!(bytes.cread_with::<i64>(0, LE), 42); + /// assert_eq!(bytes.cread_with::<u32>(8, LE), 0xefbeadde); + #[inline] + fn cwrite_with<N: IntoCtx<Ctx, <Self as Index<RangeFrom<I>>>::Output>>( + &mut self, + n: N, + offset: I, + ctx: Ctx, + ) { + n.into_ctx(self.index_mut(offset..), ctx) + } +} + +impl<Ctx: Copy, I, W: ?Sized + Index<I> + IndexMut<RangeFrom<I>>> Cwrite<Ctx, I> for W {} |