ender/lib.rs
1#![cfg_attr(feature = "unstable", feature(doc_cfg))]
2#![cfg_attr(feature = "unstable", feature(never_type))]
3#![cfg_attr(not(feature = "std"), no_std)]
4
5//! A rust **EN**coding and **DE**coding library for writing custom protocols and file formats.
6//!
7//! It aims to be **intuitive**, **expandable** and **correct**.
8//!
9//! # Example
10//!
11//! ```rust
12//! # use ender::*;
13//! # use ender::io::*;
14//! # #[derive(Debug, PartialEq, Encode, Decode)]
15//! # #[ender(crate: ender)]
16//! # struct Person {
17//! # name: String,
18//! # age: u64,
19//! # height: f32,
20//! # eye_color: EyeColor,
21//! # }
22//! #
23//! # #[derive(Debug, PartialEq, Encode, Decode)]
24//! # #[ender(crate: ender)]
25//! # enum EyeColor {
26//! # Brown,
27//! # Blue,
28//! # Green,
29//! # Gray,
30//! # Black
31//! # }
32//! #
33//! # fn hidden() -> EncodingResult<()> {
34//! let mut the_matrix = vec![0u8; 256];
35//!
36//! // Summon John into existence!
37//! let john = Person {
38//! name: String::from("John"),
39//! age: 35,
40//! height: 1.75,
41//! eye_color: EyeColor::Brown
42//! };
43//!
44//! // Encode John into the matrix
45//! encode_with(SliceMut::new(&mut the_matrix), Context::default(), &john)?;
46//!
47//! // Bring him back
48//! let john_2: Person = decode_with(Slice::new(&the_matrix), Context::default())?;
49//!
50//! // But is he really the same John?
51//! assert_eq!(john, john_2);
52//! # Ok(())
53//! # }
54//! # fn main() { hidden().unwrap() }
55//! ```
56//!
57//! # Encoding format
58//!
59//! The encoding process aims at being **correct** and **unsurprising**.
60//!
61//!
62//!
63//! Ende supports a series of options, which can be changed *during*
64//! the encoding/decoding process to get certain parts of a binary format
65//! to be represented exactly how you want them.
66//!
67//! This can be done in a manual implementation as well as with the derive
68//! macro, using the custom attributes provided.
69//!
70//! Certain types also support "flattening", which means omitting information
71//! known from the context.
72//! For instance, you can omit writing whether an `Option` is present if
73//! that information is already stored somewhere else in the file format.
74//!
75//! For *integer primitives*, *usize*, and *enum variants* you can customize the endianness,
76//! the numerical encoding (read: var-ints), the bit-width (how many bytes
77//! does a `usize` or enum variant take up in your encoding format?),
78//! the max-size (to prevent maliciously crafted binary formats to cause
79//! unlimited-size allocations).
80//!
81//! ### Var-int format
82//! - Fixed - not var-int, simply encode the number as-is
83//! - Leb128
84//! - Protobuf - both its zigzag and "wasteful" variants
85//!
86//! ### String formats
87//! As for strings, currently length-prefixed, null-terminated (with and without
88//! a maximum length) strings are supported, as well as the following encoding formats.
89//! - Ascii
90//! - Utf8
91//! - Utf16
92//! - Utf32
93//! - Windows1252
94//!
95//! If you need a new var-int encoding or string encoding added, feel free
96//! to open a PR!
97//!
98//! # Motivation
99//!
100//! One of the main reasons I made this library is because I found myself
101//! needing more sophisticate macros and runtime flexibility for existing
102//! binary formats.
103//!
104//! While for example [`bincode`](https://crates.io/crates/bincode) is perfectly
105//! ok for many applications, `ender` was made with compatibility with existing
106//! data formats in mind.
107//!
108//! For this very purpose, many internal details of the encoder are exposed
109//! through settings or the derive macros themselves, for the purpose of fine-tuning
110//! the data format exactly how you want it, while providing an easy-to-understand interface.
111//!
112//! # Deriving
113//!
114//! A big selling point of `ender` are its macros, which allow you to heavily
115//! customize the codegen through a series of attributes.
116//! To learn more about those, check out `DERIVE.md` in this crate's repository root.
117//!
118//! # MSRV
119//!
120//! This crate will always target the latest version of rust, in order
121//! to get access to new features as soon as they are released and
122//! update the code accordingly if beneficial.
123//! Of course, breaking API changes will be accompanied by a major version
124//! bump.
125//!
126//! # Future plans
127//!
128//! I plan on adding support for `async` io through a feature gate.
129
130#[cfg(feature = "alloc")]
131extern crate alloc;
132
133use core::any::Any;
134use core::fmt::Debug;
135use core::hash::Hash;
136use core::mem::replace;
137
138use parse_display::Display;
139
140/// # The Ender Derivonomicon
141///
142/// The following is a full and up-to-date breakdown of the `Encode` and `Decode` derive macros,
143/// their attributes, how they work and all the possible ways you can modify the codegen.
144///
145/// ## Flags Essentials
146///
147/// All flags follow the following format:
148/// `#[ender(flag1; flag2; flag2; ...)]`
149///
150/// The 2 special flags `en` and `de`, called Scope flags, can be used only at the beginning
151/// of the list to indicate that all the flags in the attribute declaration only apply to the
152/// encoding process (`en`) or the decoding process (`de`).
153///
154/// If neither of those flags are specified, then it is assumed that all the flags in the
155/// attribute declaration apply to both encoding and decoding.
156///
157/// Whenever a flag is said to accept an `$expr`, this means any expression is accepted,
158/// and that it will have access to an immutable reference to all the fields that have been
159/// decoded so far (actually all the fields while encoding), but the `validate` flag additionally
160/// provides a reference to the field it is applied on.<br>
161/// If the fields are part of a tuple struct/variant, the references will be named `m{idx}` where `idx` are the
162/// indexes of the tuple fields (E.G. `m0`, `m1`, ...), otherwise their names will match those of the fields themselves.
163///
164/// A seeking impl is an implementation of [`Encode`] or [`Decode`] that has an additional [`Seek`]
165/// trait bound
166/// When a flag is said to be a `seek` flag, it means that when used anywhere it will switch the
167/// impl to a seeking impl.
168///
169/// A borrowing impl is an implementation of [`Encode`] or [`Decode`] that has a [`BorrowRead`]
170/// trait bound rather than a [`Read`] one.
171/// When a flag is said to be a `borrow` flag, it means that when used anywhere it will switch the
172/// impl to a borrowing impl.
173///
174/// Borrowing and seeking impls can be combined.
175///
176/// The flags currently implemented are split into 5 groups:
177/// # 1. Setting Modifiers
178/// Setting-Modifier flags temporarily change certain settings of the encoder and can be applied
179/// to Fields or Items (the whole struct or enum).<br>
180/// Multiple can be specified at the same time, as long as they don't overlap.<br>
181/// All setting modifiers follow the `$target: $mod1, $mod2, ...` pattern.
182///
183/// - Endianness modifiers: `big_endian`, `little_endian`
184/// - Available targets:
185/// - `num`
186/// - `size`
187/// - `variant`
188/// - `string`
189/// - Numerical encoding modifiers: `fixed`, `leb128`, `protobuf_wasteful`, `protobuf_zz`
190/// - Available targets:
191/// - `num`,
192/// - `size`,
193/// - `variant`
194/// - Bit-width modifiers: `bit8`, `bit16`, `bit32`, `bit64`, `bit128`
195/// - Available targets:
196/// - `size`
197/// - `variant`
198/// - Max-size modifier: `max = $expr`
199/// - Available targets:
200/// - `size`
201/// - String encoding modifier: `ascii`, `utf8`, `utf16`, `utf32`, `windows1252`
202/// - Available targets:
203/// - `string`
204/// - String length encoding modifier: `len_prefix`, `null_term`, `null_term($max:expr)`
205/// - Available targets:
206/// - `string`
207/// <br>
208/// ### Example:
209/// ```rust
210/// # use ender::{Encode, Decode};
211/// #[derive(Encode, Decode)]
212/// # #[ender(crate: ender)]
213/// /// The variants of this enum will be encoded in the little endian ordering,
214/// /// using a fixed numerical encoding and a 32-bit width.
215/// #[ender(variant: little_endian, fixed, bit32)]
216/// enum MyEnum {
217/// VariantA {
218/// /// The length of this String will be encoded using big endian ordering,
219/// /// fixed numerical encoding and 16-bit width, with a max length of 100
220/// #[ender(size: big_endian, fixed, bit16, max = 100)]
221/// field: String,
222/// /// Encode this String with utf16 big endian, and prefix it with its length
223/// #[ender(string: utf16, big_endian, len_prefix)]
224/// utf_16: String,
225/// /// Encode this String as an utf8 null-terminated string
226/// #[ender(string: utf8, null_term)]
227/// utf_8: String,
228/// /// Encode this String as an utf8 null-terminated string with a fixed length of `15`
229/// /// Exactly `15` bytes will be read in all cases, and the length of the string is given
230/// /// by the first occurrence of a null byte or the `15` byte mark.
231/// #[ender(string: utf8, null_term(15))]
232/// max_15: String,
233/// },
234/// VariantB {
235/// /// This number will be encoded using little endian ordering, and the
236/// /// leb128 [NumEncoding][`ender::NumEncoding`]
237/// #[ender(num: little_endian, leb128)]
238/// field: u64,
239/// #[ender(num: protobuf_zz)]
240/// zigzag: i128,
241/// },
242/// }
243/// ```
244/// # 2. Stream Modifiers
245/// Stream-Modifier flags temporarily change the underlying reader/writer, and can be applied
246/// to Fields or Items.<br>
247/// Note that the order in which stream modifiers are declared is very important:<br>
248/// They are applied in the declaration order during encoding, but in the reverse order during
249/// decoding, for consistency. However, the item-level modifiers take priority over the field-level
250/// modifiers (see [ambiguous example](#ambiguous-example)).<br>
251/// * `redir: $path(...)` - Uses the given path to find an encoding/decoding function which
252/// alters the writer/reader and passes a modified encoder to a closure.<br>
253/// This can be used to implement encryption, compression and other transformations of the
254/// underlying stream, or even redirections to another stream.<br>
255/// The implementation of a redir function can be non-trivial and the signature can be
256/// cryptic, therefore it is recommended you only create your own stream transforms if you know what
257/// you're doing, in which case you should take a look at the [facade module][`facade`].<br>
258/// * If the scope is Encode, the path must be callable as `encode`.<br>
259/// * If the scope is Decode, the path must be callable as `decode`.<br>
260/// * If no scope is specified, the path must point to a module with encoding and decoding functions
261/// with the same signatures as above.
262/// * `ptr $seek: $expr` - This is a `seek` flag. Seeks to the location given by $expr
263/// (which must be of type usize or isize) relative to $seek - which can be
264/// "start", "end" or "cur"rrent - before encoding/decoding this field, then seeks back to the
265/// previous location.
266/// ### Example:
267/// ```rust
268/// # use ender::{Encode, Decode};
269/// # use ender::facade::fake::*;
270/// #[derive(Encode, Decode)]
271/// # #[ender(crate: ender)]
272/// struct MyStruct {
273/// secret_key: Vec<u8>,
274/// iv: Vec<u8>,
275/// /// While **encoding**, this field is compressed -> encrypted.
276/// /// While **decoding**, this field is decrypted -> decompressed.
277/// #[ender(redir: gzip(9))]
278/// #[ender(redir: aes(iv, secret_key))]
279/// super_secret_data: Vec<u8>,
280/// file_pointer: usize,
281/// /// Marks the current offset, seeks to `file_pointer` bytes from the start of the file,
282/// /// encodes/decodes the field, then seeks back.
283/// #[ender(ptr start: *file_pointer)]
284/// apple_count: u64,
285/// /// This field is effectively laid *right after* `file_pointer`
286/// /// in the binary representation.
287/// other_data: i32,
288/// }
289/// ```
290/// ### Ambiguous example:
291/// ```rust
292/// # use ender::{Encode, Decode};
293/// # use ender::facade::fake::*;
294/// #[derive(Encode, Decode)]
295/// # #[ender(crate: ender)]
296/// /// Because of the priority rules of items over fields, this is ambiguous, see below
297/// #[ender(redir: gzip(9))]
298/// struct MyStruct {
299/// /// While **encoding**, this field is encrypted -> compressed.
300/// /// While **decoding**, this field is decompressed -> decrypted.
301/// /// Because the "compressed" flag is declared before the "encrypted" flag, one might
302/// /// think they are applied in that order. However, since the item-level flag takes priority,
303/// /// it is applied *after* the field flag.
304/// ///
305/// /// According to your needs, this might not be what you want, so be careful when mixing
306/// /// item-level and field-level stream modifiers.
307/// #[ender(redir: aes(&[], &[]))]
308/// super_secret_data: Vec<u8>,
309/// }
310/// ```
311/// # 3. Function Modifiers
312/// Function-Modifier flags change the function that is used to encode/decode a field or item.
313/// * `serde: $crate` - Field will be serialized/deserialized with a serde compatibility layer.<br>
314/// Optionally, the serde crate name can be specified (useful if the serde crate was re-exported under
315/// another name).
316/// * `with: $path` - Uses the given path to find the encoding/decoding function.<br>
317/// * If the scope is Encode, the path must be callable as
318/// `fn<T: Write>(&V, &mut ender::Encoder<T>) -> EncodingResult<()>`
319/// where `V` is the type of the field (the function is allowed to be generic over `V`).<br>
320/// * If the scope is Decode, the path must be callable as
321/// `fn<T: Read>(&mut ender::Encoder<T>) -> EncodingResult<V>`
322/// where `V` is the type of the field (the function is allowed to be generic over `V`).<br>
323/// * If no scope is specified, the path must point to a module with encoding and decoding functions
324/// with the same signatures as above.
325/// ### Example:
326/// ```rust
327/// # use ender::{Encode, Decode};
328/// # use ender::facade::fake::rsa;
329/// # use uuid::Uuid;
330/// # use person_encoder::Person;
331/// #[derive(Encode, Decode)]
332/// # #[ender(crate: ender)]
333/// struct Friends {
334/// /// Has Serialize/Deserialize implementations, but no Encode/Decode implementations.
335/// /// A perfect fit for integrating with serde!
336/// #[ender(serde)]
337/// uuid: Uuid,
338/// /// Here we demonstrate how the with flag changes based on whether a scope
339/// /// is declared. This:
340/// #[ender(with: person_encoder)]
341/// friend1: Person,
342/// /// ...is equivalent to this!
343/// #[ender(en; with: person_encoder::encode)]
344/// #[ender(de; with: person_encoder::decode)]
345/// friend2: Person,
346/// /// Not the smartest way to store a private key!
347/// private_key: Vec<u8>,
348/// public_key: Vec<u8>,
349/// /// This block of data will be encrypted before being encoded using the public key,
350/// /// and decrypted after being decoded using the private key.
351/// #[ender(with: rsa(public_key, private_key))]
352/// even_more_secret_data: Vec<u8>,
353/// }
354/// mod person_encoder {
355/// # use ender::io::{Write, Read};
356/// # use ender::{Encoder, EncodingResult, Encode};
357/// #
358/// # pub struct Person {
359/// # name: String,
360/// # surname: String,
361/// # age: u32,
362/// # }
363/// #
364/// pub fn encode<T: Write>(person: &Person, encoder: &mut Encoder<T>) -> EncodingResult<()> {
365/// /* ... */
366/// # person.name.encode(encoder)?;
367/// # person.surname.encode(encoder)?;
368/// # person.age.encode(encoder)?;
369/// # Ok(())
370/// }
371/// #
372/// pub fn decode<T: Read>(encoder: &mut Encoder<T>) -> EncodingResult<Person> {
373/// /* ... */
374/// # Ok(Person {
375/// # name: encoder.decode_value()?,
376/// # surname: encoder.decode_value()?,
377/// # age: encoder.decode_value()?,
378/// # })
379/// }
380/// }
381/// ```
382/// # 4. Type Modifiers
383/// Type-Modifier flags change the type of the value that's encoded, and change it back after
384/// decoding it.<br>
385/// * `as: $ty` - Converts the value of the field to `$ty` before encoding it
386/// and back to the original field type after decoding it.<br>
387/// The conversion is done through the `as` keyword.
388/// * `into: $ty` - Converts the value of the field to `$ty` before encoding it
389/// and back to the original field type after decoding it.<br>
390/// The conversion is done through the `Into` trait.
391/// * `from: $ty` - Converts the value of the field to `$ty` before encoding it
392/// and back to the original field type after decoding it.<br>
393/// The conversion is done through the `From` trait.
394/// ### Example:
395/// ```rust
396/// # use ender::{Encode, Decode};
397/// #
398/// #[derive(Encode, Decode)]
399/// # #[ender(crate: ender)]
400/// struct Mountain {
401/// /// Height is encoded as a `u16`, then decoded back to a `f64`.
402/// /// These operations are performed using the `as` keyword.
403/// #[ender(as: u16)]
404/// height: f64,
405/// /// Boulder is encoded as a `BigRock`, then decoded back to a `Boulder`.
406/// /// This can be done because `BigRock` implements `From<Boulder>`, and
407/// /// `Boulder` implements `From<BigRock>`.
408/// #[ender(into: BigRock)]
409/// boulder: Boulder,
410/// }
411///
412/// /// Note: `BigRock` is required to implement `Encode` and `Decode`,
413/// /// but `Boulder` is not.
414/// #[derive(Encode, Decode)]
415/// # #[ender(crate: ender)]
416/// struct BigRock {
417/// weight: f64
418/// }
419///
420/// /* From<Boulder> and From<BigRock> impls here... */
421/// # impl From<Boulder> for BigRock {
422/// # fn from(value: Boulder) -> Self {
423/// # Self {
424/// # weight: value.weight
425/// # }
426/// # }
427/// # }
428/// #
429/// # #[derive(Clone)]
430/// # struct Boulder {
431/// # weight: f64,
432/// # radius: f64
433/// # }
434/// #
435/// # impl From<BigRock> for Boulder {
436/// # fn from(value: BigRock) -> Self {
437/// # Self {
438/// # weight: value.weight,
439/// # radius: 1.0
440/// # }
441/// # }
442/// # }
443/// ```
444/// # 5. Helpers
445/// Helper flags change certain parameters or add conditions for when a field
446/// or item should be encoded/decoded.<br>
447/// * `crate: $crate` - Overwrites the default crate name which is assumed to be `ender`.
448/// Can only be applied to items.
449/// * `if: $expr` - The field will only be encoded/decoded if the given expression
450/// evaluates to true, otherwise the default value is computed.
451/// * `default: $expr` - Overrides the default fallback for when a value can't be
452/// decoded, which is `Default::default()`
453/// * `skip` - Will not encode/decode this field.
454/// When decoding, computes the default value.
455/// * `validate: $expr, $format_string, $arg1, $arg2, $arg3, ...` - Before encoding/after decoding, returns an error if the
456/// expression evaluates to false. The error message will use the given formatting (if present).
457/// * `flatten: $expr` - Indicates that the length of the given field (for example
458/// a Vec or HashMap) doesn't need to be encoded/decoded, because it is known from the context.
459/// Can also be used with an `Option` in conjunction with the `if` flag and without the `$expr`
460/// to indicate that the presence of an optional value is known from the context.
461/// * `borrow: $lif1, $lif2, $lif3, ...` - This is a `borrow` flag. Indicates this field
462/// should be decoded using its borrowing decode implementation, and allows you to optionally specify a
463/// set of lifetimes to override those normally inferred by the macro. These lifetimes will be bound
464/// to the lifetime of the encoder's data.
465/// * `goto $seek: $expr` - This is a `seek` flag. Indicates a jump to a different stream position
466/// before encoding this field or item.
467/// $seek can be any of "start", "end" or "cur", while $expr must produce a value of
468/// type usize or isize relative to $seek.<br>
469/// If you need the stream position to be restored after encoding/decoding the field, see the
470/// `ptr` *stream modifier`.
471/// * `pos_tracker: $ident` - This is a `seek` flag. Stores the current stream position in a
472/// variable with the given name.
473/// Note that the position is stored *before* the `ptr` and `goto` flags, if any.
474/// * `pull $temp as $ty: $var <= $expr` - Attempts to retrieve the `user` field from the context and
475/// downcast it to `$ty`, early returning an error if it fails, and assigns it to the temporary variable `$temp`.
476/// The `$expr` is executed and its value stored in a local variable `$val`.
477/// This is useful for reading data from the context so that it is later available to other attributes.
478/// This flag is applied *before* `push`
479/// * `push $temp as $ty: $expr` - Attempts to retrieve the `user` field from the context and
480/// downcast it to `$ty`, early returning an error if it fails, and assigns it to the temporary variable `$temp`.
481/// The `$expr` is executed and its value ignored.
482/// This is useful for writing data to the context.
483/// * `seeking` - This is a `seek` flag. Does nothing, but simply forces a seeking impl to be used.
484/// This can only be applied to the whole item, as it doesn't make sense on individual fields.
485/// <br>
486/// ### Example:
487///
488/// ```rust
489/// # use std::borrow::Cow;
490/// # use ender::{Encode, Decode};
491/// # use uuid::Uuid;
492/// /// Hehe >:3
493/// extern crate ender as enderman;
494///
495/// #[derive(Encode, Decode)]
496/// /// We specify the name of the re-exported ender crate.
497/// #[ender(crate: enderman)]
498/// /// We specify this should use a seeking impl
499/// /// This is redundant of course, but we include it for completeness :P
500/// #[ender(seeking)]
501/// struct PersonEntry<'record> {
502/// /// Will come in handy later
503/// name_present: bool,
504/// /// Similar to the previous example, but with the addition of the flatten flag!
505/// /// We know a Uuid is always 16 bytes long, so we omit writing/reading that data.
506/// #[ender(serde; flatten size: 16)]
507/// uuid: Uuid,
508/// /// Just the string version of the uuid, not present in the binary data.
509/// /// Skip the Encoding step, and Decode it from the uuid.
510/// #[ender(skip; default: uuid.to_string())]
511/// uuid_string: String,
512/// /// We know whether this is present from the context, therefore we don't write whether
513/// /// the optional value is present, and when reading we assume it is.
514/// /// Since the "if" flag is also present, the field will only be decoded if the expression
515/// /// evaluates to true, making the previous operation safe
516/// /// (no risk of decoding garbage data)
517/// #[ender(flatten bool: true; if: * name_present)]
518/// name: Option<String>,
519/// /// Contains a file offset to the rest of the data
520/// pointer_to_data: usize,
521/// /// Go to the location in the specified file offset from this point onwards.
522/// ///
523/// /// This might be too long to clone from the decoder, so we borrow it instead.
524/// /// Decode impl -> Cow::Owned -- (NOT YET - WILL WORK WHEN SPECIALIZATION IS STABILIZED)
525/// /// BorrowDecode impl -> Cow::Borrowed
526/// /// The macro will infer the borrow lifetime to be `'record`.
527/// #[ender(goto start: *pointer_to_data; borrow)]
528/// criminal_record: Cow<'record, str>,
529/// /// Only present if the name is also present, but we want to provide a custom default!
530/// #[ender(default: String::from("Smith"); if: * name_present)]
531/// surname: String,
532/// /// No-one allowed before 18!
533/// #[ender(validate: * age >= 18, "User is too young: {}", age)]
534/// age: u32,
535/// /// This is temporary data, we don't care about including it in the binary format.
536/// #[ender(skip; default: 100)]
537/// health: u64,
538/// }
539/// ```
540/// # Relationship between seek flags
541///
542/// ```
543/// # use ender::{Decode, Encode};
544/// #[derive(Encode, Decode)]
545/// # #[ender(crate: ender)]
546/// /// This is the same...
547/// struct Ptr {
548/// pointer: usize,
549/// #[ender(ptr start: *pointer)]
550/// data: /* ... */
551/// # (),
552/// }
553///
554/// #[derive(Encode, Decode)]
555/// # #[ender(crate: ender)]
556/// /// As this!
557/// struct Goto {
558/// pointer: usize,
559/// #[ender(pos_tracker: current)]
560/// #[ender(goto start: *pointer)]
561/// data: /* ... */
562/// # (),
563/// #[ender(goto start: current)]
564/// seek_back: (),
565/// }
566/// ```
567#[cfg(feature = "derive")]
568#[cfg_attr(feature = "unstable", doc(cfg(feature = "derive")))]
569pub use ender_derive::{Decode, Encode};
570pub use error::*;
571pub use opaque::*;
572pub use convenience::*;
573
574use crate::io::{BorrowRead, Read, Seek, SeekFrom, SizeLimit, SizeTrack, Write, Zero};
575
576#[cfg(test)]
577mod test;
578
579mod error;
580pub mod facade;
581mod impls;
582pub mod io;
583mod opaque;
584#[cfg(feature = "serde")]
585mod serde;
586mod source;
587mod windows1252;
588mod convenience;
589
590/// Controls the endianness of a numerical value. Endianness is just
591/// the order in which the value's bytes are written.
592#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug, Default, Display)]
593pub enum Endianness {
594 /// Least significant byte first
595 LittleEndian,
596 /// Most significant byte first
597 #[default]
598 BigEndian,
599}
600
601impl Endianness {
602 /// Returns the native endianness for the target system.
603 #[inline]
604 pub const fn native() -> Self {
605 #[cfg(target_endian = "little")]
606 {
607 Self::LittleEndian
608 }
609 #[cfg(target_endian = "big")]
610 {
611 Self::BigEndian
612 }
613 }
614}
615
616/// Controls the encoding of a numerical value. For instance, controls whether the numbers
617/// are compressed through a var-int format or if the entire length of their value is encoded.
618#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug, Default, Display)]
619#[non_exhaustive]
620pub enum NumEncoding {
621 /// The value's bits are encoded as-is according to the [`Endianness`].
622 #[default]
623 Fixed,
624 /// The value's bits are encoded according to the [ULEB128](https://en.wikipedia.org/wiki/LEB128#Unsigned_LEB128)
625 /// (Little Endian Base 128) standard if unsigned, or [LEB128](https://en.wikipedia.org/wiki/LEB128#Signed_LEB128)
626 /// standard if signed.<br>As the name suggests, the bytes are encoded in little endian order,
627 /// ignoring the [`Endianness`].
628 Leb128,
629 /// The value's bits are encoded according to
630 /// [Protobuf's varint encoding](https://protobuf.dev/programming-guides/encoding/),
631 /// where unsigned values are encoded in the same way as [Leb128][`NumEncoding::Leb128`],
632 /// and signed values are encoded as a reinterpret-cast of the bits to unsigned,
633 /// possibly wasting all the var-int length to encode the leading 1s.<br>
634 /// This encoding method is not ideal to encode negative numbers and is provided merely for
635 /// compatibility concerns.<br>
636 /// The bytes are encoded in little endian order, ignoring the [`Endianness`].
637 ProtobufWasteful,
638 /// The value's bits are encoded according to
639 /// [Protobuf's varint encoding](https://protobuf.dev/programming-guides/encoding/),
640 /// where unsigned values are encoded in the same way as [Leb128][`NumEncoding::Leb128`],
641 /// and signed values are encoded as an unsigned value with its least significant bit
642 /// carrying the sign.<br>
643 /// The bytes are encoded in little endian order, ignoring the [`Endianness`].
644 ProtobufZigzag,
645}
646
647impl NumEncoding {
648 /// Determines whether a slice encoded with this encoding can be directly borrowed.
649 ///
650 /// Currently only returns true with the [`Fixed`][`NumEncoding::Fixed`] variant
651 #[inline]
652 pub const fn borrowable(&self) -> bool {
653 match self {
654 NumEncoding::Fixed => true,
655 _ => false,
656 }
657 }
658}
659
660/// How many bits a size or enum variant will occupy in the binary format. If the value
661/// contains more bits, they will be trimmed (lost), so change this value with care
662#[derive(Copy, Clone, Eq, PartialEq, PartialOrd, Ord, Hash, Debug, Default, Display)]
663pub enum BitWidth {
664 /// Max 8 bits per value
665 #[display("8Bit")]
666 Bit8,
667 /// Max 16 bits per value
668 #[display("16Bit")]
669 Bit16,
670 /// Max 32 bits per value
671 #[display("32Bit")]
672 Bit32,
673 /// Max 64 bits per value
674 #[display("64Bit")]
675 #[default]
676 Bit64,
677 /// Max 128 bits per value
678 #[display("128Bit")]
679 Bit128,
680}
681
682impl BitWidth {
683 /// Returns the native bit-width of the [`usize`] and [`isize`] types for the target system.
684 ///
685 /// [`usize`]: prim@usize
686 /// [`isize`]: prim@isize
687 #[inline]
688 pub const fn native() -> Self {
689 #[cfg(target_pointer_width = "64")]
690 {
691 Self::Bit64
692 }
693 #[cfg(target_pointer_width = "32")]
694 {
695 Self::Bit32
696 }
697 #[cfg(target_pointer_width = "16")]
698 {
699 Self::Bit16
700 }
701 }
702
703 /// Returns the number of bits represented by this bit-width.
704 ///
705 /// # Example
706 ///
707 /// ```rust
708 /// use ender::BitWidth;
709 /// let sixteen = BitWidth::Bit16;
710 ///
711 /// assert_eq!(sixteen.bits(), 16);
712 /// ```
713 #[inline]
714 pub const fn bits(&self) -> usize {
715 match self {
716 BitWidth::Bit8 => 8,
717 BitWidth::Bit16 => 16,
718 BitWidth::Bit32 => 32,
719 BitWidth::Bit64 => 64,
720 BitWidth::Bit128 => 128,
721 }
722 }
723
724 /// Returns the number of bytes represented by this bit-width.
725 ///
726 /// # Example
727 ///
728 /// ```rust
729 /// use ender::BitWidth;
730 /// let eight_bits = BitWidth::Bit8;
731 /// let thirtytwo_bits = BitWidth::Bit32;
732 ///
733 /// assert_eq!(eight_bits.bytes(), 1);
734 /// assert_eq!(thirtytwo_bits.bytes(), 4);
735 /// ```
736 #[inline]
737 pub const fn bytes(&self) -> usize {
738 match self {
739 BitWidth::Bit8 => 1,
740 BitWidth::Bit16 => 2,
741 BitWidth::Bit32 => 4,
742 BitWidth::Bit64 => 8,
743 BitWidth::Bit128 => 16,
744 }
745 }
746}
747
748/// The encoding method use for the length of a string.
749#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug, Default, Display)]
750pub enum StrLen {
751 /// The length of the string is stored before its contents as an `usize`.
752 #[default]
753 LengthPrefixed,
754 /// The length of the string is obtained by finding the first occurrence of `n`
755 /// number of null bytes, where `n` is the length in bytes of one code unit for
756 /// the given string encoding (see [`StrEncoding::bytes`]).
757 NullTerminated,
758 /// Like [`StrLen::NullTerminated`], but the string always occupies `n` bytes,
759 /// where the last bytes are filled with null-bytes if the length of the string after
760 /// being encoded is less than `n` bytes.
761 #[display("NullTerminatedFixed({0})")]
762 NullTerminatedFixed(usize),
763}
764
765/// The encoding method used for strings and chars.
766#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug, Default, Display)]
767#[non_exhaustive]
768pub enum StrEncoding {
769 Ascii,
770 /// See [UTF-8](https://en.wikipedia.org/wiki/UTF-8)
771 #[default]
772 Utf8,
773 /// See [UTF-16](https://en.wikipedia.org/wiki/UTF-16)
774 Utf16,
775 /// See [UTF-32](https://en.wikipedia.org/wiki/UTF-32)
776 Utf32,
777 Windows1252,
778}
779
780impl StrEncoding {
781 /// Returns the number of bytes of each **code unit** for this encoding.
782 #[inline]
783 pub const fn bytes(&self) -> usize {
784 match self {
785 StrEncoding::Ascii => 1,
786 StrEncoding::Utf8 => 1,
787 StrEncoding::Utf16 => 2,
788 StrEncoding::Utf32 => 4,
789 StrEncoding::Windows1252 => 1,
790 }
791 }
792}
793
794/// Controls the binary representation of numbers (different from sizes and enum variants).
795/// Specifically, controls the [`Endianness`] and [`NumEncoding`].
796#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug, Display)]
797#[display("endianness = {endianness}, encoding = {num_encoding}")]
798pub struct NumRepr {
799 pub endianness: Endianness,
800 pub num_encoding: NumEncoding,
801}
802
803impl NumRepr {
804 /// Returns the default numerical representation: little endian with fixed encoding
805 #[inline]
806 pub const fn new() -> Self {
807 Self {
808 endianness: Endianness::LittleEndian,
809 num_encoding: NumEncoding::Fixed,
810 }
811 }
812
813 /// Sets the **endianness**, then returns self.
814 #[inline]
815 pub const fn endianness(mut self, endiannes: Endianness) -> Self {
816 self.endianness = endiannes;
817 self
818 }
819
820 /// Sets the **numerical encoding**, then returns self.
821 #[inline]
822 pub const fn num_encoding(mut self, num_encoding: NumEncoding) -> Self {
823 self.num_encoding = num_encoding;
824 self
825 }
826}
827
828impl Default for NumRepr {
829 #[inline]
830 fn default() -> Self {
831 Self::new()
832 }
833}
834
835/// Controls the binary representation of sizes.
836/// Specifically, controls the [`Endianness`], the [`NumEncoding`], the [`BitWidth`],
837/// and the greatest encodable/decodable size before an error is thrown
838#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug, Display)]
839#[display("endianness = {endianness} , encoding = {num_encoding}, bit_width = {width}, max_size = {max_size}")]
840pub struct SizeRepr {
841 pub endianness: Endianness,
842 pub num_encoding: NumEncoding,
843 pub width: BitWidth,
844 pub max_size: usize,
845}
846
847impl SizeRepr {
848 /// Returns the default size representation: little endian, fixed encoding, 64 bit width,
849 /// and the max size set to `usize::MAX`
850 #[inline]
851 pub const fn new() -> Self {
852 Self {
853 endianness: Endianness::LittleEndian,
854 num_encoding: NumEncoding::Fixed,
855 width: BitWidth::Bit64,
856 max_size: usize::MAX,
857 }
858 }
859
860 /// Sets the **endianness**, then returns self.
861 #[inline]
862 pub const fn endianness(mut self, endiannes: Endianness) -> Self {
863 self.endianness = endiannes;
864 self
865 }
866
867 /// Sets the **numerical encoding**, then returns self.
868 #[inline]
869 pub const fn num_encoding(mut self, num_encoding: NumEncoding) -> Self {
870 self.num_encoding = num_encoding;
871 self
872 }
873
874 /// Sets the **bit width**, then returns self.
875 #[inline]
876 pub const fn bit_width(mut self, bit_width: BitWidth) -> Self {
877 self.width = bit_width;
878 self
879 }
880
881 /// Sets the **max size**, then returns self.
882 #[inline]
883 pub const fn max_size(mut self, max_size: usize) -> Self {
884 self.max_size = max_size;
885 self
886 }
887}
888
889impl Default for SizeRepr {
890 #[inline]
891 fn default() -> Self {
892 Self::new()
893 }
894}
895
896/// Controls the binary representation of enum variants.
897/// Specifically, controls the [`Endianness`], the [`NumEncoding`], and the [`BitWidth`].
898#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug, Display)]
899#[display("endianness = {endianness} , encoding = {num_encoding}, bit_width = {width}")]
900pub struct VariantRepr {
901 pub endianness: Endianness,
902 pub num_encoding: NumEncoding,
903 pub width: BitWidth,
904}
905
906impl VariantRepr {
907 /// Returns the default variant representation: little endian, fixed encoding and 32 bit width
908 #[inline]
909 pub const fn new() -> Self {
910 Self {
911 endianness: Endianness::LittleEndian,
912 num_encoding: NumEncoding::Fixed,
913 width: BitWidth::Bit32,
914 }
915 }
916
917 /// Sets the **endianness**, then returns self.
918 #[inline]
919 pub const fn endianness(mut self, endiannes: Endianness) -> Self {
920 self.endianness = endiannes;
921 self
922 }
923
924 /// Sets the **numerical encoding**, then returns self.
925 #[inline]
926 pub const fn num_encoding(mut self, num_encoding: NumEncoding) -> Self {
927 self.num_encoding = num_encoding;
928 self
929 }
930
931 /// Sets the **bit width**, then returns self.
932 #[inline]
933 pub const fn bit_width(mut self, bit_width: BitWidth) -> Self {
934 self.width = bit_width;
935 self
936 }
937}
938
939impl Default for VariantRepr {
940 #[inline]
941 fn default() -> Self {
942 Self::new()
943 }
944}
945
946/// Controls the binary representation of strings.
947/// Specifically, controls the [`StrEncoding`] of strings and chars and the [`Endianness`]
948/// in which the encoded bytes are ordered.
949///
950/// Keep in mind not all encodings support null terminated strings, because
951/// the encoding format may have the capability to contain nulls.<br>
952/// In such cases, the encoding process will produce an error in case the encoded string contains
953/// null characters, and the end of the string is encoded as a sequence of nulls of the appropriate
954/// length (1 byte for UTF-8 and ASCII, 2 bytes for UTF-16, 4 bytes for UTF-32)
955#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug, Display)]
956#[display("encoding = {encoding}, endianness = {endianness}, len = {len}")]
957pub struct StringRepr {
958 pub encoding: StrEncoding,
959 pub endianness: Endianness,
960 pub len: StrLen,
961}
962
963impl StringRepr {
964 /// Returns the default string representation: utf-8, length-prefixed, little_endian
965 #[inline]
966 pub const fn new() -> Self {
967 Self {
968 encoding: StrEncoding::Utf8,
969 endianness: Endianness::LittleEndian,
970 len: StrLen::LengthPrefixed,
971 }
972 }
973
974 /// Sets the **string encoding**, then returns self.
975 #[inline]
976 pub const fn str_encoding(mut self, str_encoding: StrEncoding) -> Self {
977 self.encoding = str_encoding;
978 self
979 }
980
981 /// Sets the **endianness**, then returns self.
982 #[inline]
983 pub const fn endianness(mut self, endiannes: Endianness) -> Self {
984 self.endianness = endiannes;
985 self
986 }
987
988 /// Sets the **string length encoding**, then returns self.
989 #[inline]
990 pub const fn len_encoding(mut self, len_encoding: StrLen) -> Self {
991 self.len = len_encoding;
992 self
993 }
994}
995
996impl Default for StringRepr {
997 #[inline]
998 fn default() -> Self {
999 Self::new()
1000 }
1001}
1002
1003/// An aggregation of [`NumRepr`], [`SizeRepr`], [`VariantRepr`], [`StringRepr`]
1004#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug, Display)]
1005#[display("num_repr = ({num_repr}), size_repr = ({size_repr}), variant_repr = ({variant_repr}), string_repr = ({string_repr})")]
1006pub struct BinSettings {
1007 pub num_repr: NumRepr,
1008 pub size_repr: SizeRepr,
1009 pub variant_repr: VariantRepr,
1010 pub string_repr: StringRepr,
1011}
1012
1013impl BinSettings {
1014 /// Returns the default options containing the default for each representation.
1015 /// See: [`NumRepr::new`], [`SizeRepr::new`], [`VariantRepr::new`], [`StringRepr::new`]
1016 #[inline]
1017 pub const fn new() -> Self {
1018 Self {
1019 num_repr: NumRepr::new(),
1020 size_repr: SizeRepr::new(),
1021 variant_repr: VariantRepr::new(),
1022 string_repr: StringRepr::new(),
1023 }
1024 }
1025
1026 /// Sets the **number** representation settings, then returns self.
1027 #[inline]
1028 pub const fn num_repr(mut self, num_repr: NumRepr) -> Self {
1029 self.num_repr = num_repr;
1030 self
1031 }
1032
1033 /// Sets the **size** representation settings, then returns self.
1034 #[inline]
1035 pub const fn size_repr(mut self, size_repr: SizeRepr) -> Self {
1036 self.size_repr = size_repr;
1037 self
1038 }
1039
1040 /// Sets the **variant** representation settings, then returns self.
1041 #[inline]
1042 pub const fn variant_repr(mut self, variant_repr: VariantRepr) -> Self {
1043 self.variant_repr = variant_repr;
1044 self
1045 }
1046
1047 /// Sets the **string** representation settings, then returns self.
1048 #[inline]
1049 pub const fn string_repr(mut self, string_repr: StringRepr) -> Self {
1050 self.string_repr = string_repr;
1051 self
1052 }
1053}
1054
1055impl Default for BinSettings {
1056 #[inline]
1057 fn default() -> Self {
1058 Self::new()
1059 }
1060}
1061
1062/// The state of the encoder, including its options and a `flatten` state variable
1063#[derive(Copy, Clone, Debug, Default)]
1064#[non_exhaustive]
1065pub struct Context<'a> {
1066 /// User provided data. This can be purposed for storing any kind of data,
1067 /// like cryptographic keys that are unknown to the data structures but known
1068 /// at a higher level.
1069 pub user: Option<&'a dyn Any>,
1070 /// The actual settings, which determine the numerical representations and the string
1071 /// representations.
1072 ///
1073 /// Implementations of [`Encode`] and [`Decode`] are required to
1074 /// preserve the state of the settings, even though they are allowed to temporarily modify it.
1075 ///
1076 /// In case of an error occurring, no guarantee is made about the state of the settings:
1077 /// for this reason it's good practice to store a copy of the settings somewhere.
1078 pub settings: BinSettings,
1079 /// The `bool` flatten state variable.
1080 ///
1081 /// When present, for `Option`, `Result` and any `bool` it indicates,
1082 /// while **Encoding** not to write the value,
1083 /// and while **Decoding** it contains the boolean value itself
1084 /// (it won't be read from the stream).
1085 pub bool_flatten: Option<bool>,
1086 /// The Variant flatten state variable.
1087 ///
1088 /// When present, for any enum it indicates,
1089 /// while **Encoding** not to write the value of the discriminant,
1090 /// and while **Decoding** it contains the discriminant value itself
1091 /// (it won't be read from the stream).
1092 pub variant_flatten: Option<Opaque>,
1093 /// The `usize` flatten state variable.
1094 ///
1095 /// When present, for `Vec`, `HashMap` and other data
1096 /// structures with a length it indicates while **Encoding** not to write said length,
1097 /// and while **Decoding** it contains the length itself
1098 /// (it won't be read from the stream).
1099 pub size_flatten: Option<usize>,
1100}
1101
1102impl<'a> Context<'a> {
1103 /// Constructs the default encoder state. Options will be set to default, flatten to None.
1104 #[inline]
1105 pub const fn new() -> Self {
1106 Self {
1107 user: None,
1108 settings: BinSettings::new(),
1109 bool_flatten: None,
1110 variant_flatten: None,
1111 size_flatten: None,
1112 }
1113 }
1114
1115 /// Replaces the settings with `settings`, then returns self.
1116 #[inline]
1117 pub const fn settings(mut self, settings: BinSettings) -> Self {
1118 self.settings = settings;
1119 self
1120 }
1121
1122 /// Replaces the user data with `data`, then returns self.
1123 #[inline]
1124 pub const fn user_data<'b>(self, data: &'b dyn Any) -> Context<'b> {
1125 let this = Context {
1126 user: Some(data),
1127 settings: self.settings,
1128 bool_flatten: self.bool_flatten,
1129 variant_flatten: self.variant_flatten,
1130 size_flatten: self.size_flatten,
1131 };
1132 this
1133 }
1134
1135 /// Replaces the bool flatten state variable with `Some(value)`, then returns self.
1136 #[inline]
1137 pub const fn bool_flatten(mut self, value: bool) -> Self {
1138 self.bool_flatten = Some(value);
1139 self
1140 }
1141
1142 /// Replaces the variant flatten state variable with `Some(value)`, then returns self.
1143 ///
1144 /// **Beware of providing an [`Opaque`] with an integer literal without a specific type!**
1145 ///
1146 /// By default, rust will infer `i32` as the type, thus it will be converted to a *Signed*
1147 /// enum variant value, and you will get a (bad) surprise when you try to then encode/decode
1148 /// an enum that uses *Unsigned* variant discriminants (most enums).
1149 ///
1150 /// How to avoid this?
1151 /// - Write the type in the num literal E.G. `Opaque::from(3u32)` or `Opaque::from(3 as u32)`
1152 /// - Better yet, use an explicit opaque value ([`Opaque::signed`], [`Opaque::unsigned`])
1153 #[inline]
1154 pub const fn variant_flatten(mut self, value: Opaque) -> Self
1155 {
1156 self.variant_flatten = Some(value);
1157 self
1158 }
1159
1160 /// Replaces the size flatten state variable with `Some(value)`, then returns self.
1161 #[inline]
1162 pub const fn size_flatten(mut self, value: usize) -> Self {
1163 self.size_flatten = Some(value);
1164 self
1165 }
1166
1167 /// Just like [`Self::new`] but uses the given settings instead of the default.
1168 #[inline]
1169 pub fn with_settings(settings: BinSettings) -> Self {
1170 Self {
1171 user: None,
1172 settings,
1173 bool_flatten: None,
1174 variant_flatten: None,
1175 size_flatten: None,
1176 }
1177 }
1178
1179 /// Just like [`Self::new`] but uses the given settings instead of the default
1180 /// and the given user data.
1181 #[inline]
1182 pub fn with_user_data(settings: BinSettings, data: &'a dyn Any) -> Self {
1183 Self {
1184 user: Some(data),
1185 settings,
1186 bool_flatten: None,
1187 variant_flatten: None,
1188 size_flatten: None,
1189 }
1190 }
1191
1192 /// Resets the context to its defaults, then overwrites the options with the given options.
1193 #[inline]
1194 pub fn reset(&mut self, options: BinSettings) {
1195 self.settings = options;
1196 self.bool_flatten = None;
1197 self.variant_flatten = None;
1198 self.size_flatten = None;
1199 }
1200
1201 /// Returns the state of the [`bool`] flatten variable, consuming it.
1202 #[inline]
1203 pub fn consume_bool_flatten(&mut self) -> Option<bool> {
1204 replace(&mut self.bool_flatten, None)
1205 }
1206
1207 /// Returns the state of the Variant flatten variable, consuming it.
1208 #[inline]
1209 pub fn consume_variant_flatten(&mut self) -> Option<Opaque> {
1210 replace(&mut self.variant_flatten, None)
1211 }
1212
1213 /// Returns the state of the [`usize`] flatten variable, consuming it.
1214 #[inline]
1215 pub fn consume_size_flatten(&mut self) -> Option<usize> {
1216 replace(&mut self.size_flatten, None)
1217 }
1218}
1219
1220/// The base type for encoding/decoding. Wraps a stream, and a [`Context`].<br>
1221/// It's recommended to wrap the stream in a [`std::io::BufReader`] or [`std::io::BufWriter`],
1222/// because many small write and read calls will be made.
1223#[derive(Clone)]
1224#[non_exhaustive]
1225pub struct Encoder<'a, T> {
1226 /// The underlying stream
1227 pub stream: T,
1228 /// The state
1229 pub ctxt: Context<'a>,
1230 /// The stack
1231 #[cfg(feature = "debug")]
1232 pub stack: source::Stack,
1233}
1234
1235macro_rules! debug_fn {
1236 ($fn_name:ident, $variant_name:ident ( $ty:ty )) => {
1237 #[inline]
1238 pub fn $fn_name<F, R>(&mut self, f: F, s: $ty) -> EncodingResult<R>
1239 where
1240 F: FnOnce(&mut Encoder<T>) -> EncodingResult<R>,
1241 {
1242 #[cfg(feature = "debug")]
1243 {
1244 #[cfg(feature = "alloc")]
1245 {
1246 self.stack.frames.push(source::Frame::$variant_name(s));
1247 let r = f(self)?;
1248 self.stack.frames.pop();
1249 Ok(r)
1250 }
1251 #[cfg(not(feature = "alloc"))]
1252 {
1253 let last_frame = self.stack.last_frame;
1254 self.stack.last_frame = source::Frame::$variant_name(s);
1255 let r = f(self)?;
1256 self.stack.last_frame = last_frame;
1257 Ok(r)
1258 }
1259 }
1260 #[cfg(not(feature = "debug"))]
1261 {
1262 let _ = s;
1263 f(self)
1264 }
1265 }
1266 };
1267}
1268
1269impl<'a, T> Encoder<'a, T> {
1270 /// Wraps the given stream and state.
1271 #[inline]
1272 pub fn new(stream: T, ctxt: Context<'a>) -> Self {
1273 Self {
1274 stream,
1275 ctxt,
1276 #[cfg(feature = "debug")]
1277 stack: source::Stack::new(),
1278 }
1279 }
1280
1281 /// Replaces the underlying stream with the new one, returning the previous value
1282 #[inline]
1283 pub fn swap_stream(&mut self, new: T) -> T {
1284 replace(&mut self.stream, new)
1285 }
1286
1287 /// Retrieves the user data and attempts to cast it to the given concrete type,
1288 /// returning a validation error in case the types don't match or no user data is stored.
1289 #[inline]
1290 pub fn user_data<U: Any>(&self) -> EncodingResult<&U> {
1291 self.ctxt
1292 .user
1293 .ok_or(val_error!("User-data requested, but none is present"))
1294 .and_then(|x| {
1295 x.downcast_ref().ok_or(val_error!(
1296 "User-data doesnt match the requested concrete type of {}",
1297 core::any::type_name::<U>()
1298 ))
1299 })
1300 }
1301
1302 debug_fn!(with_item, Item(&'static str));
1303 debug_fn!(with_variant, Variant(&'static str));
1304 debug_fn!(with_field, Field(&'static str));
1305 debug_fn!(with_index, Index(usize));
1306}
1307
1308impl<T: Write> Encoder<'_, T> {
1309 /// Method for convenience.
1310 ///
1311 /// Encodes a value using `self` as the encoder.
1312 ///
1313 /// This method is not magic - it is literally defined as `value.encode(self)`
1314 #[inline]
1315 pub fn encode_value<V: Encode<T>>(&mut self, value: V) -> EncodingResult<()> {
1316 value.encode(self)
1317 }
1318}
1319
1320impl<T: Read> Encoder<'_, T> {
1321 /// Method for convenience.
1322 ///
1323 /// Decodes a value using `self` as the decoder.
1324 ///
1325 /// This method is not magic - it is literally defined as `V::decode(self)`
1326 #[inline]
1327 pub fn decode_value<V: Decode<T>>(&mut self) -> EncodingResult<V> {
1328 V::decode(self)
1329 }
1330}
1331
1332impl<'a, T> Encoder<'a, T> {
1333 #[inline]
1334 pub fn finish(self) -> (T, Context<'a>) {
1335 (self.stream, self.ctxt)
1336 }
1337}
1338
1339macro_rules! make_write_fns {
1340 (
1341 type $uty:ty {
1342 pub u_write: $u_write:ident,
1343 pub u_write_direct: $u_write_direct:ident,
1344 priv uleb128_encode: $uleb128_encode:ident
1345 $(,)?
1346 },
1347 type $ity:ty {
1348 pub i_write: $i_write:ident,
1349 pub i_write_direct: $i_write_direct:ident,
1350 priv leb128_encode: $leb128_encode:ident
1351 $(,)?
1352 }$(,)?
1353 ) => {
1354 #[doc = "Encodes a `"]
1355 #[doc = stringify!($uty)]
1356 #[doc = "` to the underlying stream using ULEB-128 encoding"]
1357 #[inline]
1358 fn $uleb128_encode(&mut self, value: $uty) -> EncodingResult<()> {
1359 let mut shifted = value;
1360 let mut more = true;
1361 while more {
1362 let mut byte: u8 = shifted as u8 & 0b01111111;
1363 shifted >>= 7;
1364
1365 // Is the next shifted value worth writing?
1366 if shifted != 0 {
1367 byte |= 0b10000000;
1368 } else {
1369 more = false;
1370 }
1371 self.write_byte(byte)?;
1372 }
1373 Ok(())
1374 }
1375
1376 #[doc = "Encodes a `"]
1377 #[doc = stringify!($uty)]
1378 #[doc = "` to the underlying stream, according to the endianness and numerical encoding in the encoder's state"]
1379 #[inline]
1380 pub fn $u_write(&mut self, value: $uty) -> EncodingResult<()> {
1381 self.$u_write_direct(value, self.ctxt.settings.num_repr.num_encoding, self.ctxt.settings.num_repr.endianness)
1382 }
1383
1384 #[doc = "Encodes a `"]
1385 #[doc = stringify!($uty)]
1386 #[doc = "` to the underlying stream, according to the endianness and numerical passed as parameters"]
1387 #[inline]
1388 pub fn $u_write_direct(&mut self, value: $uty, num_encoding: NumEncoding, endianness: Endianness) -> EncodingResult<()> {
1389 match num_encoding {
1390 NumEncoding::Fixed => {
1391 let bytes: [u8; core::mem::size_of::<$uty>()] = match endianness {
1392 Endianness::BigEndian => value.to_be_bytes(),
1393 Endianness::LittleEndian => value.to_le_bytes()
1394 };
1395 self.stream.write(&bytes)?;
1396 },
1397 NumEncoding::Leb128 | NumEncoding::ProtobufWasteful | NumEncoding::ProtobufZigzag => {
1398 self.$uleb128_encode(value)?;
1399 }
1400 }
1401 Ok(())
1402 }
1403
1404 #[doc = "Encodes a `"]
1405 #[doc = stringify!($ity)]
1406 #[doc = "` to the underlying stream using LEB-128 encoding"]
1407 #[inline]
1408 fn $leb128_encode(&mut self, value: $ity) -> EncodingResult<()> {
1409 let mut shifted = value;
1410 let mut more = true;
1411 while more {
1412 let mut byte = shifted as u8 & 0b0111_1111;
1413 shifted >>= 7;
1414
1415 // Is the next shifted value worth writing?
1416 let neg = (byte & 0b0100_0000) != 0;
1417 if (neg && shifted != -1) || (!neg && shifted != 0) {
1418 byte |= 0b1000_0000;
1419 } else {
1420 more = false;
1421 }
1422 self.write_byte(byte)?;
1423 }
1424 Ok(())
1425 }
1426
1427 #[doc = "Encodes a `"]
1428 #[doc = stringify!($ity)]
1429 #[doc = "` to the underlying stream, according to the endianness and numerical encoding in the encoder's state"]
1430 #[inline]
1431 pub fn $i_write(&mut self, value: $ity) -> EncodingResult<()> {
1432 self.$i_write_direct(value, self.ctxt.settings.num_repr.num_encoding, self.ctxt.settings.num_repr.endianness)
1433 }
1434
1435 #[doc = "Encodes a `"]
1436 #[doc = stringify!($ity)]
1437 #[doc = "` to the underlying stream, according to the endianness and numerical encoding passed as parameters"]
1438 #[inline]
1439 pub fn $i_write_direct(&mut self, value: $ity, num_encoding: NumEncoding, endianness: Endianness) -> EncodingResult<()> {
1440 match num_encoding {
1441 NumEncoding::Fixed => {
1442 let bytes: [u8; core::mem::size_of::<$ity>()] = match endianness {
1443 Endianness::BigEndian => value.to_be_bytes(),
1444 Endianness::LittleEndian => value.to_le_bytes()
1445 };
1446 self.stream.write(&bytes)?;
1447 },
1448 NumEncoding::Leb128 => {
1449 self.$leb128_encode(value)?;
1450 },
1451 NumEncoding::ProtobufWasteful => {
1452 let unsigned = <$uty>::from_ne_bytes(value.to_ne_bytes());
1453 self.$uleb128_encode(unsigned)?;
1454 }
1455 NumEncoding::ProtobufZigzag => {
1456 let shifted = (value << 1) ^ (value >> (<$ity>::BITS - 1));
1457 let unsigned = <$uty>::from_ne_bytes(shifted.to_ne_bytes());
1458 self.$uleb128_encode(unsigned)?;
1459 }
1460 }
1461 Ok(())
1462 }
1463 };
1464}
1465
1466impl<T: Write> Encoder<'_, T> {
1467 make_write_fns! {
1468 type u8 {
1469 pub u_write: write_u8,
1470 pub u_write_direct: write_u8_with,
1471 priv uleb128_encode: uleb128_encode_u8,
1472 },
1473 type i8 {
1474 pub i_write: write_i8,
1475 pub i_write_direct: write_i8_with,
1476 priv leb128_encode: leb128_encode_i8,
1477 },
1478 }
1479 make_write_fns! {
1480 type u16 {
1481 pub u_write: write_u16,
1482 pub u_write_direct: write_u16_with,
1483 priv uleb128_encode: uleb128_encode_u16,
1484 },
1485 type i16 {
1486 pub i_write: write_i16,
1487 pub i_write_direct: write_i16_with,
1488 priv leb128_encode: leb128_encode_i16,
1489 },
1490 }
1491 make_write_fns! {
1492 type u32 {
1493 pub u_write: write_u32,
1494 pub u_write_direct: write_u32_with,
1495 priv uleb128_encode: uleb128_encode_u32,
1496 },
1497 type i32 {
1498 pub i_write: write_i32,
1499 pub i_write_direct: write_i32_with,
1500 priv leb128_encode: leb128_encode_i32,
1501 },
1502 }
1503 make_write_fns! {
1504 type u64 {
1505 pub u_write: write_u64,
1506 pub u_write_direct: write_u64_with,
1507 priv uleb128_encode: uleb128_encode_u64,
1508 },
1509 type i64 {
1510 pub i_write: write_i64,
1511 pub i_write_direct: write_i64_with,
1512 priv leb128_encode: leb128_encode_i64,
1513 },
1514 }
1515 make_write_fns! {
1516 type u128 {
1517 pub u_write: write_u128,
1518 pub u_write_direct: write_u128_with,
1519 priv uleb128_encode: uleb128_encode_u128,
1520 },
1521 type i128 {
1522 pub i_write: write_i128,
1523 pub i_write_direct: write_i128_with,
1524 priv leb128_encode: leb128_encode_i128,
1525 },
1526 }
1527
1528 /// Encodes an `usize`.
1529 ///
1530 /// If the size flatten variable is set to `Some`,
1531 /// this function checks that the value matches but then returns
1532 /// immediately without writing, otherwise it will encode the given `usize`
1533 /// to the underlying stream according to the endianness, numerical
1534 /// encoding and bit-width in the encoder's state, with an additional
1535 /// check that the value does not exceed the max size.
1536 #[inline]
1537 pub fn write_usize(&mut self, value: usize) -> EncodingResult<()> {
1538 if let Some(size) = self.ctxt.consume_size_flatten() {
1539 if size != value {
1540 return Err(EncodingError::FlattenError(FlattenError::LenMismatch {
1541 expected: size,
1542 got: value,
1543 }));
1544 }
1545 Ok(())
1546 } else {
1547 if value > self.ctxt.settings.size_repr.max_size {
1548 return Err(EncodingError::MaxSizeExceeded {
1549 max: self.ctxt.settings.size_repr.max_size,
1550 requested: value,
1551 });
1552 }
1553 let encoding = self.ctxt.settings.size_repr.num_encoding;
1554 let endianness = self.ctxt.settings.size_repr.endianness;
1555
1556 // `Opaque` already converts conversion errors to `EncodingError`
1557 let opaque = Opaque::from(value);
1558
1559 match self.ctxt.settings.size_repr.width {
1560 BitWidth::Bit8 => self.write_u8_with(opaque.try_into()?, encoding, endianness),
1561 BitWidth::Bit16 => self.write_u16_with(opaque.try_into()?, encoding, endianness),
1562 BitWidth::Bit32 => self.write_u32_with(opaque.try_into()?, encoding, endianness),
1563 BitWidth::Bit64 => self.write_u64_with(opaque.try_into()?, encoding, endianness),
1564 BitWidth::Bit128 => self.write_u128_with(opaque.try_into()?, encoding, endianness),
1565 }
1566 }
1567 }
1568
1569 /// Encodes a `isize` to the underlying stream, according to the endianness,
1570 /// numerical encoding and bit-width in the encoder's state.
1571 #[inline]
1572 pub fn write_isize(&mut self, value: isize) -> EncodingResult<()> {
1573 let encoding = self.ctxt.settings.size_repr.num_encoding;
1574 let endianness = self.ctxt.settings.size_repr.endianness;
1575
1576 // `Opaque` already converts conversion errors to `EncodingError`
1577 let opaque = Opaque::from(value);
1578
1579 match self.ctxt.settings.size_repr.width {
1580 BitWidth::Bit8 => self.write_i8_with(opaque.try_into()?, encoding, endianness),
1581 BitWidth::Bit16 => self.write_i16_with(opaque.try_into()?, encoding, endianness),
1582 BitWidth::Bit32 => self.write_i32_with(opaque.try_into()?, encoding, endianness),
1583 BitWidth::Bit64 => self.write_i64_with(opaque.try_into()?, encoding, endianness),
1584 BitWidth::Bit128 => self.write_i128_with(opaque.try_into()?, encoding, endianness),
1585 }
1586 }
1587
1588 /// Encodes an unsigned `Variant`.
1589 ///
1590 /// If the `Variant` flatten variable is set to `Some`,
1591 /// this function checks that the value matches but then returns
1592 /// immediately without writing, otherwise it will encode the given `Variant`
1593 /// to the underlying stream according to the endianness, numerical
1594 /// encoding and bit-width in the encoder's state.
1595 #[inline]
1596 #[allow(private_bounds)]
1597 pub fn write_uvariant<V>(&mut self, value: V) -> EncodingResult<()>
1598 where
1599 Opaque: From<V>,
1600 V: Sign<Sign = Unsigned>,
1601 {
1602 let value = Opaque::from(value);
1603 if let Some(variant) = self.ctxt.consume_variant_flatten() {
1604 if value != variant {
1605 return Err(FlattenError::VariantMismatch {
1606 expected: variant,
1607 got: value,
1608 }
1609 .into());
1610 }
1611 Ok(())
1612 } else {
1613 let width = self.ctxt.settings.variant_repr.width;
1614 let encoding = self.ctxt.settings.variant_repr.num_encoding;
1615 let endianness = self.ctxt.settings.variant_repr.endianness;
1616 match width {
1617 BitWidth::Bit8 => self.write_u8_with(value.try_into()?, encoding, endianness),
1618 BitWidth::Bit16 => self.write_u16_with(value.try_into()?, encoding, endianness),
1619 BitWidth::Bit32 => self.write_u32_with(value.try_into()?, encoding, endianness),
1620 BitWidth::Bit64 => self.write_u64_with(value.try_into()?, encoding, endianness),
1621 BitWidth::Bit128 => self.write_u128_with(value.try_into()?, encoding, endianness),
1622 }
1623 }
1624 }
1625
1626 /// Encodes a signed `Variant`.
1627 ///
1628 /// If the `Variant` flatten variable is set to `Some`,
1629 /// this function checks that the value matches but then returns
1630 /// immediately without writing, otherwise it will encode the given `Variant`
1631 /// to the underlying stream according to the endianness, numerical
1632 /// encoding and bit-width in the encoder's state.
1633 #[inline]
1634 #[allow(private_bounds)]
1635 pub fn write_ivariant<V>(&mut self, value: V) -> EncodingResult<()>
1636 where
1637 Opaque: From<V>,
1638 V: Sign<Sign = Signed>,
1639 {
1640 let value = Opaque::from(value);
1641 if let Some(variant) = self.ctxt.consume_variant_flatten() {
1642 if value != variant {
1643 return Err(FlattenError::VariantMismatch {
1644 expected: variant,
1645 got: value,
1646 }
1647 .into());
1648 }
1649 Ok(())
1650 } else {
1651 let width = self.ctxt.settings.variant_repr.width;
1652 let encoding = self.ctxt.settings.variant_repr.num_encoding;
1653 let endianness = self.ctxt.settings.variant_repr.endianness;
1654 match width {
1655 BitWidth::Bit8 => self.write_i8_with(value.try_into()?, encoding, endianness),
1656 BitWidth::Bit16 => self.write_i16_with(value.try_into()?, encoding, endianness),
1657 BitWidth::Bit32 => self.write_i32_with(value.try_into()?, encoding, endianness),
1658 BitWidth::Bit64 => self.write_i64_with(value.try_into()?, encoding, endianness),
1659 BitWidth::Bit128 => self.write_i128_with(value.try_into()?, encoding, endianness),
1660 }
1661 }
1662 }
1663
1664 /// Encodes a boolean value.
1665 ///
1666 /// It is guaranteed that, if `value` is `true`, a single u8 will be written to the
1667 /// underlying stream with the value `1`, and if `value` is `false`, with a value of `0`.
1668 ///
1669 /// If the `bool` flatten variable is set to `Some`,
1670 /// this function checks that the value matches but then returns
1671 /// immediately without writing, otherwise it will encode the given `bool`
1672 /// as described above.
1673 #[inline]
1674 pub fn write_bool(&mut self, value: bool) -> EncodingResult<()> {
1675 if let Some(boolean) = self.ctxt.consume_bool_flatten() {
1676 if boolean != value {
1677 return Err(FlattenError::BoolMismatch {
1678 expected: boolean,
1679 got: value,
1680 }
1681 .into());
1682 }
1683 Ok(())
1684 } else {
1685 self.write_byte(if value { 1 } else { 0 })
1686 }
1687 }
1688
1689 /// Encodes a `char` to the underlying stream, according to the endianness and string encoding
1690 /// in the encoder's state.
1691 #[inline]
1692 pub fn write_char(&mut self, value: char) -> EncodingResult<()> {
1693 self.write_char_with(
1694 value,
1695 self.ctxt.settings.string_repr.encoding,
1696 self.ctxt.settings.string_repr.endianness
1697 )
1698 }
1699
1700 /// Encodes a `char` to the underlying stream, according to the endianness and string encoding
1701 /// passed as parameters.
1702 #[inline]
1703 pub fn write_char_with(&mut self, value: char, encoding: StrEncoding, endianness: Endianness) -> EncodingResult<()> {
1704 match encoding {
1705 StrEncoding::Ascii => {
1706 if !value.is_ascii() {
1707 return Err(StringError::InvalidChar.into());
1708 }
1709
1710 self.write_byte(value as u8)?;
1711 }
1712 StrEncoding::Utf8 => {
1713 let mut buf = [0u8; 4];
1714 let len = value.encode_utf8(&mut buf).len();
1715
1716 self.write_bytes(&buf[..len])?;
1717 }
1718 StrEncoding::Utf16 => {
1719 let mut buf = [0u16; 2];
1720 let len = value.encode_utf16(&mut buf).len();
1721
1722 for block in buf[..len].iter() {
1723 self.write_u16_with(*block, NumEncoding::Fixed, endianness)?;
1724 }
1725 }
1726 StrEncoding::Utf32 => {
1727 self.write_u32_with(value as u32, NumEncoding::Fixed, endianness)?;
1728 }
1729 StrEncoding::Windows1252 => {
1730 let encoded = windows1252::dec_to_enc(value);
1731 if let Some(encoded) = encoded {
1732 self.write_byte(encoded)?;
1733 } else {
1734 return Err(StringError::InvalidChar.into());
1735 }
1736 }
1737 }
1738 Ok(())
1739 }
1740
1741 /// Encodes a `f32` to the underlying stream, ignoring the numeric encoding but respecting
1742 /// the endianness. Equivalent of `Self::write_u32(value.to_bits())` with the numeric
1743 /// encoding set to Fixed
1744 #[inline]
1745 pub fn write_f32(&mut self, value: f32) -> EncodingResult<()> {
1746 self.write_u32_with(
1747 value.to_bits(),
1748 NumEncoding::Fixed,
1749 self.ctxt.settings.num_repr.endianness,
1750 )
1751 }
1752
1753 /// Encodes a `f64` to the underlying stream, ignoring the numeric encoding but respecting
1754 /// the endianness. Equivalent of `Self::write_u64(value.to_bits())` with the numeric
1755 /// encoding set to Fixed
1756 #[inline]
1757 pub fn write_f64(&mut self, value: f64) -> EncodingResult<()> {
1758 self.write_u64_with(
1759 value.to_bits(),
1760 NumEncoding::Fixed,
1761 self.ctxt.settings.num_repr.endianness,
1762 )
1763 }
1764
1765 /// Encodes a string to the underlying stream, according to the endianness,
1766 /// string encoding and string-length encoding in the encoder's state.
1767 /// Anything whose chars can be iterated over is considered a string.
1768 ///
1769 /// # Example
1770 ///
1771 /// ```
1772 /// # use ender::{Context, Encoder};
1773 /// # use ender::io::Zero;
1774 ///
1775 /// let mut encoder = Encoder::new(Zero, Context::new());
1776 /// encoder.write_str("Hello, world!".chars()).unwrap();
1777 /// ```
1778 #[inline]
1779 pub fn write_str<S>(&mut self, string: S) -> EncodingResult<()>
1780 where
1781 S: IntoIterator<Item = char, IntoIter: Clone>,
1782 {
1783 self.write_str_with(
1784 string,
1785 self.ctxt.settings.string_repr.encoding,
1786 self.ctxt.settings.string_repr.endianness,
1787 self.ctxt.settings.string_repr.len
1788 )
1789 }
1790
1791 /// Encodes a string to the underlying stream, according to the endianness,
1792 /// string encoding and string-length encoding passed as parameters.
1793 /// Anything whose chars can be iterated over is considered a string.
1794 ///
1795 /// # Example
1796 ///
1797 /// ```
1798 /// # use ender::{Context, Encoder, Endianness, StrEncoding, StrLen};
1799 /// # use ender::io::Zero;
1800 ///
1801 /// let mut encoder = Encoder::new(Zero, Context::new());
1802 /// encoder.write_str_with(
1803 /// "Goodbye, world :(".chars(),
1804 /// StrEncoding::Utf16,
1805 /// Endianness::BigEndian,
1806 /// StrLen::NullTerminated
1807 /// ).unwrap();
1808 /// ```
1809 pub fn write_str_with<S>(&mut self, string: S, encoding: StrEncoding, endianness: Endianness, len_encoding: StrLen) -> EncodingResult<()>
1810 where
1811 S: IntoIterator<Item = char, IntoIter: Clone>,
1812 {
1813 let chars = string.into_iter();
1814
1815 match len_encoding {
1816 StrLen::LengthPrefixed => {
1817 // We don't know the length of the string in advance
1818
1819 // Create a fake encoder that simply keeps track of the length
1820 let mut sz_encoder = Encoder::new(SizeTrack::new(Zero), self.ctxt);
1821 for ch in chars.clone() {
1822 sz_encoder.write_char_with(ch, encoding, endianness)?;
1823 }
1824 let size = sz_encoder.finish().0.size_written();
1825
1826 // Now encode the length and the string data
1827 self.write_usize(size)?;
1828 for ch in chars {
1829 self.write_char_with(ch, encoding, endianness)?;
1830 }
1831 }
1832 StrLen::NullTerminated => {
1833 for ch in chars {
1834 self.write_char_with(ch, encoding, endianness)?;
1835 }
1836 self.write_char_with('\0', encoding, endianness)?;
1837 }
1838 StrLen::NullTerminatedFixed(max) => {
1839 let mut capped = Encoder::new(SizeLimit::new(&mut self.stream, max, 0), self.ctxt);
1840 for ch in chars {
1841 match capped.write_char_with(ch, encoding, endianness) {
1842 Err(EncodingError::UnexpectedEnd) => {
1843 Err(EncodingError::StringError(StringError::TooLong))
1844 }
1845 any => any,
1846 }?;
1847 }
1848
1849 // Fill the rest with zeroes
1850 for _ in 0..capped.stream.remaining_writable() {
1851 self.write_byte(0)?;
1852 }
1853 }
1854 }
1855
1856 Ok(())
1857 }
1858
1859 /// Writes a single byte to the underlying stream as-is.
1860 #[inline]
1861 pub fn write_byte(&mut self, byte: u8) -> EncodingResult<()> {
1862 self.stream.write(&[byte])
1863 }
1864
1865 /// Writes the given slice to the underlying stream as-is.
1866 #[inline]
1867 pub fn write_bytes(&mut self, bytes: &[u8]) -> EncodingResult<()> {
1868 self.stream.write(bytes)
1869 }
1870}
1871
1872macro_rules! make_read_fns {
1873 (
1874 type $uty:ty {
1875 pub u_read: $u_read:ident,
1876 pub u_read_direct: $u_read_direct:ident,
1877 priv uleb128_decode: $uleb128_decode:ident
1878 $(,)?
1879 },
1880 type $ity:ty {
1881 pub i_read: $i_read:ident,
1882 pub i_read_direct: $i_read_direct:ident,
1883 priv leb128_decode: $leb128_decode:ident
1884 $(,)?
1885 }
1886 $(,)?
1887 ) => {
1888 #[doc = "Decodes a `"]
1889 #[doc = stringify!($uty)]
1890 #[doc = "` from the underlying stream using ULEB-128 decoding"]
1891 #[inline]
1892 fn $uleb128_decode(&mut self) -> EncodingResult<$uty> {
1893 let mut result: $uty = 0;
1894 let mut shift: u8 = 0;
1895 loop {
1896 if shift >= <$uty>::BITS as u8 {
1897 return Err(EncodingError::VarIntError);
1898 }
1899
1900 let byte = self.read_byte()?;
1901 result |= (byte & 0b0111_1111) as $uty << shift;
1902 shift += 7;
1903
1904 if (byte & 0b1000_0000) == 0 {
1905 break;
1906 }
1907 }
1908 Ok(result)
1909 }
1910
1911 #[doc = "Decodes a `"]
1912 #[doc = stringify!($uty)]
1913 #[doc = "` from the underlying stream, according to the endianness and numerical encoding in the encoder's state"]
1914 #[inline]
1915 pub fn $u_read(&mut self) -> EncodingResult<$uty> {
1916 self.$u_read_direct(self.ctxt.settings.num_repr.num_encoding, self.ctxt.settings.num_repr.endianness)
1917 }
1918
1919 #[doc = "Decodes a `"]
1920 #[doc = stringify!($uty)]
1921 #[doc = "` from the underlying stream, according to the endianness and numerical passed as parameters"]
1922 #[inline]
1923 pub fn $u_read_direct(&mut self, num_encoding: NumEncoding, endianness: Endianness) -> EncodingResult<$uty> {
1924 Ok(match num_encoding {
1925 NumEncoding::Fixed => {
1926 let mut bytes: [u8; core::mem::size_of::<$uty>()] = [0u8; core::mem::size_of::<$uty>()];
1927 self.stream.read(&mut bytes)?;
1928
1929 match endianness {
1930 Endianness::BigEndian => <$uty>::from_be_bytes(bytes),
1931 Endianness::LittleEndian => <$uty>::from_le_bytes(bytes)
1932 }
1933 }
1934 NumEncoding::Leb128 | NumEncoding::ProtobufWasteful | NumEncoding::ProtobufZigzag => {
1935 self.$uleb128_decode()?
1936 }
1937 })
1938 }
1939
1940 #[doc = "Decodes a `"]
1941 #[doc = stringify!($ity)]
1942 #[doc = "` from the underlying stream using LEB-128 decoding"]
1943 #[inline]
1944 fn $leb128_decode(&mut self) -> EncodingResult<$ity> {
1945 let mut result: $ity = 0;
1946 let mut byte;
1947 let mut shift: u8 = 0;
1948 loop {
1949 if shift >= <$ity>::BITS as u8 {
1950 return Err(EncodingError::VarIntError);
1951 }
1952
1953 byte = self.read_byte()?;
1954 result |= (byte & 0b0111_1111) as $ity << shift;
1955 shift += 7;
1956
1957 if (byte & 0b1000_0000) == 0 {
1958 break;
1959 }
1960 }
1961
1962 if shift < <$ity>::BITS as u8 && (byte & 0b0100_0000) != 0 {
1963 result |= (!0 << shift);
1964 }
1965
1966 Ok(result)
1967 }
1968
1969 #[doc = "Decodes a `"]
1970 #[doc = stringify!($ity)]
1971 #[doc = "` from the underlying stream, according to the endianness and numerical encoding in the encoder's context"]
1972 #[inline]
1973 pub fn $i_read(&mut self) -> EncodingResult<$ity> {
1974 self.$i_read_direct(self.ctxt.settings.num_repr.num_encoding, self.ctxt.settings.num_repr.endianness)
1975 }
1976
1977 #[doc = "Decodes a `"]
1978 #[doc = stringify!($ity)]
1979 #[doc = "` from the underlying stream, according to the endianness and numerical encoding passed as parameters"]
1980 #[inline]
1981 pub fn $i_read_direct(&mut self, num_encoding: NumEncoding, endianness: Endianness) -> EncodingResult<$ity> {
1982 Ok(match num_encoding {
1983 NumEncoding::Fixed => {
1984 let mut bytes: [u8; core::mem::size_of::<$ity>()] = [0u8; core::mem::size_of::<$ity>()];
1985 self.stream.read(&mut bytes)?;
1986
1987 match endianness {
1988 Endianness::BigEndian => <$ity>::from_be_bytes(bytes),
1989 Endianness::LittleEndian => <$ity>::from_le_bytes(bytes)
1990 }
1991 }
1992 NumEncoding::Leb128 => {
1993 self.$leb128_decode()?
1994 }
1995 NumEncoding::ProtobufWasteful => {
1996 let unsigned = self.$uleb128_decode()?;
1997 <$ity>::from_ne_bytes(unsigned.to_ne_bytes())
1998 }
1999 NumEncoding::ProtobufZigzag => {
2000 let unsigned = self.$uleb128_decode()?;
2001 let neg = (unsigned & 1) != 0;
2002 let transformed = if neg {
2003 !(unsigned >> 1)
2004 } else {
2005 unsigned >> 1
2006 };
2007
2008 <$ity>::from_ne_bytes(transformed.to_ne_bytes())
2009 }
2010 })
2011 }
2012 };
2013}
2014
2015impl<T: Read> Encoder<'_, T> {
2016 make_read_fns! {
2017 type u8 {
2018 pub u_read: read_u8,
2019 pub u_read_direct: read_u8_with,
2020 priv uleb128_decode: uleb128_decode_u8,
2021 },
2022 type i8 {
2023 pub i_read: read_i8,
2024 pub i_read_direct: read_i8_with,
2025 priv leb128_decode: leb128_decode_i8,
2026 },
2027 }
2028 make_read_fns! {
2029 type u16 {
2030 pub u_read: read_u16,
2031 pub u_read_direct: read_u16_with,
2032 priv uleb128_decode: uleb128_decode_u16,
2033 },
2034 type i16 {
2035 pub i_read: read_i16,
2036 pub i_read_direct: read_i16_with,
2037 priv leb128_decode: leb128_decode_i16,
2038 },
2039 }
2040 make_read_fns! {
2041 type u32 {
2042 pub u_read: read_u32,
2043 pub u_read_direct: read_u32_with,
2044 priv uleb128_decode: uleb128_decode_u32,
2045 },
2046 type i32 {
2047 pub i_read: read_i32,
2048 pub i_read_direct: read_i32_with,
2049 priv leb128_decode: leb128_decode_i32,
2050 },
2051 }
2052 make_read_fns! {
2053 type u64 {
2054 pub u_read: read_u64,
2055 pub u_read_direct: read_u64_with,
2056 priv uleb128_decode: uleb128_decode_u64,
2057 },
2058 type i64 {
2059 pub i_read: read_i64,
2060 pub i_read_direct: read_i64_with,
2061 priv leb128_decode: leb128_decode_i64,
2062 },
2063 }
2064 make_read_fns! {
2065 type u128 {
2066 pub u_read: read_u128,
2067 pub u_read_direct: read_u128_with,
2068 priv uleb128_decode: uleb128_decode_u128,
2069 },
2070 type i128 {
2071 pub i_read: read_i128,
2072 pub i_read_direct: read_i128_with,
2073 priv leb128_decode: leb128_decode_i128,
2074 },
2075 }
2076
2077 /// Decodes an `usize`.
2078 ///
2079 /// If the `usize` flatten variable is set to `Some`, this function
2080 /// will return its value without reading, otherwise it will decode an `usize`
2081 /// from the underlying stream, according to the endianness, numerical encoding
2082 /// and bit-width in the encoder's state, with an additional check that the size
2083 /// does not exceed the max size.
2084 #[inline]
2085 pub fn read_usize(&mut self) -> EncodingResult<usize> {
2086 if let Some(size) = self.ctxt.consume_size_flatten() {
2087 Ok(size)
2088 } else {
2089 let encoding = self.ctxt.settings.size_repr.num_encoding;
2090 let endianness = self.ctxt.settings.size_repr.endianness;
2091 let value = match self.ctxt.settings.size_repr.width {
2092 BitWidth::Bit8 => Opaque::from(self.read_u8_with(encoding, endianness)?),
2093 BitWidth::Bit16 => Opaque::from(self.read_u16_with(encoding, endianness)?),
2094 BitWidth::Bit32 => Opaque::from(self.read_u32_with(encoding, endianness)?),
2095 BitWidth::Bit64 => Opaque::from(self.read_u64_with(encoding, endianness)?),
2096 BitWidth::Bit128 => Opaque::from(self.read_u128_with(encoding, endianness)?),
2097 }
2098 .try_into()?;
2099
2100 if value > self.ctxt.settings.size_repr.max_size {
2101 return Err(EncodingError::MaxSizeExceeded {
2102 max: self.ctxt.settings.size_repr.max_size,
2103 requested: value,
2104 });
2105 }
2106 Ok(value)
2107 }
2108 }
2109
2110 /// Decodes a `isize` from the underlying stream, according to the endianness,
2111 /// numerical encoding and bit-width in the encoder's state
2112 #[inline]
2113 pub fn read_isize(&mut self) -> EncodingResult<isize> {
2114 let encoding = self.ctxt.settings.size_repr.num_encoding;
2115 let endianness = self.ctxt.settings.size_repr.endianness;
2116 match self.ctxt.settings.size_repr.width {
2117 BitWidth::Bit8 => Opaque::from(self.read_i8_with(encoding, endianness)?),
2118 BitWidth::Bit16 => Opaque::from(self.read_i16_with(encoding, endianness)?),
2119 BitWidth::Bit32 => Opaque::from(self.read_i32_with(encoding, endianness)?),
2120 BitWidth::Bit64 => Opaque::from(self.read_i64_with(encoding, endianness)?),
2121 BitWidth::Bit128 => Opaque::from(self.read_i128_with(encoding, endianness)?),
2122 }
2123 .try_into()
2124 }
2125
2126 /// Decodes an unsigned `Variant`.
2127 ///
2128 /// If the `Variant` flatten variable is set to `Some`, this function
2129 /// will return its value without reading, otherwise it will decode a `Variant`
2130 /// from the underlying stream, according to the endianness, numerical encoding
2131 /// and bit-width in the encoder's state.
2132 #[inline]
2133 #[allow(private_bounds)]
2134 pub fn read_uvariant<V>(&mut self) -> EncodingResult<V>
2135 where
2136 V: Sign<Sign = Unsigned>,
2137 Opaque: TryInto<V, Error = EncodingError>,
2138 {
2139 if let Some(variant) = self.ctxt.consume_variant_flatten() {
2140 variant.try_into()
2141 } else {
2142 let width = self.ctxt.settings.variant_repr.width;
2143 let encoding = self.ctxt.settings.variant_repr.num_encoding;
2144 let endianness = self.ctxt.settings.variant_repr.endianness;
2145
2146 match width {
2147 BitWidth::Bit8 => Opaque::from(self.read_u8_with(encoding, endianness)?),
2148 BitWidth::Bit16 => Opaque::from(self.read_u16_with(encoding, endianness)?),
2149 BitWidth::Bit32 => Opaque::from(self.read_u32_with(encoding, endianness)?),
2150 BitWidth::Bit64 => Opaque::from(self.read_u64_with(encoding, endianness)?),
2151 BitWidth::Bit128 => Opaque::from(self.read_u128_with(encoding, endianness)?),
2152 }
2153 .try_into()
2154 }
2155 }
2156
2157 /// Decodes a signed `Variant`.
2158 ///
2159 /// If the `Variant` flatten variable is set to `Some`, this function
2160 /// will return its value without reading, otherwise it will decode a `Variant`
2161 /// from the underlying stream, according to the endianness, numerical encoding
2162 /// and bit-width in the encoder's state.
2163 #[inline]
2164 #[allow(private_bounds)]
2165 pub fn read_ivariant<V>(&mut self) -> EncodingResult<V>
2166 where
2167 V: Sign<Sign = Signed>,
2168 Opaque: TryInto<V, Error = EncodingError>,
2169 {
2170 if let Some(variant) = self.ctxt.consume_variant_flatten() {
2171 variant.try_into()
2172 } else {
2173 let width = self.ctxt.settings.variant_repr.width;
2174 let encoding = self.ctxt.settings.variant_repr.num_encoding;
2175 let endianness = self.ctxt.settings.variant_repr.endianness;
2176
2177 match width {
2178 BitWidth::Bit8 => Opaque::from(self.read_u8_with(encoding, endianness)?),
2179 BitWidth::Bit16 => Opaque::from(self.read_i16_with(encoding, endianness)?),
2180 BitWidth::Bit32 => Opaque::from(self.read_i32_with(encoding, endianness)?),
2181 BitWidth::Bit64 => Opaque::from(self.read_i64_with(encoding, endianness)?),
2182 BitWidth::Bit128 => Opaque::from(self.read_i128_with(encoding, endianness)?),
2183 }
2184 .try_into()
2185 }
2186 }
2187
2188 /// Decodes a boolean value.
2189 ///
2190 /// It is guaranteed that, one `u8` is read from the underlying stream and, if
2191 /// it's equal to `1`, `true` is returned, if it's equal to `0`, `false` is returned,
2192 /// for any other value an [`InvalidBool`][`EncodingError::InvalidBool`]
2193 /// error will be returned.
2194 ///
2195 /// If the `bool` flatten variable is set to `Some`,
2196 /// then its value is returned without reading,
2197 /// otherwise the boolean is decoded as described above.
2198 #[inline]
2199 pub fn read_bool(&mut self) -> EncodingResult<bool> {
2200 if let Some(boolean) = self.ctxt.consume_bool_flatten() {
2201 Ok(boolean)
2202 } else {
2203 match self.read_byte()? {
2204 0 => Ok(false),
2205 1 => Ok(true),
2206 _ => Err(EncodingError::InvalidBool),
2207 }
2208 }
2209 }
2210
2211 /// Decodes a `char` from the underlying stream, according to the endianness and string encoding
2212 /// in the encoder's state.
2213 #[inline]
2214 pub fn read_char(&mut self) -> EncodingResult<char> {
2215 self.read_char_with(
2216 self.ctxt.settings.string_repr.encoding,
2217 self.ctxt.settings.string_repr.endianness
2218 )
2219 }
2220
2221 /// Decodes a `char` from the underlying stream, according to the endianness and string encoding
2222 /// passed as parameters.
2223 #[inline]
2224 fn read_char_with(&mut self, encoding: StrEncoding, endianness: Endianness) -> EncodingResult<char> {
2225 match encoding {
2226 StrEncoding::Ascii => {
2227 let ch = self.read_byte()?;
2228 if !ch.is_ascii() {
2229 return Err(StringError::InvalidChar.into());
2230 }
2231 let ch = char::from_u32(ch as u32);
2232
2233 // PANIC SAFETY
2234 //
2235 // We check that the character is ascii before converting it to a char
2236 // and if it is, we return *BEFORE* converting it, so `ch` is ALWAYS
2237 // Some at this point
2238 Ok(ch.unwrap())
2239 }
2240 StrEncoding::Utf8 => {
2241 // See https://en.wikipedia.org/wiki/UTF-8#Encoding
2242 let mut buf = self.read_byte()?;
2243 let (add, rshift) = if buf.leading_ones() == 0 {
2244 (0usize, 1u32)
2245 } else {
2246 let leading = buf.leading_ones();
2247 if leading == 1 || leading > 4 {
2248 // The first byte was either a continuation byte
2249 // or forward declared more than 3 continuation bytes
2250 return Err(StringError::InvalidChar.into());
2251 }
2252 (leading as usize - 1, leading + 1)
2253 };
2254
2255 let mut ch: u32 = ((u8::MAX >> rshift) & buf) as u32;
2256
2257 let mut shift = 0;
2258 for _ in 0..add {
2259 buf = self.read_byte()?;
2260
2261 if buf.leading_ones() != 1 {
2262 // This byte was not a continuation byte, but we expected it to be
2263 return Err(StringError::InvalidChar.into());
2264 }
2265
2266 shift += 6;
2267 ch = (ch << shift) | ((buf & 0b0011_1111) as u32);
2268 }
2269
2270 Ok(char::from_u32(ch).ok_or(
2271 EncodingError::StringError(StringError::InvalidChar),
2272 )?)
2273 }
2274 StrEncoding::Utf16 => {
2275 // See https://en.wikipedia.org/wiki/UTF-16#Code_points_from_U+010000_to_U+10FFFF
2276 let buf = self.read_u16_with(NumEncoding::Fixed, endianness)?;
2277 let ch;
2278
2279 // This is a high surrogate
2280 if 0xD800 <= buf && buf <= 0xDBFF {
2281 let high_surrogate = buf;
2282 let low_surrogate = self.read_u16_with(NumEncoding::Fixed, endianness)?;
2283
2284 if !(0xDC00 <= low_surrogate && low_surrogate <= 0xDFFF) {
2285 // First character was in the high surrogate range,
2286 // but the second character wasn't in the low surrogate range
2287 return Err(StringError::InvalidChar.into());
2288 }
2289
2290 const LOW_TEN_BITS: u16 = 0b0000_0011_1111_1111;
2291
2292 let high_bits = ((high_surrogate - 0xD800) & LOW_TEN_BITS) as u32;
2293 let low_bits = ((low_surrogate - 0xDC00) & LOW_TEN_BITS) as u32;
2294
2295 ch = (high_bits << 10) | low_bits;
2296 } else if 0xDC00 <= buf && buf <= 0xDFFF {
2297 // First character was in the low surrogate range
2298 return Err(StringError::InvalidChar.into());
2299 } else {
2300 ch = buf as u32;
2301 }
2302
2303 Ok(char::from_u32(ch).ok_or(
2304 EncodingError::StringError(StringError::InvalidChar),
2305 )?)
2306 }
2307 StrEncoding::Utf32 => {
2308 let buf = self.read_u32_with(NumEncoding::Fixed, endianness)?;
2309
2310 Ok(char::from_u32(buf).ok_or(
2311 EncodingError::StringError(StringError::InvalidChar),
2312 )?)
2313 }
2314 StrEncoding::Windows1252 => {
2315 let buf = self.read_byte()?;
2316
2317 if let Some(ch) = windows1252::enc_to_dec(buf) {
2318 Ok(ch)
2319 } else {
2320 Err(EncodingError::StringError(StringError::InvalidChar))
2321 }
2322 }
2323 }
2324 }
2325
2326 /// Decodes a `f32` from the underlying stream, ignoring the numeric encoding but respecting
2327 /// the endianness. Equivalent of `f32::from_bits(self.read_u32())` with the numeric
2328 /// encoding set to [`NumEncoding::Fixed`].
2329 #[inline]
2330 pub fn read_f32(&mut self) -> EncodingResult<f32> {
2331 Ok(f32::from_bits(self.read_u32_with(
2332 NumEncoding::Fixed,
2333 self.ctxt.settings.num_repr.endianness,
2334 )?))
2335 }
2336
2337 /// Decodes a `f64` from the underlying stream, ignoring the numeric encoding but respecting
2338 /// the endianness. Equivalent of `f64::from_bits(self.read_u64())` with the numeric
2339 /// encoding set to [`NumEncoding::Fixed`].
2340 #[inline]
2341 pub fn read_f64(&mut self) -> EncodingResult<f64> {
2342 Ok(f64::from_bits(self.read_u64_with(
2343 NumEncoding::Fixed,
2344 self.ctxt.settings.num_repr.endianness,
2345 )?))
2346 }
2347
2348 /// Decodes a String from the underlying stream, according to the endianness,
2349 /// and string encoding in the encoder's state.
2350 #[inline]
2351 pub fn read_str<S>(&mut self) -> EncodingResult<S>
2352 where
2353 S: FromIterator<char>,
2354 {
2355 self.read_str_with(
2356 self.ctxt.settings.string_repr.encoding,
2357 self.ctxt.settings.string_repr.endianness,
2358 self.ctxt.settings.string_repr.len
2359 )
2360 }
2361
2362 /// Decodes a String from the underlying stream, according to the endianness,
2363 /// and string encoding passed as parameters.
2364 #[inline]
2365 pub fn read_str_with<S>(&mut self, encoding: StrEncoding, endianness: Endianness, len_encoding: StrLen) -> EncodingResult<S>
2366 where
2367 S: FromIterator<char>,
2368 {
2369 struct LenPrefixCharIter<'iter, 'user, T: Read> {
2370 encoder: Encoder<'user, SizeLimit<&'iter mut T>>,
2371 encoding: StrEncoding,
2372 endianness: Endianness
2373 }
2374
2375 impl<'iter, 'user, T: Read> Iterator for LenPrefixCharIter<'iter, 'user, T> {
2376 type Item = EncodingResult<char>;
2377 fn next(&mut self) -> Option<Self::Item> {
2378 if self.encoder.stream.remaining_readable() == 0 {
2379 // We expect 0 more bytes
2380 // This means we can end the iterator by returning None
2381 return None;
2382 };
2383
2384 Some(self.encoder.read_char_with(self.encoding, self.endianness))
2385 }
2386 }
2387
2388 struct NullTermCharIter<'iter, 'user, T: Read> {
2389 encoder: &'iter mut Encoder<'user, T>,
2390 encoding: StrEncoding,
2391 endianness: Endianness
2392 }
2393
2394 impl<T: Read> Iterator for NullTermCharIter<'_, '_, T> {
2395 type Item = EncodingResult<char>;
2396 fn next(&mut self) -> Option<Self::Item> {
2397 match self.encoder.read_char_with(self.encoding, self.endianness) {
2398 Ok('\0') => {
2399 // Null character found
2400 None // => STOP!
2401 }
2402 Ok(x) => {
2403 // Just a char
2404 Some(Ok(x)) // ==> Continue
2405 }
2406 Err(x) => {
2407 // An unrelated error occurred
2408 Some(Err(x)) // ==> "Continue" but actually early return an error
2409 }
2410 }
2411 }
2412 }
2413
2414 struct NullTermFixedLengthCharIter<'iter, 'user, T: Read> {
2415 encoder: Encoder<'user, SizeLimit<&'iter mut T>>,
2416 encoding: StrEncoding,
2417 endianness: Endianness
2418 }
2419
2420 impl<T: Read> Iterator for NullTermFixedLengthCharIter<'_, '_, T> {
2421 type Item = EncodingResult<char>;
2422 fn next(&mut self) -> Option<Self::Item> {
2423 if self.encoder.stream.remaining_readable() == 0 {
2424 // We reached the maximum amount of bytes we can read
2425 // Simply end the iterator
2426 return None;
2427 }
2428 match self.encoder.read_char_with(self.encoding, self.endianness) {
2429 Ok('\0') => {
2430 // Null character found
2431 // Read all the remaining nulls
2432 for _ in 0..self.encoder.stream.remaining_readable() {
2433 let z = match self.encoder.read_byte() {
2434 Ok(z) => z,
2435 Err(err) => return Some(Err(err)),
2436 };
2437 if z != 0 {
2438 return Some(Err(EncodingError::StringError(
2439 StringError::MissingNull,
2440 )));
2441 }
2442 }
2443
2444 None // => STOP!
2445 }
2446 Ok(x) => {
2447 // Just a char
2448 Some(Ok(x)) // ==> Continue
2449 }
2450 Err(x) => {
2451 // An unrelated error occurred
2452 Some(Err(x)) // ==> "Continue" but actually early return an error
2453 }
2454 }
2455 }
2456 }
2457
2458 match len_encoding {
2459 StrLen::LengthPrefixed => {
2460 let length = self.read_usize()?;
2461 let iter = LenPrefixCharIter {
2462 encoder: Encoder::new(SizeLimit::new(&mut self.stream, 0, length), self.ctxt),
2463 encoding,
2464 endianness
2465 };
2466
2467 iter.collect()
2468 }
2469 StrLen::NullTerminated => {
2470 let iter = NullTermCharIter {
2471 encoder: self,
2472 encoding,
2473 endianness
2474 };
2475 iter.collect()
2476 }
2477 StrLen::NullTerminatedFixed(max) => {
2478 let iter = NullTermFixedLengthCharIter {
2479 encoder: Encoder::new(SizeLimit::new(&mut self.stream, 0, max), self.ctxt),
2480 encoding,
2481 endianness
2482 };
2483 iter.collect()
2484 }
2485 }
2486 }
2487
2488 /// Reads a single byte from the stream.
2489 #[inline]
2490 pub fn read_byte(&mut self) -> EncodingResult<u8> {
2491 let mut buf = [0u8; 1];
2492 self.stream.read(&mut buf)?;
2493 Ok(buf[0])
2494 }
2495
2496 /// Reads `buf.len()` bytes from the stream to the buffer as-is.
2497 #[inline]
2498 pub fn read_bytes(&mut self, buf: &mut [u8]) -> EncodingResult<()> {
2499 self.stream.read(buf)
2500 }
2501}
2502
2503macro_rules! make_borrow_slice_fn {
2504 ($name:ident -> $ty:ty) => {
2505 #[doc = "Borrows a `"]
2506 #[doc = stringify!($ty)]
2507 #[doc = "` slice of `length` length from the encoder, checking"]
2508 #[doc = "that the [`Endianness`] and alignment match those of the system"]
2509 #[doc = "and that the [`NumEncoding`] is [`borrowable`][`NumEncoding::borrowable`]"]
2510 #[inline]
2511 pub fn $name(
2512 &mut self,
2513 length: usize,
2514 num_encoding: NumEncoding,
2515 endianness: Endianness,
2516 ) -> EncodingResult<&'data [$ty]> {
2517 // Assert the num encoding is borrowable
2518 if !num_encoding.borrowable() {
2519 return Err(EncodingError::BorrowError(
2520 BorrowError::NonBorrowableNumEncoding { num_encoding },
2521 ));
2522 }
2523
2524 // Assert the endianness matches, else we would be borrowing garbage-looking data.
2525 if endianness != Endianness::native() {
2526 return Err(EncodingError::BorrowError(
2527 BorrowError::EndiannessMismatch {
2528 found: endianness,
2529 system: Endianness::native(),
2530 },
2531 ));
2532 }
2533
2534 const BYTES: usize = core::mem::size_of::<$ty>();
2535
2536 let u8_slice: &[u8] = self.stream.borrow_read(length * BYTES)?;
2537
2538 // Depending on the alignment of the target system, this might fail.
2539 let conv: &[$ty] = bytemuck::try_cast_slice(u8_slice)
2540 .map_err(|_| EncodingError::BorrowError(BorrowError::AlignmentMismatch))?;
2541 Ok(conv)
2542 }
2543 };
2544}
2545
2546impl<'data, T: BorrowRead<'data>> Encoder<'_, T> {
2547 /// Returns a reference to `len` bytes in the stream, without advancing it.
2548 ///
2549 /// This forwards the call to [`BorrowRead::peek`], meaning multiple calls
2550 /// produce the same output.
2551 ///
2552 /// # Example
2553 ///
2554 /// ```
2555 /// use ender::{Context, Encoder};
2556 /// use ender::io::Slice;
2557 ///
2558 /// let slice = [0, 7, 15, 42, 2];
2559 /// let encoder = Encoder::new(Slice::new(&slice), Context::new());
2560 ///
2561 /// let first_peek = encoder.peek_bytes(3).unwrap();
2562 /// let second_peek = encoder.peek_bytes(3).unwrap();
2563 ///
2564 /// assert_eq!(first_peek, second_peek);
2565 /// ```
2566 #[inline]
2567 pub fn peek_bytes(&self, len: usize) -> EncodingResult<&'data [u8]> {
2568 self.stream.peek(len)
2569 }
2570
2571 /// Borrows a `u8` slice of length `length` from the encoder,
2572 /// without performing any additional checks.
2573 #[inline]
2574 pub fn borrow_byte_slice(&mut self, len: usize) -> EncodingResult<&'data [u8]> {
2575 self.stream.borrow_read(len)
2576 }
2577
2578 /// Borrows a `u8` slice of length `length` from the encoder,
2579 /// checking that the [`NumEncoding`] is [`borrowable`][`NumEncoding::borrowable`].
2580 #[inline]
2581 pub fn borrow_u8_slice(
2582 &mut self,
2583 len: usize,
2584 num_encoding: NumEncoding,
2585 ) -> EncodingResult<&'data [u8]> {
2586 // Assert the num encoding is borrowable
2587 if !num_encoding.borrowable() {
2588 return Err(EncodingError::BorrowError(
2589 BorrowError::NonBorrowableNumEncoding { num_encoding },
2590 ));
2591 }
2592
2593 self.stream.borrow_read(len)
2594 }
2595
2596 make_borrow_slice_fn!(borrow_u16_slice -> u16);
2597 make_borrow_slice_fn!(borrow_u32_slice -> u32);
2598 make_borrow_slice_fn!(borrow_u64_slice -> u64);
2599 make_borrow_slice_fn!(borrow_u128_slice -> u128);
2600
2601 /// Borrows a `u8` slice of length `length` from the encoder,
2602 /// checking that the [`NumEncoding`] is [`borrowable`][`NumEncoding::borrowable`].
2603 #[inline]
2604 pub fn borrow_i8_slice(
2605 &mut self,
2606 len: usize,
2607 num_encoding: NumEncoding,
2608 ) -> EncodingResult<&'data [i8]> {
2609 // Assert the num encoding is borrowable
2610 if !num_encoding.borrowable() {
2611 return Err(EncodingError::BorrowError(
2612 BorrowError::NonBorrowableNumEncoding { num_encoding },
2613 ));
2614 }
2615
2616 let u8_slice: &[u8] = self.stream.borrow_read(len)?;
2617 Ok(bytemuck::try_cast_slice(u8_slice).map_err(|_| BorrowError::AlignmentMismatch)?)
2618 }
2619
2620 make_borrow_slice_fn!(borrow_i16_slice -> i16);
2621 make_borrow_slice_fn!(borrow_i32_slice -> i32);
2622 make_borrow_slice_fn!(borrow_i64_slice -> i64);
2623 make_borrow_slice_fn!(borrow_i128_slice -> i128);
2624
2625 make_borrow_slice_fn!(borrow_f32_slice -> f32);
2626 make_borrow_slice_fn!(borrow_f64_slice -> f64);
2627
2628 /// Borrows a `usize` slice of length `length` from the encoder.
2629 ///
2630 /// Checks that the [`Endianness`] and [`BitWidth`] match those of the target system,
2631 /// and that the [`NumEncoding`] is [`borrowable`][`NumEncoding::borrowable`]
2632 #[inline]
2633 pub fn borrow_usize_slice(
2634 &mut self,
2635 len: usize,
2636 num_encoding: NumEncoding,
2637 endianness: Endianness,
2638 bit_width: BitWidth,
2639 ) -> EncodingResult<&'data [usize]> {
2640 // Assert the num encoding is borrowable
2641 if !num_encoding.borrowable() {
2642 return Err(EncodingError::BorrowError(
2643 BorrowError::NonBorrowableNumEncoding { num_encoding },
2644 ));
2645 }
2646
2647 // If the system endianness doesn't match, we would be borrowing
2648 // garbage-looking data
2649 if endianness != Endianness::native() {
2650 return Err(EncodingError::BorrowError(
2651 BorrowError::EndiannessMismatch {
2652 found: endianness,
2653 system: Endianness::native(),
2654 },
2655 ));
2656 }
2657
2658 // Again, if the system bit width doesn't match, we would be borrowing a different
2659 // number of bytes than what the user expects
2660 if bit_width != BitWidth::native() {
2661 return Err(EncodingError::BorrowError(BorrowError::BitWidthMismatch {
2662 found: bit_width,
2663 system: BitWidth::native(),
2664 }));
2665 }
2666
2667 let u8_slice = self.stream.borrow_read(bit_width.bytes() * len)?;
2668
2669 // Depending on the alignment of the target system, this might fail.
2670 let conv: &[usize] = bytemuck::try_cast_slice(u8_slice)
2671 .map_err(|_| EncodingError::BorrowError(BorrowError::AlignmentMismatch))?;
2672
2673 // Check that none of the elements exceed the max size
2674 for &elem in conv {
2675 let max = self.ctxt.settings.size_repr.max_size;
2676 if elem > max {
2677 return Err(EncodingError::MaxSizeExceeded {
2678 requested: elem,
2679 max,
2680 });
2681 }
2682 }
2683
2684 Ok(conv)
2685 }
2686
2687 /// Borrows a `isize` slice of length `length` from the encoder.
2688 ///
2689 /// Checks that the [`Endianness`] and [`BitWidth`] match those of the target system,
2690 /// and that the [`NumEncoding`] is [`borrowable`][`NumEncoding::borrowable`]
2691 #[inline]
2692 pub fn borrow_isize_slice(
2693 &mut self,
2694 len: usize,
2695 num_encoding: NumEncoding,
2696 endianness: Endianness,
2697 bit_width: BitWidth,
2698 ) -> EncodingResult<&'data [isize]> {
2699 // Assert the num encoding is borrowable
2700 if !num_encoding.borrowable() {
2701 return Err(EncodingError::BorrowError(
2702 BorrowError::NonBorrowableNumEncoding { num_encoding },
2703 ));
2704 }
2705
2706 // If the system endianness doesn't match, we would be borrowing
2707 // garbage-looking data
2708 if endianness != Endianness::native() {
2709 return Err(EncodingError::BorrowError(
2710 BorrowError::EndiannessMismatch {
2711 found: endianness,
2712 system: Endianness::native(),
2713 },
2714 ));
2715 }
2716
2717 // Again, if the system bit width doesn't match, we would be borrowing a different
2718 // number of bytes than what the user expects
2719 if bit_width != BitWidth::native() {
2720 return Err(EncodingError::BorrowError(BorrowError::BitWidthMismatch {
2721 found: bit_width,
2722 system: BitWidth::native(),
2723 }));
2724 }
2725
2726 let u8_slice = self.stream.borrow_read(bit_width.bytes() * len)?;
2727
2728 // Depending on the alignment of the target system, this might fail.
2729 let conv: &[isize] = bytemuck::try_cast_slice(u8_slice)
2730 .map_err(|_| EncodingError::BorrowError(BorrowError::AlignmentMismatch))?;
2731 Ok(conv)
2732 }
2733}
2734
2735impl<T: Seek> Encoder<'_, T> {
2736 /// Returns the current stream position as a byte offset from the start.
2737 #[inline]
2738 pub fn stream_position(&mut self) -> EncodingResult<usize> {
2739 self.stream.seek(SeekFrom::POSITION)
2740 }
2741
2742 /// Performs a seek operation on the underlying stream using the given `seek`
2743 /// argument.
2744 #[inline]
2745 pub fn seek(&mut self, seek: SeekFrom) -> EncodingResult<usize> {
2746 self.stream.seek(seek)
2747 }
2748
2749 /// Performs a seek operation on the underlying stream using the given `seek`
2750 /// argument, calls the closure, then seeks back to the original position.
2751 // Notice the `StreamModifier` signature
2752 #[inline]
2753 pub fn with_seek<F, R>(&mut self, f: F, seek: SeekFrom) -> EncodingResult<R>
2754 where
2755 F: FnOnce(&mut Encoder<T>) -> EncodingResult<R>,
2756 {
2757 // Track the current position
2758 let prev = self.stream_position()? as isize;
2759
2760 // Magic fn!
2761 let ret = f(self);
2762
2763 // Seek to the desired location, and track the location now
2764 let cur = self.stream.seek(seek)? as isize;
2765 // Find the difference
2766 let diff = prev - cur;
2767
2768 // Now we can seek even on streams that don't support seeking from the Start or End
2769 self.stream.seek(SeekFrom::Current(diff))?;
2770 ret
2771 }
2772}
2773
2774/// A binary data structure specification which can be **encoded** into its binary representation.
2775///
2776/// Implementations that need to **seek** should implement for `W: Write + Seek`.
2777///
2778/// You should keep your implementation as general as possible and avoid
2779/// implementing for a `R = ConcreteType` if possible
2780pub trait Encode<W: Write> {
2781 /// Encodes `self` into its binary format.
2782 ///
2783 /// Calling `encode` multiple times on the same value without
2784 /// changing the encoder settings or the value itself in-between calls should produce
2785 /// the same output.
2786 ///
2787 /// If the result is Ok,
2788 /// implementations should guarantee that the state of the encoder
2789 /// is preserved. If the result is Err,
2790 /// no guarantees are made about the state of the encoder,
2791 /// and users should reset it before reuse.
2792 fn encode(&self, encoder: &mut Encoder<W>) -> EncodingResult<()>;
2793}
2794
2795/// A binary data structure specification which can be **decoded** from its binary representation.
2796///
2797/// Implementations that need to **seek** should implement for `R: Read + Seek`,
2798/// while those that need to **borrow** should implement for `R: BorrowRead<'data>`.
2799///
2800/// If you need both, use `R: BorrowRead<'data> + Seek`
2801///
2802/// You should keep your implementation as general as possible and avoid
2803/// implementing for a `R = ConcreteType` if possible
2804///
2805/// # Note about lifetimes
2806///
2807/// An implementation of this trait where your type uses the same lifetime as the decoder
2808/// (the `'data` lifetime) will greatly limit the possible usages of the implementation.
2809///
2810/// Instead, prefer giving your type a different lifetime and make the `'data` lifetime depend on it.
2811///
2812/// ### Correct:
2813/// ```ignore
2814/// impl<'data: 'a + 'b + ..., 'a, 'b, ...> Decode<BorrowRead<'data>> for Thing<'a, 'b, ...> { ... }
2815/// ```
2816///
2817/// ### Misleading:
2818/// ```ignore
2819/// impl<'data> Decode<BorrowRead<'data>> for Thing<'data, 'data, ...> { ... }
2820/// ```
2821pub trait Decode<R: Read>: Sized {
2822 /// Decodes `Self` from its binary format.
2823 ///
2824 /// Calling `decode` multiple times without changing the
2825 /// encoder settings or the underlying binary data in-between calls should produce
2826 /// the same output.
2827 ///
2828 /// If the result is Ok,
2829 /// implementations should guarantee that the state of the encoder
2830 /// is preserved. If the result is Err,
2831 /// no guarantees are made about the state of the encoder,
2832 /// and users should reset it before reuse.
2833 fn decode(decoder: &mut Encoder<R>) -> EncodingResult<Self>;
2834}