Coverage Report

Created: 2025-07-11 06:15

/rust/registry/src/index.crates.io-6f17d22bba15001f/scroll-0.10.2/src/ctx.rs
Line
Count
Source (jump to first uncovered line)
1
//! Generic context-aware conversion traits, for automatic _downstream_ extension of `Pread`, et. al
2
//!
3
//! The context traits are arguably the center piece of the scroll crate. In simple terms they
4
//! define how to actually read and write, respectively, a data type from a container, being able to
5
//! take context into account.
6
//!
7
//! ### Reading
8
//!
9
//! Types implementing [TryFromCtx](trait.TryFromCtx.html) and it's infallible cousin [FromCtx](trait.FromCtx.html)
10
//! allow a user of [Pread::pread](../trait.Pread.html#method.pread) or respectively
11
//! [Cread::cread](../trait.Cread.html#method.cread) and
12
//! [IOread::ioread](../trait.IOread.html#method.ioread) to read that data type from a data source one
13
//! of the `*read` traits has been implemented for.
14
//! 
15
//! Implementations of `TryFromCtx` specify a source (called `This`) and an `Error` type for failed
16
//! reads. The source defines the kind of container the type can be read from, and defaults to
17
//! `[u8]` for any type that implements `AsRef<[u8]>`.
18
//!
19
//! `FromCtx` is slightly more restricted; it requires the implementer to use `[u8]` as source and
20
//! never fail, and thus does not have an `Error` type.
21
//!
22
//! Types chosen here are of relevance to `Pread` implementations; of course only a container which
23
//! can produce a source of the type `This` can be used to read a `TryFromCtx` requiring it and the
24
//! `Error` type returned in `Err` of `Pread::pread`'s Result.
25
//!
26
//! ### Writing
27
//!
28
//! [TryIntoCtx](trait.TryIntoCtx.html) and the infallible [IntoCtx](trait.IntoCtx.html) work
29
//! similarly to the above traits, allowing [Pwrite::pwrite](../trait.Pwrite.html#method.pwrite) or
30
//! respectively [Cwrite::cwrite](../trait.Cwrite.html#method.cwrite) and
31
//! [IOwrite::iowrite](../trait.IOwrite.html#method.iowrite) to write data into a byte sink for
32
//! which one of the `*write` traits has been implemented for.
33
//!
34
//! `IntoCtx` is similarly restricted as `FromCtx` is to `TryFromCtx`. And equally the types chosen
35
//! affect usable `Pwrite` implementation.
36
//!
37
//! ### Context
38
//!
39
//! Each of the traits passes along a `Ctx` to the marshalling logic. This context type contains
40
//! any additional information that may be required to successfully parse or write the data:
41
//! Examples would be endianness to use, field lengths of a serialized struct, or delimiters to use
42
//! when reading/writing `&str`. The context type can be any type but must derive
43
//! [Copy](https://doc.rust-lang.org/std/marker/trait.Copy.html). In addition if you want to use
44
//! the `*read`-methods instead of the `*read_with` ones you must also implement
45
//! [default::Default](https://doc.rust-lang.org/std/default/trait.Default.html).
46
//!
47
//! # Example
48
//!
49
//! Let's expand on the [previous example](../index.html#complex-use-cases).
50
//!
51
//! ```rust
52
//! use scroll::{self, ctx, Pread, Endian};
53
//! use scroll::ctx::StrCtx;
54
//!
55
//! #[derive(Copy, Clone, PartialEq, Eq)]
56
//! enum FieldSize {
57
//!     U32,
58
//!     U64
59
//! }
60
//!
61
//! // Our custom context type. As said above it has to derive Copy.
62
//! #[derive(Copy, Clone)]
63
//! struct Context {
64
//!     fieldsize: FieldSize,
65
//!     endianess: Endian,
66
//! }
67
//!
68
//! // Our custom data type
69
//! struct Data<'b> {
70
//!   // These u64 are encoded either as 32-bit or 64-bit wide ints. Which one it is is defined in
71
//!   // the Context.
72
//!   // Also, let's imagine they have a strict relationship: A < B < C otherwise the struct is
73
//!   // invalid.
74
//!   field_a: u64,
75
//!   field_b: u64,
76
//!   field_c: u64,
77
//!
78
//!   // Both of these are marshalled with a prefixed length.
79
//!   name: &'b str,
80
//!   value: &'b [u8],
81
//! }
82
//!
83
//! #[derive(Debug)]
84
//! enum Error {
85
//!     // We'll return this custom error if the field* relationship doesn't hold
86
//!     BadFieldMatchup,
87
//!     Scroll(scroll::Error),
88
//! }
89
//!
90
//! impl<'a> ctx::TryFromCtx<'a, Context> for Data<'a> {
91
//!   type Error = Error;
92
//!
93
//!   // Using the explicit lifetime specification again you ensure that read data doesn't outlife
94
//!   // its source buffer without having to resort to copying.
95
//!   fn try_from_ctx (src: &'a [u8], ctx: Context)
96
//!     // the `usize` returned here is the amount of bytes read.
97
//!     -> Result<(Self, usize), Self::Error> 
98
//!   {
99
//!     // The offset counter; gread and gread_with increment a given counter automatically so we
100
//!     // don't have to manually care.
101
//!     let offset = &mut 0;
102
//!
103
//!     let field_a;
104
//!     let field_b;
105
//!     let field_c;
106
//!
107
//!     // Switch the amount of bytes read depending on the parsing context
108
//!     if ctx.fieldsize == FieldSize::U32 {
109
//!       field_a = src.gread_with::<u32>(offset, ctx.endianess)? as u64;
110
//!       field_b = src.gread_with::<u32>(offset, ctx.endianess)? as u64;
111
//!       field_c = src.gread_with::<u32>(offset, ctx.endianess)? as u64;
112
//!     } else {
113
//!       field_a = src.gread_with::<u64>(offset, ctx.endianess)?;
114
//!       field_b = src.gread_with::<u64>(offset, ctx.endianess)?;
115
//!       field_c = src.gread_with::<u64>(offset, ctx.endianess)?;
116
//!     }
117
//!
118
//!     // You can use type ascribition or turbofish operators, whichever you prefer.
119
//!     let namelen = src.gread_with::<u16>(offset, ctx.endianess)? as usize;
120
//!     let name: &str = src.gread_with(offset, scroll::ctx::StrCtx::Length(namelen))?;
121
//!
122
//!     let vallen = src.gread_with::<u16>(offset, ctx.endianess)? as usize;
123
//!     let value = &src[*offset..(*offset+vallen)];
124
//!
125
//!     // Let's sanity check those fields, shall we?
126
//!     if ! (field_a < field_b && field_b < field_c) {
127
//!       return Err(Error::BadFieldMatchup);
128
//!     }
129
//!
130
//!     Ok((Data { field_a, field_b, field_c, name, value }, *offset))
131
//!   }
132
//! }
133
//!
134
//! // In lieu of a complex byte buffer we hearken back to the venerable &[u8]; do note however
135
//! // that the implementation of TryFromCtx did not specify such. In fact any type that implements
136
//! // Pread can now read `Data` as it implements TryFromCtx.
137
//! let bytes = b"\x00\x02\x03\x04\x01\x02\x03\x04\xde\xad\xbe\xef\x00\x08UserName\x00\x02\xCA\xFE";
138
//!
139
//! // We define an appropiate context, and get going
140
//! let contextA = Context {
141
//!     fieldsize: FieldSize::U32,
142
//!     endianess: Endian::Big,
143
//! };
144
//! let data: Data = bytes.pread_with(0, contextA).unwrap();
145
//!
146
//! assert_eq!(data.field_a, 0x00020304);
147
//! assert_eq!(data.field_b, 0x01020304);
148
//! assert_eq!(data.field_c, 0xdeadbeef);
149
//! assert_eq!(data.name, "UserName");
150
//! assert_eq!(data.value, [0xCA, 0xFE]);
151
//!
152
//! // Here we have a context with a different FieldSize, changing parsing information at runtime.
153
//! let contextB = Context {
154
//!     fieldsize: FieldSize::U64,
155
//!     endianess: Endian::Big,
156
//! };
157
//!
158
//! // Which will of course error with a malformed input for the context
159
//! let err: Result<Data, Error> = bytes.pread_with(0, contextB);
160
//! assert!(err.is_err());
161
//!
162
//! let bytes_long = [0x00,0x00,0x00,0x00,0x00,0x02,0x03,0x04,0x00,0x00,0x00,0x00,0x01,0x02,0x03,
163
//!                   0x04,0x00,0x00,0x00,0x00,0xde,0xad,0xbe,0xef,0x00,0x08,0x55,0x73,0x65,0x72,
164
//!                   0x4e,0x61,0x6d,0x65,0x00,0x02,0xCA,0xFE];
165
//!
166
//! let data: Data = bytes_long.pread_with(0, contextB).unwrap();
167
//!
168
//! assert_eq!(data.field_a, 0x00020304);
169
//! assert_eq!(data.field_b, 0x01020304);
170
//! assert_eq!(data.field_c, 0xdeadbeef);
171
//! assert_eq!(data.name, "UserName");
172
//! assert_eq!(data.value, [0xCA, 0xFE]);
173
//!
174
//! // Ergonomic conversion, not relevant really.
175
//! use std::convert::From;
176
//! impl From<scroll::Error> for Error {
177
//!   fn from(error: scroll::Error) -> Error {
178
//!     Error::Scroll(error)
179
//!   }
180
//! }
181
//! ```
182
183
use core::ptr::copy_nonoverlapping;
184
use core::mem::transmute;
185
use core::mem::size_of;
186
use core::str;
187
use core::result;
188
189
#[cfg(feature = "std")]
190
use std::ffi::{CStr, CString};
191
192
use crate::error;
193
use crate::endian::Endian;
194
195
/// A trait for measuring how large something is; for a byte sequence, it will be its length.
196
pub trait MeasureWith<Ctx> {
197
    /// How large is `Self`, given the `ctx`?
198
    fn measure_with(&self, ctx: &Ctx) -> usize;
199
}
200
201
impl<Ctx> MeasureWith<Ctx> for [u8] {
202
    #[inline]
203
242M
    fn measure_with(&self, _ctx: &Ctx) -> usize {
204
242M
        self.len()
205
242M
    }
<[u8] as scroll::ctx::MeasureWith<scroll::endian::Endian>>::measure_with
Line
Count
Source
203
513k
    fn measure_with(&self, _ctx: &Ctx) -> usize {
204
513k
        self.len()
205
513k
    }
Unexecuted instantiation: <[u8] as scroll::ctx::MeasureWith<_>>::measure_with
<[u8] as scroll::ctx::MeasureWith<scroll::endian::Endian>>::measure_with
Line
Count
Source
203
16.2M
    fn measure_with(&self, _ctx: &Ctx) -> usize {
204
16.2M
        self.len()
205
16.2M
    }
<[u8] as scroll::ctx::MeasureWith<scroll::endian::Endian>>::measure_with
Line
Count
Source
203
225M
    fn measure_with(&self, _ctx: &Ctx) -> usize {
204
225M
        self.len()
205
225M
    }
206
}
207
208
impl<Ctx, T: AsRef<[u8]>> MeasureWith<Ctx> for T {
209
    #[inline]
210
0
    fn measure_with(&self, _ctx: &Ctx) -> usize {
211
0
        self.as_ref().len()
212
0
    }
213
}
214
215
/// The parsing context for converting a byte sequence to a `&str`
216
///
217
/// `StrCtx` specifies what byte delimiter to use, and defaults to C-style null terminators. Be careful.
218
#[derive(Debug, Copy, Clone)]
219
pub enum StrCtx {
220
    Delimiter(u8),
221
    DelimiterUntil(u8, usize),
222
    Length(usize),
223
}
224
225
/// A C-style, null terminator based delimiter
226
pub const NULL: u8 = 0;
227
/// A space-based delimiter
228
pub const SPACE: u8 = 0x20;
229
/// A newline-based delimiter
230
pub const RET: u8 = 0x0a;
231
/// A tab-based delimiter
232
pub const TAB: u8 = 0x09;
233
234
impl Default for StrCtx {
235
    #[inline]
236
0
    fn default() -> Self {
237
0
        StrCtx::Delimiter(NULL)
238
0
    }
239
}
240
241
impl StrCtx {
242
0
    pub fn len(&self) -> usize {
243
0
        match *self {
244
            StrCtx::Delimiter(_) |
245
0
            StrCtx::DelimiterUntil(_, _) => 1,
246
0
            StrCtx::Length(_) => 0,
247
        }
248
0
    }
249
250
0
    pub fn is_empty(&self) -> bool {
251
0
        if let StrCtx::Length(_) = *self { true } else { false }
252
0
    }
253
}
254
255
/// Reads `Self` from `This` using the context `Ctx`; must _not_ fail
256
pub trait FromCtx<Ctx: Copy = (), This: ?Sized = [u8]> {
257
    fn from_ctx(this: &This, ctx: Ctx) -> Self;
258
}
259
260
/// Tries to read `Self` from `This` using the context `Ctx`
261
///
262
/// # Implementing Your Own Reader
263
/// If you want to implement your own reader for a type `Foo` from some kind of buffer (say
264
/// `[u8]`), then you need to implement this trait
265
///
266
/// ```rust
267
/// use scroll::{self, ctx, Pread};
268
/// #[derive(Debug, PartialEq, Eq)]
269
/// pub struct Foo(u16);
270
///
271
/// impl<'a> ctx::TryFromCtx<'a, scroll::Endian> for Foo {
272
///      type Error = scroll::Error;
273
///      fn try_from_ctx(this: &'a [u8], le: scroll::Endian) -> Result<(Self, usize), Self::Error> {
274
///          if this.len() < 2 { return Err((scroll::Error::Custom("whatever".to_string())).into()) }
275
///          let n = this.pread_with(0, le)?;
276
///          Ok((Foo(n), 2))
277
///      }
278
/// }
279
///
280
/// let bytes: [u8; 4] = [0xde, 0xad, 0, 0];
281
/// let foo = bytes.pread_with::<Foo>(0, scroll::LE).unwrap();
282
/// assert_eq!(Foo(0xadde), foo);
283
///
284
/// let foo2 = bytes.pread_with::<Foo>(0, scroll::BE).unwrap();
285
/// assert_eq!(Foo(0xdeadu16), foo2);
286
/// ```
287
///
288
/// # Advanced: Using Your Own Error in `TryFromCtx`
289
/// ```rust
290
///  use scroll::{self, ctx, Pread};
291
///  use std::error;
292
///  use std::fmt::{self, Display};
293
///  // make some kind of normal error which also can transformed from a scroll error
294
///  #[derive(Debug)]
295
///  pub struct ExternalError {}
296
///
297
///  impl Display for ExternalError {
298
///      fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
299
///          write!(fmt, "ExternalError")
300
///      }
301
///  }
302
///
303
///  impl error::Error for ExternalError {
304
///      fn description(&self) -> &str {
305
///          "ExternalError"
306
///      }
307
///      fn cause(&self) -> Option<&error::Error> { None}
308
///  }
309
///
310
///  impl From<scroll::Error> for ExternalError {
311
///      fn from(err: scroll::Error) -> Self {
312
///          match err {
313
///              _ => ExternalError{},
314
///          }
315
///      }
316
///  }
317
///  #[derive(Debug, PartialEq, Eq)]
318
///  pub struct Foo(u16);
319
///
320
///  impl<'a> ctx::TryFromCtx<'a, scroll::Endian> for Foo {
321
///      type Error = ExternalError;
322
///      fn try_from_ctx(this: &'a [u8], le: scroll::Endian) -> Result<(Self, usize), Self::Error> {
323
///          if this.len() <= 2 { return Err((ExternalError {}).into()) }
324
///          let offset = &mut 0;
325
///          let n = this.gread_with(offset, le)?;
326
///          Ok((Foo(n), *offset))
327
///      }
328
///  }
329
///
330
/// let bytes: [u8; 4] = [0xde, 0xad, 0, 0];
331
/// let foo: Result<Foo, ExternalError> = bytes.pread(0);
332
/// ```
333
pub trait TryFromCtx<'a, Ctx: Copy = (), This: ?Sized = [u8]> where Self: 'a + Sized {
334
    type Error;
335
    fn try_from_ctx(from: &'a This, ctx: Ctx) -> Result<(Self, usize), Self::Error>;
336
}
337
338
/// Writes `Self` into `This` using the context `Ctx`
339
pub trait IntoCtx<Ctx: Copy = (), This: ?Sized = [u8]>: Sized {
340
    fn into_ctx(self, _: &mut This, ctx: Ctx);
341
}
342
343
/// Tries to write `Self` into `This` using the context `Ctx`
344
/// To implement writing into an arbitrary byte buffer, implement `TryIntoCtx`
345
/// # Example
346
/// ```rust
347
/// use scroll::{self, ctx, LE, Endian, Pwrite};
348
/// #[derive(Debug, PartialEq, Eq)]
349
/// pub struct Foo(u16);
350
///
351
/// // this will use the default `DefaultCtx = scroll::Endian`
352
/// impl ctx::TryIntoCtx<Endian> for Foo {
353
///     // you can use your own error here too, but you will then need to specify it in fn generic parameters
354
///     type Error = scroll::Error;
355
///     // you can write using your own context type, see `leb128.rs`
356
///     fn try_into_ctx(self, this: &mut [u8], le: Endian) -> Result<usize, Self::Error> {
357
///         if this.len() < 2 { return Err((scroll::Error::Custom("whatever".to_string())).into()) }
358
///         this.pwrite_with(self.0, 0, le)?;
359
///         Ok(2)
360
///     }
361
/// }
362
/// // now we can write a `Foo` into some buffer (in this case, a byte buffer, because that's what we implemented it for above)
363
///
364
/// let mut bytes: [u8; 4] = [0, 0, 0, 0];
365
/// bytes.pwrite_with(Foo(0x7f), 1, LE).unwrap();
366
/// ```
367
pub trait TryIntoCtx<Ctx: Copy = (), This: ?Sized = [u8]>: Sized {
368
    type Error;
369
    fn try_into_ctx(self, _: &mut This, ctx: Ctx) -> Result<usize, Self::Error>;
370
}
371
372
/// Gets the size of `Self` with a `Ctx`, and in `Self::Units`. Implementors can then call `Gread` related functions
373
///
374
/// The rationale behind this trait is to:
375
///
376
/// 1. Prevent `gread` from being used, and the offset being modified based on simply the sizeof the value, which can be a misnomer, e.g., for Leb128, etc.
377
/// 2. Allow a context based size, which is useful for 32/64 bit variants for various containers, etc.
378
pub trait SizeWith<Ctx = ()> {
379
    fn size_with(ctx: &Ctx) -> usize;
380
}
381
382
macro_rules! signed_to_unsigned {
383
    (i8) =>  {u8 };
384
    (u8) =>  {u8 };
385
    (i16) => {u16};
386
    (u16) => {u16};
387
    (i32) => {u32};
388
    (u32) => {u32};
389
    (i64) => {u64};
390
    (u64) => {u64};
391
    (i128) => {u128};
392
    (u128) => {u128};
393
    (f32) => {u32};
394
    (f64) => {u64};
395
}
396
397
macro_rules! write_into {
398
    ($typ:ty, $size:expr, $n:expr, $dst:expr, $endian:expr) => ({
399
        unsafe {
400
            assert!($dst.len() >= $size);
401
            let bytes = transmute::<$typ, [u8; $size]>(if $endian.is_little() { $n.to_le() } else { $n.to_be() });
402
            copy_nonoverlapping((&bytes).as_ptr(), $dst.as_mut_ptr(), $size);
403
        }
404
    });
405
}
406
407
macro_rules! into_ctx_impl {
408
    ($typ:tt, $size:expr) => {
409
        impl IntoCtx<Endian> for $typ {
410
            #[inline]
411
24.1k
            fn into_ctx(self, dst: &mut [u8], le: Endian) {
412
24.1k
                assert!(dst.len() >= $size);
413
24.1k
                write_into!($typ, $size, self, dst, le);
414
24.1k
            }
Unexecuted instantiation: <u8 as scroll::ctx::IntoCtx<scroll::endian::Endian>>::into_ctx
Unexecuted instantiation: <i8 as scroll::ctx::IntoCtx<scroll::endian::Endian>>::into_ctx
Unexecuted instantiation: <u16 as scroll::ctx::IntoCtx<scroll::endian::Endian>>::into_ctx
Unexecuted instantiation: <i16 as scroll::ctx::IntoCtx<scroll::endian::Endian>>::into_ctx
Unexecuted instantiation: <u32 as scroll::ctx::IntoCtx<scroll::endian::Endian>>::into_ctx
Unexecuted instantiation: <i32 as scroll::ctx::IntoCtx<scroll::endian::Endian>>::into_ctx
Unexecuted instantiation: <u64 as scroll::ctx::IntoCtx<scroll::endian::Endian>>::into_ctx
Unexecuted instantiation: <i64 as scroll::ctx::IntoCtx<scroll::endian::Endian>>::into_ctx
Unexecuted instantiation: <u128 as scroll::ctx::IntoCtx<scroll::endian::Endian>>::into_ctx
Unexecuted instantiation: <i128 as scroll::ctx::IntoCtx<scroll::endian::Endian>>::into_ctx
<u64 as scroll::ctx::IntoCtx<scroll::endian::Endian>>::into_ctx
Line
Count
Source
411
24.1k
            fn into_ctx(self, dst: &mut [u8], le: Endian) {
412
24.1k
                assert!(dst.len() >= $size);
413
24.1k
                write_into!($typ, $size, self, dst, le);
414
24.1k
            }
415
        }
416
        impl<'a> IntoCtx<Endian> for &'a $typ {
417
            #[inline]
418
0
            fn into_ctx(self, dst: &mut [u8], le: Endian) {
419
0
                (*self).into_ctx(dst, le)
420
0
            }
Unexecuted instantiation: <&u8 as scroll::ctx::IntoCtx<scroll::endian::Endian>>::into_ctx
Unexecuted instantiation: <&i8 as scroll::ctx::IntoCtx<scroll::endian::Endian>>::into_ctx
Unexecuted instantiation: <&u16 as scroll::ctx::IntoCtx<scroll::endian::Endian>>::into_ctx
Unexecuted instantiation: <&i16 as scroll::ctx::IntoCtx<scroll::endian::Endian>>::into_ctx
Unexecuted instantiation: <&u32 as scroll::ctx::IntoCtx<scroll::endian::Endian>>::into_ctx
Unexecuted instantiation: <&i32 as scroll::ctx::IntoCtx<scroll::endian::Endian>>::into_ctx
Unexecuted instantiation: <&u64 as scroll::ctx::IntoCtx<scroll::endian::Endian>>::into_ctx
Unexecuted instantiation: <&i64 as scroll::ctx::IntoCtx<scroll::endian::Endian>>::into_ctx
Unexecuted instantiation: <&u128 as scroll::ctx::IntoCtx<scroll::endian::Endian>>::into_ctx
Unexecuted instantiation: <&i128 as scroll::ctx::IntoCtx<scroll::endian::Endian>>::into_ctx
421
        }
422
        impl TryIntoCtx<Endian> for $typ where $typ: IntoCtx<Endian> {
423
            type Error = error::Error;
424
            #[inline]
425
24.1k
            fn try_into_ctx(self, dst: &mut [u8], le: Endian) -> error::Result<usize> {
426
24.1k
                if $size > dst.len () {
427
3
                    Err(error::Error::TooBig{size: $size, len: dst.len()})
428
                } else {
429
24.1k
                    <$typ as IntoCtx<Endian>>::into_ctx(self, dst, le);
430
24.1k
                    Ok($size)
431
                }
432
24.1k
            }
Unexecuted instantiation: <u8 as scroll::ctx::TryIntoCtx<scroll::endian::Endian>>::try_into_ctx
Unexecuted instantiation: <i8 as scroll::ctx::TryIntoCtx<scroll::endian::Endian>>::try_into_ctx
Unexecuted instantiation: <u16 as scroll::ctx::TryIntoCtx<scroll::endian::Endian>>::try_into_ctx
Unexecuted instantiation: <i16 as scroll::ctx::TryIntoCtx<scroll::endian::Endian>>::try_into_ctx
Unexecuted instantiation: <u32 as scroll::ctx::TryIntoCtx<scroll::endian::Endian>>::try_into_ctx
Unexecuted instantiation: <i32 as scroll::ctx::TryIntoCtx<scroll::endian::Endian>>::try_into_ctx
Unexecuted instantiation: <u64 as scroll::ctx::TryIntoCtx<scroll::endian::Endian>>::try_into_ctx
Unexecuted instantiation: <i64 as scroll::ctx::TryIntoCtx<scroll::endian::Endian>>::try_into_ctx
Unexecuted instantiation: <u128 as scroll::ctx::TryIntoCtx<scroll::endian::Endian>>::try_into_ctx
Unexecuted instantiation: <i128 as scroll::ctx::TryIntoCtx<scroll::endian::Endian>>::try_into_ctx
<u64 as scroll::ctx::TryIntoCtx<scroll::endian::Endian>>::try_into_ctx
Line
Count
Source
425
24.1k
            fn try_into_ctx(self, dst: &mut [u8], le: Endian) -> error::Result<usize> {
426
24.1k
                if $size > dst.len () {
427
3
                    Err(error::Error::TooBig{size: $size, len: dst.len()})
428
                } else {
429
24.1k
                    <$typ as IntoCtx<Endian>>::into_ctx(self, dst, le);
430
24.1k
                    Ok($size)
431
                }
432
24.1k
            }
433
        }
434
        impl<'a> TryIntoCtx<Endian> for &'a $typ {
435
            type Error = error::Error;
436
            #[inline]
437
0
            fn try_into_ctx(self, dst: &mut [u8], le: Endian) -> error::Result<usize> {
438
0
                (*self).try_into_ctx(dst, le)
439
0
            }
Unexecuted instantiation: <&u8 as scroll::ctx::TryIntoCtx<scroll::endian::Endian>>::try_into_ctx
Unexecuted instantiation: <&i8 as scroll::ctx::TryIntoCtx<scroll::endian::Endian>>::try_into_ctx
Unexecuted instantiation: <&u16 as scroll::ctx::TryIntoCtx<scroll::endian::Endian>>::try_into_ctx
Unexecuted instantiation: <&i16 as scroll::ctx::TryIntoCtx<scroll::endian::Endian>>::try_into_ctx
Unexecuted instantiation: <&u32 as scroll::ctx::TryIntoCtx<scroll::endian::Endian>>::try_into_ctx
Unexecuted instantiation: <&i32 as scroll::ctx::TryIntoCtx<scroll::endian::Endian>>::try_into_ctx
Unexecuted instantiation: <&u64 as scroll::ctx::TryIntoCtx<scroll::endian::Endian>>::try_into_ctx
Unexecuted instantiation: <&i64 as scroll::ctx::TryIntoCtx<scroll::endian::Endian>>::try_into_ctx
Unexecuted instantiation: <&u128 as scroll::ctx::TryIntoCtx<scroll::endian::Endian>>::try_into_ctx
Unexecuted instantiation: <&i128 as scroll::ctx::TryIntoCtx<scroll::endian::Endian>>::try_into_ctx
440
        }
441
    }
442
}
443
444
macro_rules! from_ctx_impl {
445
    ($typ:tt, $size:expr) => {
446
        impl<'a> FromCtx<Endian> for $typ {
447
            #[inline]
448
0
            fn from_ctx(src: &[u8], le: Endian) -> Self {
449
0
                assert!(src.len() >= $size);
450
0
                let mut data: signed_to_unsigned!($typ) = 0;
451
0
                unsafe {
452
0
                    copy_nonoverlapping(
453
0
                        src.as_ptr(),
454
0
                        &mut data as *mut signed_to_unsigned!($typ) as *mut u8,
455
0
                        $size);
456
0
                }
457
0
                (if le.is_little() { data.to_le() } else { data.to_be() }) as $typ
458
0
            }
Unexecuted instantiation: <u8 as scroll::ctx::FromCtx<scroll::endian::Endian>>::from_ctx
Unexecuted instantiation: <i8 as scroll::ctx::FromCtx<scroll::endian::Endian>>::from_ctx
Unexecuted instantiation: <u16 as scroll::ctx::FromCtx<scroll::endian::Endian>>::from_ctx
Unexecuted instantiation: <i16 as scroll::ctx::FromCtx<scroll::endian::Endian>>::from_ctx
Unexecuted instantiation: <u32 as scroll::ctx::FromCtx<scroll::endian::Endian>>::from_ctx
Unexecuted instantiation: <i32 as scroll::ctx::FromCtx<scroll::endian::Endian>>::from_ctx
Unexecuted instantiation: <u64 as scroll::ctx::FromCtx<scroll::endian::Endian>>::from_ctx
Unexecuted instantiation: <i64 as scroll::ctx::FromCtx<scroll::endian::Endian>>::from_ctx
Unexecuted instantiation: <u128 as scroll::ctx::FromCtx<scroll::endian::Endian>>::from_ctx
Unexecuted instantiation: <i128 as scroll::ctx::FromCtx<scroll::endian::Endian>>::from_ctx
459
        }
460
461
        impl<'a> TryFromCtx<'a, Endian> for $typ where $typ: FromCtx<Endian> {
462
            type Error = error::Error;
463
            #[inline]
464
176M
            fn try_from_ctx(src: &'a [u8], le: Endian) -> result::Result<(Self, usize), Self::Error> {
465
176M
                if $size > src.len () {
466
1.75k
                    Err(error::Error::TooBig{size: $size, len: src.len()})
467
                } else {
468
176M
                    Ok((FromCtx::from_ctx(&src, le), $size))
469
                }
470
176M
            }
<u64 as scroll::ctx::TryFromCtx<scroll::endian::Endian>>::try_from_ctx
Line
Count
Source
464
4.82k
            fn try_from_ctx(src: &'a [u8], le: Endian) -> result::Result<(Self, usize), Self::Error> {
465
4.82k
                if $size > src.len () {
466
18
                    Err(error::Error::TooBig{size: $size, len: src.len()})
467
                } else {
468
4.81k
                    Ok((FromCtx::from_ctx(&src, le), $size))
469
                }
470
4.82k
            }
<u8 as scroll::ctx::TryFromCtx<scroll::endian::Endian>>::try_from_ctx
Line
Count
Source
464
454k
            fn try_from_ctx(src: &'a [u8], le: Endian) -> result::Result<(Self, usize), Self::Error> {
465
454k
                if $size > src.len () {
466
0
                    Err(error::Error::TooBig{size: $size, len: src.len()})
467
                } else {
468
454k
                    Ok((FromCtx::from_ctx(&src, le), $size))
469
                }
470
454k
            }
<u16 as scroll::ctx::TryFromCtx<scroll::endian::Endian>>::try_from_ctx
Line
Count
Source
464
4.76k
            fn try_from_ctx(src: &'a [u8], le: Endian) -> result::Result<(Self, usize), Self::Error> {
465
4.76k
                if $size > src.len () {
466
3
                    Err(error::Error::TooBig{size: $size, len: src.len()})
467
                } else {
468
4.76k
                    Ok((FromCtx::from_ctx(&src, le), $size))
469
                }
470
4.76k
            }
<u32 as scroll::ctx::TryFromCtx<scroll::endian::Endian>>::try_from_ctx
Line
Count
Source
464
15.1k
            fn try_from_ctx(src: &'a [u8], le: Endian) -> result::Result<(Self, usize), Self::Error> {
465
15.1k
                if $size > src.len () {
466
19
                    Err(error::Error::TooBig{size: $size, len: src.len()})
467
                } else {
468
15.1k
                    Ok((FromCtx::from_ctx(&src, le), $size))
469
                }
470
15.1k
            }
Unexecuted instantiation: <u8 as scroll::ctx::TryFromCtx<scroll::endian::Endian>>::try_from_ctx
Unexecuted instantiation: <i8 as scroll::ctx::TryFromCtx<scroll::endian::Endian>>::try_from_ctx
Unexecuted instantiation: <u16 as scroll::ctx::TryFromCtx<scroll::endian::Endian>>::try_from_ctx
Unexecuted instantiation: <i16 as scroll::ctx::TryFromCtx<scroll::endian::Endian>>::try_from_ctx
Unexecuted instantiation: <u32 as scroll::ctx::TryFromCtx<scroll::endian::Endian>>::try_from_ctx
Unexecuted instantiation: <i32 as scroll::ctx::TryFromCtx<scroll::endian::Endian>>::try_from_ctx
Unexecuted instantiation: <u64 as scroll::ctx::TryFromCtx<scroll::endian::Endian>>::try_from_ctx
Unexecuted instantiation: <i64 as scroll::ctx::TryFromCtx<scroll::endian::Endian>>::try_from_ctx
Unexecuted instantiation: <u128 as scroll::ctx::TryFromCtx<scroll::endian::Endian>>::try_from_ctx
Unexecuted instantiation: <i128 as scroll::ctx::TryFromCtx<scroll::endian::Endian>>::try_from_ctx
<u64 as scroll::ctx::TryFromCtx<scroll::endian::Endian>>::try_from_ctx
Line
Count
Source
464
128k
            fn try_from_ctx(src: &'a [u8], le: Endian) -> result::Result<(Self, usize), Self::Error> {
465
128k
                if $size > src.len () {
466
14
                    Err(error::Error::TooBig{size: $size, len: src.len()})
467
                } else {
468
128k
                    Ok((FromCtx::from_ctx(&src, le), $size))
469
                }
470
128k
            }
<u8 as scroll::ctx::TryFromCtx<scroll::endian::Endian>>::try_from_ctx
Line
Count
Source
464
7.47M
            fn try_from_ctx(src: &'a [u8], le: Endian) -> result::Result<(Self, usize), Self::Error> {
465
7.47M
                if $size > src.len () {
466
0
                    Err(error::Error::TooBig{size: $size, len: src.len()})
467
                } else {
468
7.47M
                    Ok((FromCtx::from_ctx(&src, le), $size))
469
                }
470
7.47M
            }
<u16 as scroll::ctx::TryFromCtx<scroll::endian::Endian>>::try_from_ctx
Line
Count
Source
464
4.04M
            fn try_from_ctx(src: &'a [u8], le: Endian) -> result::Result<(Self, usize), Self::Error> {
465
4.04M
                if $size > src.len () {
466
6
                    Err(error::Error::TooBig{size: $size, len: src.len()})
467
                } else {
468
4.04M
                    Ok((FromCtx::from_ctx(&src, le), $size))
469
                }
470
4.04M
            }
<u32 as scroll::ctx::TryFromCtx<scroll::endian::Endian>>::try_from_ctx
Line
Count
Source
464
2.10M
            fn try_from_ctx(src: &'a [u8], le: Endian) -> result::Result<(Self, usize), Self::Error> {
465
2.10M
                if $size > src.len () {
466
22
                    Err(error::Error::TooBig{size: $size, len: src.len()})
467
                } else {
468
2.10M
                    Ok((FromCtx::from_ctx(&src, le), $size))
469
                }
470
2.10M
            }
<u64 as scroll::ctx::TryFromCtx<scroll::endian::Endian>>::try_from_ctx
Line
Count
Source
464
142M
            fn try_from_ctx(src: &'a [u8], le: Endian) -> result::Result<(Self, usize), Self::Error> {
465
142M
                if $size > src.len () {
466
971
                    Err(error::Error::TooBig{size: $size, len: src.len()})
467
                } else {
468
142M
                    Ok((FromCtx::from_ctx(&src, le), $size))
469
                }
470
142M
            }
<i64 as scroll::ctx::TryFromCtx<scroll::endian::Endian>>::try_from_ctx
Line
Count
Source
464
9.59M
            fn try_from_ctx(src: &'a [u8], le: Endian) -> result::Result<(Self, usize), Self::Error> {
465
9.59M
                if $size > src.len () {
466
186
                    Err(error::Error::TooBig{size: $size, len: src.len()})
467
                } else {
468
9.59M
                    Ok((FromCtx::from_ctx(&src, le), $size))
469
                }
470
9.59M
            }
<u8 as scroll::ctx::TryFromCtx<scroll::endian::Endian>>::try_from_ctx
Line
Count
Source
464
282k
            fn try_from_ctx(src: &'a [u8], le: Endian) -> result::Result<(Self, usize), Self::Error> {
465
282k
                if $size > src.len () {
466
0
                    Err(error::Error::TooBig{size: $size, len: src.len()})
467
                } else {
468
282k
                    Ok((FromCtx::from_ctx(&src, le), $size))
469
                }
470
282k
            }
<u16 as scroll::ctx::TryFromCtx<scroll::endian::Endian>>::try_from_ctx
Line
Count
Source
464
1.72M
            fn try_from_ctx(src: &'a [u8], le: Endian) -> result::Result<(Self, usize), Self::Error> {
465
1.72M
                if $size > src.len () {
466
20
                    Err(error::Error::TooBig{size: $size, len: src.len()})
467
                } else {
468
1.72M
                    Ok((FromCtx::from_ctx(&src, le), $size))
469
                }
470
1.72M
            }
<u32 as scroll::ctx::TryFromCtx<scroll::endian::Endian>>::try_from_ctx
Line
Count
Source
464
8.35M
            fn try_from_ctx(src: &'a [u8], le: Endian) -> result::Result<(Self, usize), Self::Error> {
465
8.35M
                if $size > src.len () {
466
494
                    Err(error::Error::TooBig{size: $size, len: src.len()})
467
                } else {
468
8.35M
                    Ok((FromCtx::from_ctx(&src, le), $size))
469
                }
470
8.35M
            }
471
        }
472
        // as ref
473
        impl<'a, T> FromCtx<Endian, T> for $typ where T: AsRef<[u8]> {
474
            #[inline]
475
176M
            fn from_ctx(src: &T, le: Endian) -> Self {
476
176M
                let src = src.as_ref();
477
176M
                assert!(src.len() >= $size);
478
176M
                let mut data: signed_to_unsigned!($typ) = 0;
479
176M
                unsafe {
480
176M
                    copy_nonoverlapping(
481
176M
                        src.as_ptr(),
482
176M
                        &mut data as *mut signed_to_unsigned!($typ) as *mut u8,
483
176M
                        $size);
484
176M
                }
485
176M
                (if le.is_little() { data.to_le() } else { data.to_be() }) as $typ
486
176M
            }
<u64 as scroll::ctx::FromCtx<scroll::endian::Endian, &[u8]>>::from_ctx
Line
Count
Source
475
4.81k
            fn from_ctx(src: &T, le: Endian) -> Self {
476
4.81k
                let src = src.as_ref();
477
4.81k
                assert!(src.len() >= $size);
478
4.81k
                let mut data: signed_to_unsigned!($typ) = 0;
479
4.81k
                unsafe {
480
4.81k
                    copy_nonoverlapping(
481
4.81k
                        src.as_ptr(),
482
4.81k
                        &mut data as *mut signed_to_unsigned!($typ) as *mut u8,
483
4.81k
                        $size);
484
4.81k
                }
485
4.81k
                (if le.is_little() { data.to_le() } else { data.to_be() }) as $typ
486
4.81k
            }
<u8 as scroll::ctx::FromCtx<scroll::endian::Endian, &[u8]>>::from_ctx
Line
Count
Source
475
454k
            fn from_ctx(src: &T, le: Endian) -> Self {
476
454k
                let src = src.as_ref();
477
454k
                assert!(src.len() >= $size);
478
454k
                let mut data: signed_to_unsigned!($typ) = 0;
479
454k
                unsafe {
480
454k
                    copy_nonoverlapping(
481
454k
                        src.as_ptr(),
482
454k
                        &mut data as *mut signed_to_unsigned!($typ) as *mut u8,
483
454k
                        $size);
484
454k
                }
485
454k
                (if le.is_little() { data.to_le() } else { data.to_be() }) as $typ
486
454k
            }
<u16 as scroll::ctx::FromCtx<scroll::endian::Endian, &[u8]>>::from_ctx
Line
Count
Source
475
4.76k
            fn from_ctx(src: &T, le: Endian) -> Self {
476
4.76k
                let src = src.as_ref();
477
4.76k
                assert!(src.len() >= $size);
478
4.76k
                let mut data: signed_to_unsigned!($typ) = 0;
479
4.76k
                unsafe {
480
4.76k
                    copy_nonoverlapping(
481
4.76k
                        src.as_ptr(),
482
4.76k
                        &mut data as *mut signed_to_unsigned!($typ) as *mut u8,
483
4.76k
                        $size);
484
4.76k
                }
485
4.76k
                (if le.is_little() { data.to_le() } else { data.to_be() }) as $typ
486
4.76k
            }
<u32 as scroll::ctx::FromCtx<scroll::endian::Endian, &[u8]>>::from_ctx
Line
Count
Source
475
15.1k
            fn from_ctx(src: &T, le: Endian) -> Self {
476
15.1k
                let src = src.as_ref();
477
15.1k
                assert!(src.len() >= $size);
478
15.1k
                let mut data: signed_to_unsigned!($typ) = 0;
479
15.1k
                unsafe {
480
15.1k
                    copy_nonoverlapping(
481
15.1k
                        src.as_ptr(),
482
15.1k
                        &mut data as *mut signed_to_unsigned!($typ) as *mut u8,
483
15.1k
                        $size);
484
15.1k
                }
485
15.1k
                (if le.is_little() { data.to_le() } else { data.to_be() }) as $typ
486
15.1k
            }
Unexecuted instantiation: <u8 as scroll::ctx::FromCtx<scroll::endian::Endian, _>>::from_ctx
Unexecuted instantiation: <i8 as scroll::ctx::FromCtx<scroll::endian::Endian, _>>::from_ctx
Unexecuted instantiation: <u16 as scroll::ctx::FromCtx<scroll::endian::Endian, _>>::from_ctx
Unexecuted instantiation: <i16 as scroll::ctx::FromCtx<scroll::endian::Endian, _>>::from_ctx
Unexecuted instantiation: <u32 as scroll::ctx::FromCtx<scroll::endian::Endian, _>>::from_ctx
Unexecuted instantiation: <i32 as scroll::ctx::FromCtx<scroll::endian::Endian, _>>::from_ctx
Unexecuted instantiation: <u64 as scroll::ctx::FromCtx<scroll::endian::Endian, _>>::from_ctx
Unexecuted instantiation: <i64 as scroll::ctx::FromCtx<scroll::endian::Endian, _>>::from_ctx
Unexecuted instantiation: <u128 as scroll::ctx::FromCtx<scroll::endian::Endian, _>>::from_ctx
Unexecuted instantiation: <i128 as scroll::ctx::FromCtx<scroll::endian::Endian, _>>::from_ctx
<u64 as scroll::ctx::FromCtx<scroll::endian::Endian, &[u8]>>::from_ctx
Line
Count
Source
475
128k
            fn from_ctx(src: &T, le: Endian) -> Self {
476
128k
                let src = src.as_ref();
477
128k
                assert!(src.len() >= $size);
478
128k
                let mut data: signed_to_unsigned!($typ) = 0;
479
128k
                unsafe {
480
128k
                    copy_nonoverlapping(
481
128k
                        src.as_ptr(),
482
128k
                        &mut data as *mut signed_to_unsigned!($typ) as *mut u8,
483
128k
                        $size);
484
128k
                }
485
128k
                (if le.is_little() { data.to_le() } else { data.to_be() }) as $typ
486
128k
            }
<u8 as scroll::ctx::FromCtx<scroll::endian::Endian, &[u8]>>::from_ctx
Line
Count
Source
475
7.47M
            fn from_ctx(src: &T, le: Endian) -> Self {
476
7.47M
                let src = src.as_ref();
477
7.47M
                assert!(src.len() >= $size);
478
7.47M
                let mut data: signed_to_unsigned!($typ) = 0;
479
7.47M
                unsafe {
480
7.47M
                    copy_nonoverlapping(
481
7.47M
                        src.as_ptr(),
482
7.47M
                        &mut data as *mut signed_to_unsigned!($typ) as *mut u8,
483
7.47M
                        $size);
484
7.47M
                }
485
7.47M
                (if le.is_little() { data.to_le() } else { data.to_be() }) as $typ
486
7.47M
            }
<u16 as scroll::ctx::FromCtx<scroll::endian::Endian, &[u8]>>::from_ctx
Line
Count
Source
475
4.04M
            fn from_ctx(src: &T, le: Endian) -> Self {
476
4.04M
                let src = src.as_ref();
477
4.04M
                assert!(src.len() >= $size);
478
4.04M
                let mut data: signed_to_unsigned!($typ) = 0;
479
4.04M
                unsafe {
480
4.04M
                    copy_nonoverlapping(
481
4.04M
                        src.as_ptr(),
482
4.04M
                        &mut data as *mut signed_to_unsigned!($typ) as *mut u8,
483
4.04M
                        $size);
484
4.04M
                }
485
4.04M
                (if le.is_little() { data.to_le() } else { data.to_be() }) as $typ
486
4.04M
            }
<u32 as scroll::ctx::FromCtx<scroll::endian::Endian, &[u8]>>::from_ctx
Line
Count
Source
475
2.10M
            fn from_ctx(src: &T, le: Endian) -> Self {
476
2.10M
                let src = src.as_ref();
477
2.10M
                assert!(src.len() >= $size);
478
2.10M
                let mut data: signed_to_unsigned!($typ) = 0;
479
2.10M
                unsafe {
480
2.10M
                    copy_nonoverlapping(
481
2.10M
                        src.as_ptr(),
482
2.10M
                        &mut data as *mut signed_to_unsigned!($typ) as *mut u8,
483
2.10M
                        $size);
484
2.10M
                }
485
2.10M
                (if le.is_little() { data.to_le() } else { data.to_be() }) as $typ
486
2.10M
            }
<u64 as scroll::ctx::FromCtx<scroll::endian::Endian, &[u8]>>::from_ctx
Line
Count
Source
475
142M
            fn from_ctx(src: &T, le: Endian) -> Self {
476
142M
                let src = src.as_ref();
477
142M
                assert!(src.len() >= $size);
478
142M
                let mut data: signed_to_unsigned!($typ) = 0;
479
142M
                unsafe {
480
142M
                    copy_nonoverlapping(
481
142M
                        src.as_ptr(),
482
142M
                        &mut data as *mut signed_to_unsigned!($typ) as *mut u8,
483
142M
                        $size);
484
142M
                }
485
142M
                (if le.is_little() { data.to_le() } else { data.to_be() }) as $typ
486
142M
            }
<i64 as scroll::ctx::FromCtx<scroll::endian::Endian, &[u8]>>::from_ctx
Line
Count
Source
475
9.59M
            fn from_ctx(src: &T, le: Endian) -> Self {
476
9.59M
                let src = src.as_ref();
477
9.59M
                assert!(src.len() >= $size);
478
9.59M
                let mut data: signed_to_unsigned!($typ) = 0;
479
9.59M
                unsafe {
480
9.59M
                    copy_nonoverlapping(
481
9.59M
                        src.as_ptr(),
482
9.59M
                        &mut data as *mut signed_to_unsigned!($typ) as *mut u8,
483
9.59M
                        $size);
484
9.59M
                }
485
9.59M
                (if le.is_little() { data.to_le() } else { data.to_be() }) as $typ
486
9.59M
            }
<u8 as scroll::ctx::FromCtx<scroll::endian::Endian, &[u8]>>::from_ctx
Line
Count
Source
475
282k
            fn from_ctx(src: &T, le: Endian) -> Self {
476
282k
                let src = src.as_ref();
477
282k
                assert!(src.len() >= $size);
478
282k
                let mut data: signed_to_unsigned!($typ) = 0;
479
282k
                unsafe {
480
282k
                    copy_nonoverlapping(
481
282k
                        src.as_ptr(),
482
282k
                        &mut data as *mut signed_to_unsigned!($typ) as *mut u8,
483
282k
                        $size);
484
282k
                }
485
282k
                (if le.is_little() { data.to_le() } else { data.to_be() }) as $typ
486
282k
            }
<u16 as scroll::ctx::FromCtx<scroll::endian::Endian, &[u8]>>::from_ctx
Line
Count
Source
475
1.72M
            fn from_ctx(src: &T, le: Endian) -> Self {
476
1.72M
                let src = src.as_ref();
477
1.72M
                assert!(src.len() >= $size);
478
1.72M
                let mut data: signed_to_unsigned!($typ) = 0;
479
1.72M
                unsafe {
480
1.72M
                    copy_nonoverlapping(
481
1.72M
                        src.as_ptr(),
482
1.72M
                        &mut data as *mut signed_to_unsigned!($typ) as *mut u8,
483
1.72M
                        $size);
484
1.72M
                }
485
1.72M
                (if le.is_little() { data.to_le() } else { data.to_be() }) as $typ
486
1.72M
            }
<u32 as scroll::ctx::FromCtx<scroll::endian::Endian, &[u8]>>::from_ctx
Line
Count
Source
475
8.35M
            fn from_ctx(src: &T, le: Endian) -> Self {
476
8.35M
                let src = src.as_ref();
477
8.35M
                assert!(src.len() >= $size);
478
8.35M
                let mut data: signed_to_unsigned!($typ) = 0;
479
8.35M
                unsafe {
480
8.35M
                    copy_nonoverlapping(
481
8.35M
                        src.as_ptr(),
482
8.35M
                        &mut data as *mut signed_to_unsigned!($typ) as *mut u8,
483
8.35M
                        $size);
484
8.35M
                }
485
8.35M
                (if le.is_little() { data.to_le() } else { data.to_be() }) as $typ
486
8.35M
            }
487
        }
488
489
        impl<'a, T> TryFromCtx<'a, Endian, T> for $typ where $typ: FromCtx<Endian, T>, T: AsRef<[u8]> {
490
            type Error = error::Error;
491
            #[inline]
492
0
            fn try_from_ctx(src: &'a T, le: Endian) -> result::Result<(Self, usize), Self::Error> {
493
0
                let src = src.as_ref();
494
0
                Self::try_from_ctx(src, le)
495
0
            }
Unexecuted instantiation: <u8 as scroll::ctx::TryFromCtx<scroll::endian::Endian, _>>::try_from_ctx
Unexecuted instantiation: <i8 as scroll::ctx::TryFromCtx<scroll::endian::Endian, _>>::try_from_ctx
Unexecuted instantiation: <u16 as scroll::ctx::TryFromCtx<scroll::endian::Endian, _>>::try_from_ctx
Unexecuted instantiation: <i16 as scroll::ctx::TryFromCtx<scroll::endian::Endian, _>>::try_from_ctx
Unexecuted instantiation: <u32 as scroll::ctx::TryFromCtx<scroll::endian::Endian, _>>::try_from_ctx
Unexecuted instantiation: <i32 as scroll::ctx::TryFromCtx<scroll::endian::Endian, _>>::try_from_ctx
Unexecuted instantiation: <u64 as scroll::ctx::TryFromCtx<scroll::endian::Endian, _>>::try_from_ctx
Unexecuted instantiation: <i64 as scroll::ctx::TryFromCtx<scroll::endian::Endian, _>>::try_from_ctx
Unexecuted instantiation: <u128 as scroll::ctx::TryFromCtx<scroll::endian::Endian, _>>::try_from_ctx
Unexecuted instantiation: <i128 as scroll::ctx::TryFromCtx<scroll::endian::Endian, _>>::try_from_ctx
496
        }
497
    };
498
}
499
500
macro_rules! ctx_impl {
501
    ($typ:tt, $size:expr) => {
502
        from_ctx_impl!($typ, $size);
503
     };
504
}
505
506
ctx_impl!(u8,  1);
507
ctx_impl!(i8,  1);
508
ctx_impl!(u16, 2);
509
ctx_impl!(i16, 2);
510
ctx_impl!(u32, 4);
511
ctx_impl!(i32, 4);
512
ctx_impl!(u64, 8);
513
ctx_impl!(i64, 8);
514
ctx_impl!(u128, 16);
515
ctx_impl!(i128, 16);
516
517
macro_rules! from_ctx_float_impl {
518
    ($typ:tt, $size:expr) => {
519
        impl<'a> FromCtx<Endian> for $typ {
520
            #[inline]
521
0
            fn from_ctx(src: &[u8], le: Endian) -> Self {
522
0
                assert!(src.len() >= ::core::mem::size_of::<Self>());
523
0
                let mut data: signed_to_unsigned!($typ) = 0;
524
0
                unsafe {
525
0
                    copy_nonoverlapping(
526
0
                        src.as_ptr(),
527
0
                        &mut data as *mut signed_to_unsigned!($typ) as *mut u8,
528
0
                        $size);
529
0
                    transmute(if le.is_little() { data.to_le() } else { data.to_be() })
530
                }
531
0
            }
Unexecuted instantiation: <f32 as scroll::ctx::FromCtx<scroll::endian::Endian>>::from_ctx
Unexecuted instantiation: <f64 as scroll::ctx::FromCtx<scroll::endian::Endian>>::from_ctx
532
        }
533
        impl<'a> TryFromCtx<'a, Endian> for $typ where $typ: FromCtx<Endian> {
534
            type Error = error::Error;
535
            #[inline]
536
0
            fn try_from_ctx(src: &'a [u8], le: Endian) -> result::Result<(Self, usize), Self::Error> {
537
0
                if $size > src.len () {
538
0
                    Err(error::Error::TooBig{size: $size, len: src.len()})
539
                } else {
540
0
                    Ok((FromCtx::from_ctx(src, le), $size))
541
                }
542
0
            }
Unexecuted instantiation: <f32 as scroll::ctx::TryFromCtx<scroll::endian::Endian>>::try_from_ctx
Unexecuted instantiation: <f64 as scroll::ctx::TryFromCtx<scroll::endian::Endian>>::try_from_ctx
543
        }
544
    }
545
}
546
547
from_ctx_float_impl!(f32, 4);
548
from_ctx_float_impl!(f64, 8);
549
550
into_ctx_impl!(u8,  1);
551
into_ctx_impl!(i8,  1);
552
into_ctx_impl!(u16, 2);
553
into_ctx_impl!(i16, 2);
554
into_ctx_impl!(u32, 4);
555
into_ctx_impl!(i32, 4);
556
into_ctx_impl!(u64, 8);
557
into_ctx_impl!(i64, 8);
558
into_ctx_impl!(u128, 16);
559
into_ctx_impl!(i128, 16);
560
561
macro_rules! into_ctx_float_impl {
562
    ($typ:tt, $size:expr) => {
563
        impl IntoCtx<Endian> for $typ {
564
            #[inline]
565
0
            fn into_ctx(self, dst: &mut [u8], le: Endian) {
566
0
                assert!(dst.len() >= $size);
567
0
                write_into!(signed_to_unsigned!($typ), $size, transmute::<$typ, signed_to_unsigned!($typ)>(self), dst, le);
568
0
            }
Unexecuted instantiation: <f32 as scroll::ctx::IntoCtx<scroll::endian::Endian>>::into_ctx
Unexecuted instantiation: <f64 as scroll::ctx::IntoCtx<scroll::endian::Endian>>::into_ctx
569
        }
570
        impl<'a> IntoCtx<Endian> for &'a $typ {
571
            #[inline]
572
0
            fn into_ctx(self, dst: &mut [u8], le: Endian) {
573
0
                (*self).into_ctx(dst, le)
574
0
            }
Unexecuted instantiation: <&f32 as scroll::ctx::IntoCtx<scroll::endian::Endian>>::into_ctx
Unexecuted instantiation: <&f64 as scroll::ctx::IntoCtx<scroll::endian::Endian>>::into_ctx
575
        }
576
        impl TryIntoCtx<Endian> for $typ where $typ: IntoCtx<Endian> {
577
            type Error = error::Error;
578
            #[inline]
579
0
            fn try_into_ctx(self, dst: &mut [u8], le: Endian) -> error::Result<usize> {
580
0
                if $size > dst.len () {
581
0
                    Err(error::Error::TooBig{size: $size, len: dst.len()})
582
                } else {
583
0
                    <$typ as IntoCtx<Endian>>::into_ctx(self, dst, le);
584
0
                    Ok($size)
585
                }
586
0
            }
Unexecuted instantiation: <f32 as scroll::ctx::TryIntoCtx<scroll::endian::Endian>>::try_into_ctx
Unexecuted instantiation: <f64 as scroll::ctx::TryIntoCtx<scroll::endian::Endian>>::try_into_ctx
587
        }
588
        impl<'a> TryIntoCtx<Endian> for &'a $typ {
589
            type Error = error::Error;
590
            #[inline]
591
0
            fn try_into_ctx(self, dst: &mut [u8], le: Endian) -> error::Result<usize> {
592
0
                (*self).try_into_ctx(dst, le)
593
0
            }
Unexecuted instantiation: <&f32 as scroll::ctx::TryIntoCtx<scroll::endian::Endian>>::try_into_ctx
Unexecuted instantiation: <&f64 as scroll::ctx::TryIntoCtx<scroll::endian::Endian>>::try_into_ctx
594
        }
595
    }
596
}
597
598
into_ctx_float_impl!(f32, 4);
599
into_ctx_float_impl!(f64, 8);
600
601
impl<'a> TryFromCtx<'a, StrCtx> for &'a str {
602
    type Error = error::Error;
603
    #[inline]
604
    /// Read a `&str` from `src` using `delimiter`
605
0
    fn try_from_ctx(src: &'a [u8], ctx: StrCtx) -> Result<(Self, usize), Self::Error> {
606
0
        let len = match ctx {
607
0
            StrCtx::Length(len) => len,
608
0
            StrCtx::Delimiter(delimiter) => src.iter().take_while(|c| **c != delimiter).count(),
609
0
            StrCtx::DelimiterUntil(delimiter, len) => {
610
0
                if len > src.len() {
611
0
                    return Err(error::Error::TooBig{size: len, len: src.len()});
612
0
                };
613
0
                src
614
0
                    .iter()
615
0
                    .take_while(|c| **c != delimiter)
616
0
                    .take(len)
617
0
                    .count()
618
            }
619
        };
620
621
0
        if len > src.len() {
622
0
            return Err(error::Error::TooBig{size: len, len: src.len()});
623
0
        };
624
0
625
0
        match str::from_utf8(&src[..len]) {
626
0
            Ok(res) => Ok((res, len + ctx.len())),
627
0
            Err(_) => Err(error::Error::BadInput{size: src.len(), msg: "invalid utf8"})
628
        }
629
0
    }
630
}
631
632
impl<'a, T> TryFromCtx<'a, StrCtx, T> for &'a str where T: AsRef<[u8]> {
633
    type Error = error::Error;
634
    #[inline]
635
0
    fn try_from_ctx(src: &'a T, ctx: StrCtx) -> result::Result<(Self, usize), Self::Error> {
636
0
        let src = src.as_ref();
637
0
        TryFromCtx::try_from_ctx(src, ctx)
638
0
    }
639
}
640
641
impl<'a> TryIntoCtx for &'a [u8] {
642
    type Error = error::Error;
643
    #[inline]
644
0
    fn try_into_ctx(self, dst: &mut [u8], _ctx: ()) -> error::Result<usize> {
645
0
        let src_len = self.len() as isize;
646
0
        let dst_len = dst.len() as isize;
647
0
        // if src_len < 0 || dst_len < 0 || offset < 0 {
648
0
        //     return Err(error::Error::BadOffset(format!("requested operation has negative casts: src len: {} dst len: {} offset: {}", src_len, dst_len, offset)).into())
649
0
        // }
650
0
        if src_len > dst_len {
651
0
            Err(error::Error::TooBig{ size: self.len(), len: dst.len()})
652
        } else {
653
0
            unsafe { copy_nonoverlapping(self.as_ptr(), dst.as_mut_ptr(), src_len as usize) };
654
0
            Ok(self.len())
655
        }
656
0
    }
657
}
658
659
// TODO: make TryIntoCtx use StrCtx for awesomeness
660
impl<'a> TryIntoCtx for &'a str {
661
    type Error = error::Error;
662
    #[inline]
663
0
    fn try_into_ctx(self, dst: &mut [u8], _ctx: ()) -> error::Result<usize> {
664
0
        let bytes = self.as_bytes();
665
0
        TryIntoCtx::try_into_ctx(bytes, dst, ())
666
0
    }
667
}
668
669
// TODO: we can make this compile time without size_of call, but compiler probably does that anyway
670
macro_rules! sizeof_impl {
671
    ($ty:ty) => {
672
        impl SizeWith<Endian> for $ty {
673
            #[inline]
674
0
            fn size_with(_ctx: &Endian) -> usize {
675
0
                size_of::<$ty>()
676
0
            }
Unexecuted instantiation: <u8 as scroll::ctx::SizeWith<scroll::endian::Endian>>::size_with
Unexecuted instantiation: <i8 as scroll::ctx::SizeWith<scroll::endian::Endian>>::size_with
Unexecuted instantiation: <u16 as scroll::ctx::SizeWith<scroll::endian::Endian>>::size_with
Unexecuted instantiation: <i16 as scroll::ctx::SizeWith<scroll::endian::Endian>>::size_with
Unexecuted instantiation: <u32 as scroll::ctx::SizeWith<scroll::endian::Endian>>::size_with
Unexecuted instantiation: <i32 as scroll::ctx::SizeWith<scroll::endian::Endian>>::size_with
Unexecuted instantiation: <u64 as scroll::ctx::SizeWith<scroll::endian::Endian>>::size_with
Unexecuted instantiation: <i64 as scroll::ctx::SizeWith<scroll::endian::Endian>>::size_with
Unexecuted instantiation: <u128 as scroll::ctx::SizeWith<scroll::endian::Endian>>::size_with
Unexecuted instantiation: <i128 as scroll::ctx::SizeWith<scroll::endian::Endian>>::size_with
Unexecuted instantiation: <f32 as scroll::ctx::SizeWith<scroll::endian::Endian>>::size_with
Unexecuted instantiation: <f64 as scroll::ctx::SizeWith<scroll::endian::Endian>>::size_with
Unexecuted instantiation: <usize as scroll::ctx::SizeWith<scroll::endian::Endian>>::size_with
Unexecuted instantiation: <isize as scroll::ctx::SizeWith<scroll::endian::Endian>>::size_with
677
        }
678
    }
679
}
680
681
sizeof_impl!(u8);
682
sizeof_impl!(i8);
683
sizeof_impl!(u16);
684
sizeof_impl!(i16);
685
sizeof_impl!(u32);
686
sizeof_impl!(i32);
687
sizeof_impl!(u64);
688
sizeof_impl!(i64);
689
sizeof_impl!(u128);
690
sizeof_impl!(i128);
691
sizeof_impl!(f32);
692
sizeof_impl!(f64);
693
sizeof_impl!(usize);
694
sizeof_impl!(isize);
695
696
impl FromCtx<Endian> for usize {
697
    #[inline]
698
0
    fn from_ctx(src: &[u8], le: Endian) -> Self {
699
0
        let size = ::core::mem::size_of::<Self>();
700
0
        assert!(src.len() >= size);
701
0
        let mut data: usize = 0;
702
0
        unsafe {
703
0
            copy_nonoverlapping(
704
0
                src.as_ptr(),
705
0
                &mut data as *mut usize as *mut u8,
706
0
                size);
707
0
            if le.is_little() { data.to_le() } else { data.to_be() }
708
        }
709
0
    }
710
}
711
712
impl<'a> TryFromCtx<'a, Endian> for usize where usize: FromCtx<Endian> {
713
    type Error = error::Error;
714
    #[inline]
715
0
    fn try_from_ctx(src: &'a [u8], le: Endian) -> result::Result<(Self, usize), Self::Error> {
716
0
        let size = ::core::mem::size_of::<usize>();
717
0
        if size > src.len () {
718
0
            Err(error::Error::TooBig{size, len: src.len()})
719
        } else {
720
0
            Ok((FromCtx::from_ctx(src, le), size))
721
        }
722
0
    }
723
}
724
725
impl<'a> TryFromCtx<'a, usize> for &'a[u8] {
726
    type Error = error::Error;
727
    #[inline]
728
0
    fn try_from_ctx(src: &'a [u8], size: usize) -> result::Result<(Self, usize), Self::Error> {
729
0
        if size > src.len () {
730
0
            Err(error::Error::TooBig{size, len: src.len()})
731
        } else {
732
0
            Ok((&src[..size], size))
733
        }
734
0
    }
735
}
736
737
impl IntoCtx<Endian> for usize {
738
    #[inline]
739
0
    fn into_ctx(self, dst: &mut [u8], le: Endian) {
740
0
        let size = ::core::mem::size_of::<Self>();
741
0
        assert!(dst.len() >= size);
742
0
        let mut data = if le.is_little() { self.to_le() } else { self.to_be() };
743
0
        let data = &mut data as *mut usize as *mut u8;
744
0
        unsafe {
745
0
            copy_nonoverlapping(data, dst.as_mut_ptr(), size);
746
0
        }
747
0
    }
748
}
749
750
impl TryIntoCtx<Endian> for usize where usize: IntoCtx<Endian> {
751
    type Error = error::Error;
752
    #[inline]
753
0
    fn try_into_ctx(self, dst: &mut [u8], le: Endian) -> error::Result<usize> {
754
0
        let size = ::core::mem::size_of::<usize>();
755
0
        if size > dst.len() {
756
0
            Err(error::Error::TooBig{size, len: dst.len()})
757
        } else {
758
0
            <usize as IntoCtx<Endian>>::into_ctx(self, dst, le);
759
0
            Ok(size)
760
        }
761
0
    }
762
}
763
764
#[cfg(feature = "std")]
765
impl<'a> TryFromCtx<'a> for &'a CStr {
766
    type Error = error::Error;
767
    #[inline]
768
    fn try_from_ctx(src: &'a [u8], _ctx: ()) -> result::Result<(Self, usize), Self::Error> {
769
        let null_byte = match src.iter().position(|b| *b == 0) {
770
            Some(ix) => ix,
771
            None => return Err(error::Error::BadInput {
772
                size: 0,
773
                msg: "The input doesn't contain a null byte",
774
            })
775
        };
776
777
        let cstr = unsafe { CStr::from_bytes_with_nul_unchecked(&src[..=null_byte]) };
778
        Ok((cstr, null_byte+1))
779
    }
780
}
781
782
#[cfg(feature = "std")]
783
impl<'a> TryFromCtx<'a> for CString {
784
    type Error = error::Error;
785
    #[inline]
786
    fn try_from_ctx(src: &'a [u8], _ctx: ()) -> result::Result<(Self, usize), Self::Error> {
787
        let (raw, bytes_read) = <&CStr as TryFromCtx>::try_from_ctx(src, _ctx)?;
788
        Ok((raw.to_owned(), bytes_read))
789
    }
790
}
791
792
#[cfg(feature = "std")]
793
impl<'a> TryIntoCtx for &'a CStr {
794
    type Error = error::Error;
795
    #[inline]
796
    fn try_into_ctx(self, dst: &mut [u8], _ctx: ()) -> error::Result<usize> {
797
        let data = self.to_bytes_with_nul();
798
799
        if dst.len() < data.len() {
800
            Err(error::Error::TooBig {
801
                size: dst.len(),
802
                len: data.len(),
803
            })
804
        } else {
805
            unsafe {
806
                copy_nonoverlapping(data.as_ptr(), dst.as_mut_ptr(), data.len());
807
            }
808
809
            Ok(data.len())
810
        }
811
    }
812
}
813
814
#[cfg(feature = "std")]
815
impl TryIntoCtx for CString {
816
    type Error = error::Error;
817
    #[inline]
818
    fn try_into_ctx(self, dst: &mut [u8], _ctx: ()) -> error::Result<usize> {
819
        self.as_c_str().try_into_ctx(dst, ())
820
    }
821
}
822
823
824
// example of marshalling to bytes, let's wait until const is an option
825
// impl FromCtx for [u8; 10] {
826
//     fn from_ctx(bytes: &[u8], _ctx: Endian) -> Self {
827
//         let mut dst: Self = [0; 10];
828
//         assert!(bytes.len() >= dst.len());
829
//         unsafe {
830
//             copy_nonoverlapping(bytes.as_ptr(), dst.as_mut_ptr(), dst.len());
831
//         }
832
//         dst
833
//     }
834
// }
835
836
#[cfg(test)]
837
mod tests {
838
    use super::*;
839
840
    #[test]
841
    #[cfg(feature = "std")]
842
    fn parse_a_cstr() {
843
        let src = CString::new("Hello World").unwrap();
844
        let as_bytes = src.as_bytes_with_nul();
845
846
        let (got, bytes_read) = <&CStr as TryFromCtx>::try_from_ctx(as_bytes, ()).unwrap();
847
848
        assert_eq!(bytes_read, as_bytes.len());
849
        assert_eq!(got, src.as_c_str());
850
    }
851
852
    #[test]
853
    #[cfg(feature = "std")]
854
    fn round_trip_a_c_str() {
855
        let src = CString::new("Hello World").unwrap();
856
        let src = src.as_c_str();
857
        let as_bytes = src.to_bytes_with_nul();
858
859
        let mut buffer = vec![0; as_bytes.len()];
860
        let bytes_written = src.try_into_ctx(&mut buffer, ()).unwrap();
861
        assert_eq!(bytes_written, as_bytes.len());
862
863
        let (got, bytes_read) = <&CStr as TryFromCtx>::try_from_ctx(&buffer, ()).unwrap();
864
865
        assert_eq!(bytes_read, as_bytes.len());
866
        assert_eq!(got, src);
867
    }
868
}
869
870