Skip to main content

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