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}