summaryrefslogtreecommitdiffstats
path: root/third_party/rust/scroll/src/greater.rs
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--third_party/rust/scroll/src/greater.rs169
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 {}