musli/help/derives.rs
1//! Deriving [`Encode`] and [`Decode`].
2//!
3//! The [`Encode`] and [`Decode`] derives allows for automatically implementing
4//! [`Encode`] and [`Decode`].
5//!
6//! They come with a number of options for customizing their implementation,
7//! detailed below. But first we need to talk about *modes*.
8//!
9//! <br>
10//!
11//! #### Modes
12//!
13//! If you've paid close attention to the [`Encode`] and [`Decode`] traits you
14//! might notive that they have an extra parameter called `M`. This stands for
15//! "mode".
16//!
17//! This parameter allows us to have different implementations of these traits
18//! for the same type.
19//!
20//! By default we implements two modes, which each have subtly different default
21//! behaviors:
22//! * [`Binary`] - which uses indexed fields, the equivalent of
23//! `#[musli(name_type = usize)]`.
24//! * [`Text`] - which uses literally text fields by their name, the equivalent
25//! of `#[musli(name_type = str)]`.
26//!
27//! When it comes to deriving these traits you can scope attributes to apply to
28//! any mode including custom local ones. This is done using the `#[musli(mode =
29//! ..)]` meta attribute like this:
30//!
31//! ```
32//! use musli::{Encode, Decode};
33//! use musli::mode::Binary;
34//! use musli::json::Encoding;
35//!
36//! #[derive(Encode, Decode)]
37//! struct Person<'a> {
38//! #[musli(mode = Text, name = "name")]
39//! not_name: &'a str,
40//! age: u32,
41//! }
42//!
43//! const TEXT: Encoding = Encoding::new();
44//! const BINARY: Encoding<Binary> = Encoding::new().with_mode();
45//!
46//! let named = TEXT.to_vec(&Person { not_name: "Aristotle", age: 61 })?;
47//! assert_eq!(named.as_slice(), br#"{"name":"Aristotle","age":61}"#);
48//!
49//! let indexed = BINARY.to_vec(&Person { not_name: "Plato", age: 84 })?;
50//! assert_eq!(indexed.as_slice(), br#"{"0":"Plato","1":84}"#);
51//! # Ok::<_, musli::json::Error>(())
52//! ```
53//!
54//! So the `#[musli(mode)]` atttribute is supported in any position. And any of
55//! its sibling attributes will be added to the given *alternative* mode, rather
56//! the [default mode].
57//!
58//! <br>
59//!
60//! #### Attributes
61//!
62//! * [*Meta attributes*](#meta-attributes) which apply to the attribute itself.
63//! It is used to filter what scope the current attribute applies to, such as
64//! only applying to an `Encode` derive using `#[musli(encode_only, ..)]` or a
65//! specific mode such as `#[musli(mode = Json, ..)]`.
66//!
67//! * [*Container attributes*](#container-attributes) are attributes which apply
68//! to the `struct` or `enum`.
69//!
70//! * [*Variant attributes*](#variant-attributes) are attributes which apply to
71//! each individual variant in an `enum`.
72//!
73//! * [*Field attributes*](#field-attributes) are attributes which apply to each
74//! individual field either in a `struct` or an `enum` variant.
75//!
76//! <br>
77//!
78//! ## Meta attributes
79//!
80//! Certain attributes affect which other attributes apply to a given context.
81//! These are called *meta* attributes.
82//!
83//! Meta attributes are applicable to any context, and can be used on
84//! containers, variants, and fields.
85//!
86//! <br>
87//!
88//! #### `#[musli(mode = <path>)]`
89//!
90//! The attributes only apply to the given `mode`.
91//!
92//! The `Person` struct below uses string field names by default when the `Text`
93//! mode is enabled, but we can change this behavior only for that particular
94//! mode like this:
95//!
96//! ```
97//! use musli::{Encode, Decode};
98//! use musli::mode::Text;
99//!
100//! #[derive(Encode, Decode)]
101//! #[musli(mode = Text, name_type = usize)]
102//! struct Person<'a> {
103//! name: &'a str,
104//! age: u32,
105//! }
106//! ```
107//!
108//! <br>
109//!
110//! #### `#[musli(encode_only)]`
111//!
112//! The attributes only apply when implementing the `Encode` trait.
113//!
114//! An example where this is useful is if you want to apply `#[musli(packed)]`
115//! in a different mode, but only for encoding, since decoding packed types is
116//! not supported for enums.
117//!
118//! ```
119//! use musli::mode::Binary;
120//! use musli::{Decode, Encode};
121//!
122//! enum Packed {}
123//!
124//! #[derive(Encode, Decode)]
125//! #[musli(mode = Packed, encode_only, packed)]
126//! enum Name<'a> {
127//! Full(&'a str),
128//! Given(&'a str),
129//! }
130//! ```
131//!
132//! <br>
133//!
134//! #### `#[musli(decode_only)]`
135//!
136//! The attributes only apply when implementing the `Decode` trait.
137//!
138//! ```
139//! use musli::{Decode, Encode};
140//!
141//! #[derive(Encode, Decode)]
142//! #[musli(name_all = "name")]
143//! struct Name<'a> {
144//! sur_name: &'a str,
145//! #[musli(decode_only, name = "last")]
146//! last_name: &'a str,
147//! }
148//! ```
149//!
150//! <br>
151//!
152//! ## Container attributes
153//!
154//! Container attributes apply to the container, such as directly on the
155//! `struct` or `enum`. Like the uses of `#[musli(packed)]` and
156//! `#[musli(name_all = "name")]` here:
157//!
158//! ```
159//! use musli::{Encode, Decode};
160//!
161//! #[derive(Encode, Decode)]
162//! #[musli(packed)]
163//! struct Struct {
164//! /* the body of the struct */
165//! }
166//!
167//! #[derive(Encode, Decode)]
168//! #[musli(name_all = "name")]
169//! enum Enum {
170//! /* the body of the enum */
171//! }
172//! ```
173//!
174//! <br>
175//!
176//! #### `#[musli(name_all = "..")]`
177//!
178//! Allos for renaming every field in the container. It can take any of the
179//! following values:
180//!
181//! * `index` (default) - the index of the field will be used.
182//! * `name` - the literal name of the field will be used.
183//! * `PascalCase` - the field will be converted to pascal case.
184//! * `camelCase` - the field will be converted to camel case.
185//! * `snake_case` - the field will be converted to snake case.
186//! * `SCREAMING_SNAKE_CASE` - the field will be converted to screaming snake case.
187//! * `kebab-case` - the field will be converted to kebab case.
188//! * `SCREAMING-KEBAB-CASE` - the field will be converted to screaming kebab case.
189//!
190//! ```
191//! use musli::{Encode, Decode};
192//!
193//! #[derive(Encode, Decode)]
194//! #[musli(name_all = "PascalCase")]
195//! struct PascalCaseStruct {
196//! field_name: u32,
197//! }
198//!
199//! #[derive(Encode, Decode)]
200//! #[musli(name_all = "name")]
201//! struct NamedStruct {
202//! field1: u32,
203//! field2: u32,
204//! }
205//! ```
206//!
207//! If applied to an enum, it will instead rename all variants:
208//!
209//! ```
210//! use musli::{Encode, Decode};
211//!
212//! #[derive(Encode, Decode)]
213//! #[musli(name_all = "PascalCase")]
214//! enum PascalCaseEnum {
215//! VariantName {
216//! field_name: u32,
217//! }
218//! }
219//!
220//! #[derive(Encode, Decode)]
221//! #[musli(name_all = "name")]
222//! enum NamedEnum {
223//! Variant1 {
224//! field1: u32,
225//! },
226//! Variant2 {
227//! field1: u32,
228//! },
229//! }
230//! ```
231//!
232//! <br>
233//!
234//! #### `#[musli(transparent)]`
235//!
236//! This can only be used on types which have a single field. It will cause that
237//! field to define how that variant is encoded or decoded transparently without
238//! being treated as a field.
239//!
240//! ```
241//! use musli::{Encode, Decode};
242//!
243//! #[derive(Encode)]
244//! #[musli(transparent)]
245//! struct Struct(u32);
246//!
247//! let data = musli::wire::to_vec(&Struct(42))?;
248//! let actual: u32 = musli::wire::from_slice(&data)?;
249//! assert_eq!(actual, 42u32);
250//! # Ok::<_, musli::wire::Error>(())
251//! ```
252//!
253//! <br>
254//!
255//! #### `#[musli(packed)]`
256//!
257//! This attribute will disable all *tagging* and the structure will simply be
258//! encoded with one field following another in the order in which they are
259//! defined.
260//!
261//! A caveat of *packed* structures is that they cannot be safely versioned and
262//! the two systems communicating through them need to be using strictly
263//! synchronized representations.
264//!
265//! This attribute is useful for performing simple decoding over "raw" bytes
266//! when combined with an encoder which does minimal prefixing and packs fields.
267//!
268//! ```
269//! use musli::{Encode, Decode};
270//!
271//! #[derive(Encode)]
272//! #[musli(packed)]
273//! struct Struct {
274//! field1: u32,
275//! field2: u32,
276//! field3: u32,
277//! }
278//!
279//! let data = musli::storage::to_vec(&Struct {
280//! field1: 1,
281//! field2: 2,
282//! field3: 3,
283//! })?;
284//!
285//! assert_eq!(data.as_slice(), [1, 2, 3]);
286//! # Ok::<_, musli::storage::Error>(())
287//! ```
288//!
289//! <br>
290//!
291//! #### `#[musli(name_type = ..)]`
292//!
293//! This indicates which type any contained `#[musli(name = ..)]` attributes
294//! should have. Tags can usually be inferred, but specifying this field ensures
295//! that all tags have a single well-defined type.
296//!
297//! The following values are treated specially:
298//! * `str` applies `#[musli(name_all = "name")]` by default.
299//! * `[u8]` applies `#[musli(name_all = "name")]` by default.
300//!
301//! ```
302//! use core::fmt;
303//!
304//! use musli::{Encode, Decode};
305//!
306//! #[derive(Debug, PartialEq, Eq, Encode, Decode)]
307//! #[musli(transparent)]
308//! struct CustomTag<'a>(&'a [u8]);
309//!
310//! impl fmt::Display for CustomTag<'_> {
311//! fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
312//! fmt::Debug::fmt(self.0, f)
313//! }
314//! }
315//!
316//! #[derive(Encode, Decode)]
317//! #[musli(name_type = CustomTag)]
318//! struct Struct {
319//! #[musli(name = CustomTag(b"name in bytes"))]
320//! name: String,
321//! }
322//!
323//! #[derive(Encode, Decode)]
324//! #[musli(name_type = CustomTag)]
325//! enum EnumWithCustomTag {
326//! #[musli(name = CustomTag(b"variant one"))]
327//! Variant1 {
328//! /* .. */
329//! },
330//! }
331//! ```
332//!
333//! <br>
334//!
335//! #### `#[musli(name_method = ..)]`
336//!
337//! This allows for explicitly setting which method should be used to decode
338//! names. Available options are:
339//!
340//! * `"value"` (default) - the name is decoded as a value.
341//! * `"unsized"` - the name is decoded as an unsized value, this is the default
342//! if for example `#[musli(name_type = str)]` is used.
343//! * `"unsized_bytes"` - the name is decoded as a unsized bytes, this is the
344//! default if for example `#[musli(name_type = [u8])]` is used.
345//!
346//! This can be overrided for values which are unsized, but cannot be determined
347//! through heuristics. Such a type must also implement [`Decode`] (for
348//! `"value"`), `DecodeUnsized`, or `DecodeUnsizedBytes` as appropriate.
349//!
350//! <br>
351//!
352//! #### `#[musli(bound = {..})]` and `#[musli(decode_bound = {..})]`
353//!
354//! These attributes can be used to apply bounds to an [`Encode`] or [`Decode`]
355//! implementation.
356//!
357//! These are necessary to use when a generic container is used to ensure that
358//! the given parameter implements the necessary bounds.
359//!
360//! `#[musli(bound = {..})]` applies to all implementations while
361//! `#[musli(decode_bound = {..})]` only applies to the [`Decode`]
362//! implementation. The latter allows for using the decode lifetime parameter
363//! (which defaults to `'de`).
364//!
365//! ```
366//! use musli::{Decode, Encode};
367//! use musli::mode::{Binary, Text};
368//!
369//! #[derive(Clone, Debug, PartialEq, Encode, Decode)]
370//! #[musli(mode = Binary, bound = {T: Encode<Binary>}, decode_bound = {T: Decode<'de, Binary>})]
371//! #[musli(mode = Text, bound = {T: Encode<Text>}, decode_bound = {T: Decode<'de, Text>})]
372//! pub struct GenericWithBound<T> {
373//! value: T,
374//! }
375//! ```
376//!
377//! <br>
378//!
379//! ## Enum attributes
380//!
381//! <br>
382//!
383//! #### `#[musli(tag = ..)]`
384//!
385//! This attribute causes the enum to be internally tagged, with the given tag.
386//! See [enum representations](#enum-representations) for details on this
387//! representation.
388//!
389//! ```
390//! # use musli::{Encode, Decode};
391//! # #[derive(Encode, Decode)] struct Params;
392//! # #[derive(Encode, Decode)] struct Value;
393//! #[derive(Encode, Decode)]
394//! #[musli(name_all = "name", tag = "type")]
395//! enum Message {
396//! Request { id: String, method: String, params: Params },
397//! Response { id: String, result: Value },
398//! }
399//! ```
400//!
401//! <br>
402//!
403//! ## Variant attributes
404//!
405//! *Variant attributes* are attributes which apply to each individual variant
406//! in an `enum`. Like the use of `#[musli(name = ..)]` here:
407//!
408//! ```
409//! use musli::{Encode, Decode};
410//!
411//! #[derive(Encode, Decode)]
412//!#[musli(name_all = "name")]
413//! enum Enum {
414//! Variant {
415//! /* variant body */
416//! },
417//! #[musli(name = "Other")]
418//! Something {
419//! /* variant body */
420//! },
421//! }
422//! ```
423//!
424//! <br>
425//!
426//! #### `#[musli(name = ..)]`
427//!
428//! This allows for renaming a variant from its default value. It can take any
429//! value (including complex ones) that can be serialized with the current
430//! encoding, such as:
431//!
432//! * `#[musli(name = 1)]`
433//! * `#[musli(name = "Hello World")]`
434//! * `#[musli(name = b"box\0")]`
435//! * `#[musli(name = SomeStruct { field: 42 })]` (if `SomeStruct` implements
436//! [`Encode`] and [`Decode`] as appropriate).
437//!
438//! If the type of the tag is ambiguous it can be explicitly specified through
439//! the `#[musli(name_type)]` attribute.
440//!
441//! <br>
442//!
443//! #### `#[musli(pattern = ..)]`
444//!
445//! A pattern to match for decoding a variant.
446//!
447//! This allows for more flexibility when decoding variants.
448//!
449//! ```
450//! use musli::{Encode, Decode};
451//!
452//! #[derive(Encode, Decode)]
453//! enum Enum {
454//! Variant1,
455//! Variant2,
456//! #[musli(mode = Binary, pattern = 2..=4)]
457//! Deprecated,
458//! }
459//! ```
460//!
461//! <br>
462//!
463//! #### `#[musli(name_all = "..")]`
464//!
465//! Allos for renaming every field in the variant. It can take any of the
466//! following values:
467//!
468//! * `index` (default) - the index of the field will be used.
469//! * `name` - the literal name of the field will be used.
470//! * `PascalCase` - the field will be converted to pascal case.
471//! * `camelCase` - the field will be converted to camel case.
472//! * `snake_case` - the field will be converted to snake case.
473//! * `SCREAMING_SNAKE_CASE` - the field will be converted to screaming snake case.
474//! * `kebab-case` - the field will be converted to kebab case.
475//! * `SCREAMING-KEBAB-CASE` - the field will be converted to screaming kebab case.
476//!
477//! ```
478//! use musli::{Encode, Decode};
479//!
480//! #[derive(Encode, Decode)]
481//! enum PascalCaseEnum {
482//! #[musli(name_all = "PascalCase")]
483//! Variant {
484//! field_name: u32,
485//! }
486//! }
487//!
488//! #[derive(Encode, Decode)]
489//! enum NamedEnum {
490//! #[musli(name_all = "name")]
491//! Variant {
492//! field1: u32,
493//! },
494//! Variant2 {
495//! field1: u32,
496//! },
497//! }
498//! ```
499//!
500//! <br>
501//!
502//! #### `#[musli(name_type = ..)]`
503//!
504//! This indicates which type any contained `#[musli(tag = ..)]` attributes
505//! should have. Tags can usually be inferred, but specifying this field ensures
506//! that all tags have a well-defined type.
507//!
508//! The following values are treated specially:
509//! * `str` applies `#[musli(name_all = "name")]` by default.
510//! * `[u8]` applies `#[musli(name_all = "name")]` by default.
511//!
512//! ```
513//! use core::fmt;
514//!
515//! use musli::{Encode, Decode};
516//!
517//! #[derive(Debug, PartialEq, Eq, Encode, Decode)]
518//! #[musli(transparent)]
519//! struct CustomTag<'a>(&'a [u8]);
520//!
521//! impl fmt::Display for CustomTag<'_> {
522//! fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
523//! fmt::Debug::fmt(self.0, f)
524//! }
525//! }
526//!
527//! #[derive(Encode, Decode)]
528//! #[musli(name_type = usize)]
529//! enum Enum {
530//! #[musli(name = 0usize, name_type = CustomTag)]
531//! Variant {
532//! #[musli(name = CustomTag(b"field1"))]
533//! field1: u32,
534//! #[musli(name = CustomTag(b"field2"))]
535//! field2: u32,
536//! },
537//! #[musli(name = 1usize, name_all = "name")]
538//! Variant2 {
539//! #[musli(name = "field1")]
540//! field1: u32,
541//! #[musli(name = "field2")]
542//! field2: u32,
543//! },
544//! }
545//! ```
546//!
547//! <br>
548//!
549//! #### `#[musli(name_method = ..)]`
550//!
551//! This allows for explicitly setting which method should be used to decode
552//! field names. Available options are:
553//!
554//! * `"value"` (default) - the name is decoded as a value.
555//! * `"unsized"` - the name is decoded as an unsized value, this is the default
556//! if for example `#[musli(name_type = str)]` is used.
557//! * `"unsized_bytes"` - the name is decoded as a unsized bytes, this is the
558//! default if for example `#[musli(name_type = [u8])]` is used.
559//!
560//! This can be overrided for values which are unsized, but cannot be determined
561//! through heuristics. Such a type must also implement [`Decode`] (for
562//! `"value"`), `DecodeUnsized`, or `DecodeUnsizedBytes` as appropriate.
563//!
564//! <br>
565//!
566//! #### `#[musli(transparent)]`
567//!
568//! This can only be used on variants which have a single field. It will cause
569//! that field to define how that variant is encoded or decoded transparently
570//! without being treated as a field.
571//!
572//! <br>
573//!
574//! #### `#[musli(default)]`
575//!
576//! This defines the variant that will be used in case no other variant matches.
577//! Only one such variant can be defined.
578//!
579//! ```
580//! use musli::{Encode, Decode};
581//!
582//! #[derive(Debug, PartialEq, Eq, Encode, Decode)]
583//! #[musli(name_all = "kebab-case")]
584//! enum Animal {
585//! Cat,
586//! Dog,
587//! #[musli(default)]
588//! Unknown,
589//! }
590//! ```
591//!
592//! <br>
593//!
594//! ## Field attributes
595//!
596//! *Field attributes* are attributes which apply to each individual field
597//! either in a `struct` or an `enum` variant. Like the uses of `#[musli(all)]`
598//! here:
599//!
600//! ```
601//! use musli::{Encode, Decode};
602//!
603//! #[derive(Encode, Decode)]
604//! #[musli(name_all = "name")]
605//! struct Struct {
606//! #[musli(name = "other")]
607//! something: String,
608//! #[musli(skip, default = default_field)]
609//! skipped_field: u32,
610//! }
611//!
612//! fn default_field() -> u32 {
613//! 42
614//! }
615//!
616//! #[derive(Encode, Decode)]
617//! #[musli(name_all = "name")]
618//! enum Enum {
619//! #[musli(name_all = "name")]
620//! Variant {
621//! #[musli(name = "other")]
622//! something: String,
623//! }
624//! }
625//! ```
626//!
627//! <br>
628//!
629//! #### `#[musli(skip)]`
630//!
631//! This attribute means that the entire field is skipped. If a field is decoded
632//! it uses [`Default::default`] to construct the value. Other defaults can be
633//! specified with [`#[musli(default = <path>)]`][#muslidefault--path].
634//!
635//! ```
636//! use musli::{Encode, Decode};
637//!
638//! #[derive(Encode, Decode)]
639//! struct Person {
640//! name: String,
641//! #[musli(skip)]
642//! age: Option<u32>,
643//! #[musli(skip, default = default_country)]
644//! country: Option<String>,
645//! }
646//!
647//! fn default_country() -> Option<String> {
648//! Some(String::from("Earth"))
649//! }
650//! ```
651//!
652//! <br>
653//!
654//! #### `#[musli(default [= <path>])]`
655//!
656//! When a field is absent or disabled with `#[musli(skip)]`, this attribute
657//! specifies that a default value should be used instead.
658//!
659//! If `#[musli(default)]` is specified, the default value is constructed using
660//! [`Default::default`].
661//!
662//! If `#[musli(default = <path>)]` is specified, the default value is
663//! constructed by calling the function at `<path>`.
664//!
665//! ```
666//! use musli::{Encode, Decode};
667//!
668//! #[derive(Encode, Decode)]
669//! struct Person {
670//! name: String,
671//! #[musli(default)]
672//! age: Option<u32>,
673//! #[musli(default = default_height)]
674//! height: Option<u32>,
675//! #[musli(skip, default = default_meaning)]
676//! meaning: u32,
677//! }
678//!
679//! fn default_height() -> Option<u32> {
680//! Some(180)
681//! }
682//!
683//! fn default_meaning() -> u32 {
684//! 42
685//! }
686//! ```
687//!
688//! <br>
689//!
690//! #### `#[musli(name = ..)]`
691//!
692//! This allows for renaming a field from its default value. It can take any
693//! value (including complex ones) that can be serialized with the current
694//! encoding, such as:
695//!
696//! * `#[musli(name = 1)]`
697//! * `#[musli(name = "Hello World")]`
698//! * `#[musli(name = b"box\0")]`
699//! * `#[musli(name = SomeStruct { field: 42 })]` (if `SomeStruct` implements
700//! [`Encode`] and [`Decode`] as appropriate).
701//!
702//! If the type of the tag is ambiguous it can be explicitly specified through
703//! the `#[musli(name_type)]` variant or container attributes.
704//!
705//! <br>
706//!
707//! #### `#[musli(pattern = ..)]`
708//!
709//! A pattern to match for decoding the given field.
710//!
711//! This allows for more flexibility when decoding fields.
712//!
713//! ```
714//! use musli::{Encode, Decode};
715//!
716//! #[derive(Encode, Decode)]
717//! struct Struct {
718//! field1: u32,
719//! field2: u32,
720//! #[musli(mode = Binary, pattern = 2..=4)]
721//! other: u32,
722//! }
723//! ```
724//!
725//! <br>
726//!
727//! #### `#[musli(packed)]`
728//!
729//! This specifies that encoding and decoding should happen through the
730//! [`EncodePacked`] and [`DecodePacked`] traits, instead of the default
731//! [`Encode`] and [`Decode`].
732//!
733//! These traits contained implementations which are biased towards encoding the
734//! field as a compact, non-future compatible pack. In essense, the fields are
735//! encoded "one after another" without any metadata separating them. So for
736//! packed fields, the order, types and number of the fields are important.
737//!
738//! ```
739//! use std::collections::VecDeque;
740//!
741//! use musli::{Decode, Encode};
742//!
743//! #[derive(Decode, Encode)]
744//! struct Container {
745//! #[musli(packed)]
746//! tuple: (u32, u64),
747//! #[musli(packed)]
748//! array: [u32; 4],
749//! }
750//! ```
751//!
752//! <br>
753//!
754//! #### `#[musli(bytes)]`
755//!
756//! This specifies that encoding and decoding should happen through the
757//! [`EncodeBytes`] and [`DecodeBytes`] traits, instead of the default
758//! [`Encode`] and [`Decode`].
759//!
760//! These traits contained implementations which are biased towards encoding the
761//! field as an array of bytes.
762//!
763//! ```
764//! use std::collections::VecDeque;
765//!
766//! use musli::{Decode, Encode};
767//!
768//! #[derive(Decode, Encode)]
769//! struct Container<'de> {
770//! #[musli(bytes)]
771//! vec: Vec<u8>,
772//! #[musli(bytes)]
773//! vec_deque: VecDeque<u8>,
774//! #[musli(bytes)]
775//! bytes: &'de [u8],
776//! }
777//! ```
778//!
779//! <br>
780//!
781//! #### `#[musli(with = <path>)]`
782//!
783//! This specifies the path to a module to use instead of the fields default
784//! [`Encode`] or [`Decode`] implementations.
785//!
786//! It expects `encode` and `decode` and decodee function to be defined in the path being specified, like this:
787//!
788//! ```
789//! # mod example {
790//! use musli::{Decode, Encode};
791//!
792//! #[derive(Decode, Encode)]
793//! struct Container {
794//! #[musli(with = self::module)]
795//! field: Field,
796//! }
797//!
798//! struct Field {
799//! /* internal */
800//! }
801//!
802//! mod module {
803//! use musli::{Decoder, Encoder};
804//!
805//! use super::Field;
806//!
807//! pub fn encode<E>(field: &Field, cx: &E::Cx, encoder: E) -> Result<E::Ok, E::Error>
808//! where
809//! E: Encoder,
810//! # { todo!() }
811//!
812//! pub fn decode<'de, D>(cx: &D::Cx, decoder: D) -> Result<Field, D::Error>
813//! where
814//! D: Decoder<'de>,
815//! # { todo!() }
816//! }
817//! # }
818//! ```
819//!
820//! This can also be generic such as:
821//!
822//! ```
823//! # mod example {
824//! use musli::{Decode, Encode};
825//!
826//! #[derive(Decode, Encode)]
827//! struct Container {
828//! #[musli(with = self::module)]
829//! field: Field<u32>,
830//! }
831//!
832//! struct Field<T> {
833//! /* internal */
834//! # value: T,
835//! }
836//!
837//! mod module {
838//! use musli::{Decoder, Encoder};
839//!
840//! use super::Field;
841//!
842//! pub fn encode<E, T>(field: &Field<T>, cx: &E::Cx, encoder: E) -> Result<E::Ok, E::Error>
843//! where
844//! E: Encoder,
845//! # { todo!() }
846//!
847//! pub fn decode<'de, D, T>(cx: &D::Cx, decoder: D) -> Result<Field<T>, D::Error>
848//! where
849//! D: Decoder<'de>,
850//! # { todo!() }
851//! }
852//! # }
853//! ```
854//!
855//! More complete example:
856//!
857//! ```
858//! # mod example {
859//! use std::collections::HashSet;
860//! use musli::{Encode, Decode};
861//!
862//! pub struct CustomUuid(u128);
863//!
864//! #[derive(Encode, Decode)]
865//! struct Struct {
866//! #[musli(with = self::custom_uuid)]
867//! id: CustomUuid,
868//! #[musli(with = self::custom_set)]
869//! numbers: HashSet<u32>,
870//! }
871//!
872//! mod custom_uuid {
873//! use musli::{Context, Decode, Decoder, Encode, Encoder};
874//!
875//! use super::CustomUuid;
876//!
877//! pub fn encode<E>(uuid: &CustomUuid, cx: &E::Cx, encoder: E) -> Result<E::Ok, E::Error>
878//! where
879//! E: Encoder,
880//! {
881//! uuid.0.encode(cx, encoder)
882//! }
883//!
884//! pub fn decode<'de, D>(cx: &D::Cx, decoder: D) -> Result<CustomUuid, D::Error>
885//! where
886//! D: Decoder<'de>,
887//! {
888//! Ok(CustomUuid(decoder.decode()?))
889//! }
890//! }
891//!
892//! mod custom_set {
893//! use std::collections::HashSet;
894//! use std::hash::Hash;
895//!
896//! use musli::{Context, Decode, Decoder, Encode, Encoder};
897//!
898//! pub fn encode<E, T>(set: &HashSet<T>, cx: &E::Cx, encoder: E) -> Result<E::Ok, E::Error>
899//! where
900//! E: Encoder,
901//! T: Encode<E::Mode> + Eq + Hash,
902//! {
903//! encoder.encode(set)
904//! }
905//!
906//! pub fn decode<'de, D, T>(cx: &D::Cx, decoder: D) -> Result<HashSet<T>, D::Error>
907//! where
908//! D: Decoder<'de>,
909//! T: Decode<'de, D::Mode> + Eq + Hash,
910//! {
911//! decoder.decode()
912//! }
913//! }
914//! # }
915//! ```
916//!
917//! <br>
918//!
919//! #### `#[musli(skip_encoding_if = <path>)]`
920//!
921//! This adds a condition to skip encoding a field entirely if the condition is
922//! true. This is very commonly used to skip over encoding `Option<T>` fields.
923//!
924//! ```
925//! use musli::{Encode, Decode};
926//!
927//! #[derive(Encode, Decode)]
928//! struct Person {
929//! name: String,
930//! #[musli(skip_encoding_if = Option::is_none)]
931//! age: Option<u32>,
932//! }
933//! ```
934//!
935//! #### `#[musli(trace)]`
936//!
937//! This causes the field to use the [`DecodeTrace`] / [`EncodeTrace`] when
938//! encoding the field. This is left optional for types where enabling tracing
939//! for the field requires extra traits to be implemented, such as `HashMap<K,
940//! V>` where we'd need `K` to implement `fmt::Display`.
941//!
942//! Without using the `trace` attribute below, the keys in the `values` field
943//! would not be instrumented, so with a decoding error you'd see this:
944//!
945//! ```text
946//! .values: not numeric (at bytes 15-16)
947//! ```
948//!
949//! Instead of this (where `#[musli(trace)]` is enabled):
950//!
951//! ```text
952//! .values[Hello]: not numeric (at bytes 15-16)
953//! ```
954//!
955//! ```
956//! use std::collections::HashMap;
957//!
958//! use musli::{Encode, Decode};
959//!
960//! #[derive(Encode, Decode)]
961//! struct Collection {
962//! #[musli(trace)]
963//! values: HashMap<String, u32>,
964//! }
965//! ```
966//!
967//! <br>
968//!
969//! # Enum representations
970//!
971//! Müsli supports the following enum representations, which mimics the ones
972//! supported by *serde*:
973//!
974//! * Externally tagged (*default*).
975//! * Internally tagged when `#[musli(tag = ..)]` is specified on the enum.
976//! * Adjacently tagged when both `#[musli(tag = ..)]` and `#[musli(content)]`
977//! are specified.
978//!
979//! <br>
980//!
981//! ## Externally tagged
982//!
983//! ```
984//! # use musli::{Encode, Decode};
985//! # #[derive(Encode, Decode)] struct Params;
986//! # #[derive(Encode, Decode)] struct Value;
987//! #[derive(Encode, Decode)]
988//! enum Message {
989//! Request { id: String, method: String, params: Params },
990//! Response { id: String, result: Value },
991//! }
992//! ```
993//!
994//! When an enum is externally tagged it is represented by a single field
995//! indicating the variant of the enum.
996//!
997//! ```json
998//! {"Request": {"id": "...", "method": "...", "params": {...}}}
999//! ```
1000//!
1001//! This is the most portable representation and is supported by most formats.
1002//! It has special support in the [`Encoder`] and [`Decoder`] traits through
1003//! [`Encoder::encode_variant`] and [`Decoder::decode_variant`].
1004//!
1005//! Conceptually this can be considered as a "pair", where the variant tag can
1006//! be extracted from the format before the variant is decoded.
1007//!
1008//! <br>
1009//!
1010//! ## Internally tagged
1011//!
1012//! ```
1013//! # use musli::{Encode, Decode};
1014//! # #[derive(Encode, Decode)] struct Params;
1015//! # #[derive(Encode, Decode)] struct Value;
1016//! #[derive(Encode, Decode)]
1017//! #[musli(name_all = "name", tag = "type")]
1018//! enum Message {
1019//! Request { id: String, method: String, params: Params },
1020//! Response { id: String, result: Value },
1021//! }
1022//! ```
1023//!
1024//! In JSON, the `Message::Request` would be represented as:
1025//!
1026//! ```json
1027//! {"type": "Request", "id": "...", "method": "...", "params": {...}}
1028//! ```
1029//!
1030//! This is only supported by formats which are *self descriptive*, which is a
1031//! requirement for the format to be buffered through [`Decoder::decode_buffer`].
1032//!
1033//! It is necessary to buffer the value, since we need to inspect the fields of
1034//! a map for the field corresponding to the `tag`, and then use this to
1035//! determine which decoder implementation to call.
1036//!
1037//! [`Binary`]: crate::mode::Binary
1038//! [`Text`]: crate::mode::Text
1039//! [`Decode`]: crate::Decode
1040//! [`DecodeBytes`]: crate::de::DecodeBytes
1041//! [`DecodePacked`]: crate::de::DecodePacked
1042//! [`Decoder::decode_buffer`]: crate::Decoder::decode_buffer
1043//! [`Decoder::decode_variant`]: crate::Decoder::decode_variant
1044//! [`Decoder`]: crate::Decoder
1045//! [`DecodeTrace`]: crate::de::DecodeTrace
1046//! [`Encode`]: crate::Encode
1047//! [`EncodeBytes`]: crate::en::EncodeBytes
1048//! [`EncodePacked`]: crate::en::EncodePacked
1049//! [`Encoder::encode_variant`]: crate::Encoder::encode_variant
1050//! [`Encoder`]: crate::Encoder
1051//! [`EncodeTrace`]: crate::en::EncodeTrace
1052//! [default mode]: crate::mode::Binary
1053
1054// Parts of this documentation