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}