/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 | | |