//! [<img alt="github" src="https://img.shields.io/badge/github-udoprog/musli-8da0cb?style=for-the-badge&logo=github" height="20">](https://github.com/udoprog/musli)
//! [<img alt="crates.io" src="https://img.shields.io/crates/v/musli.svg?style=for-the-badge&color=fc8d62&logo=rust" height="20">](https://crates.io/crates/musli)
//! [<img alt="docs.rs" src="https://img.shields.io/badge/docs.rs-musli-66c2a5?style=for-the-badge&logoColor=white&logo=data:image/svg+xml;base64,PHN2ZyByb2xlPSJpbWciIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgdmlld0JveD0iMCAwIDUxMiA1MTIiPjxwYXRoIGZpbGw9IiNmNWY1ZjUiIGQ9Ik00ODguNiAyNTAuMkwzOTIgMjE0VjEwNS41YzAtMTUtOS4zLTI4LjQtMjMuNC0zMy43bC0xMDAtMzcuNWMtOC4xLTMuMS0xNy4xLTMuMS0yNS4zIDBsLTEwMCAzNy41Yy0xNC4xIDUuMy0yMy40IDE4LjctMjMuNCAzMy43VjIxNGwtOTYuNiAzNi4yQzkuMyAyNTUuNSAwIDI2OC45IDAgMjgzLjlWMzk0YzAgMTMuNiA3LjcgMjYuMSAxOS45IDMyLjJsMTAwIDUwYzEwLjEgNS4xIDIyLjEgNS4xIDMyLjIgMGwxMDMuOS01MiAxMDMuOSA1MmMxMC4xIDUuMSAyMi4xIDUuMSAzMi4yIDBsMTAwLTUwYzEyLjItNi4xIDE5LjktMTguNiAxOS45LTMyLjJWMjgzLjljMC0xNS05LjMtMjguNC0yMy40LTMzLjd6TTM1OCAyMTQuOGwtODUgMzEuOXYtNjguMmw4NS0zN3Y3My4zek0xNTQgMTA0LjFsMTAyLTM4LjIgMTAyIDM4LjJ2LjZsLTEwMiA0MS40LTEwMi00MS40di0uNnptODQgMjkxLjFsLTg1IDQyLjV2LTc5LjFsODUtMzguOHY3NS40em0wLTExMmwtMTAyIDQxLjQtMTAyLTQxLjR2LS42bDEwMi0zOC4yIDEwMiAzOC4ydi42em0yNDAgMTEybC04NSA0Mi41di03OS4xbDg1LTM4Ljh2NzUuNHptMC0xMTJsLTEwMiA0MS40LTEwMi00MS40di0uNmwxMDItMzguMiAxMDIgMzguMnYuNnoiPjwvcGF0aD48L3N2Zz4K" height="20">](https://docs.rs/musli)
//!
//! Excellent performance, no compromises[^1]!
//!
//! Müsli is a flexible, fast, and generic binary serialization framework for
//! Rust, in the same vein as [`serde`].
//!
//! It provides a set of [formats](#formats), each with its own well-documented
//! set of features and tradeoffs. Every byte-oriented serialization method
//! including escaped formats like [`musli::json`] has full `#[no_std]` support
//! with or without `alloc`. And a particularly neat component providing
//! low-level refreshingly simple [zero-copy serialization][zerocopy].
//!
//! [^1]: As in Müsli should be able to do everything you need and more.
//!
//! <br>
//!
//! ## Overview
//!
//! * See [`derives`] to learn how to implement [`Encode`] and [`Decode`].
//! * See [`data_model`] to learn about the abstract data model of Müsli.
//! * See [benchmarks] and [size comparisons] to learn about the performance of
//!   this framework.
//! * See [`tests`] to learn how this library is tested.
//! * See [`musli::serde`] for seamless compatibility with [`serde`]. You might
//!   also be interested to learn how [Müsli is different][different].
//!
//! [different]: #müsli-is-different-from-serde
//!
//! <br>
//!
//! ## Usage
//!
//! Add the following to your `Cargo.toml` using the [format](#formats) you want
//! to use:
//!
//! ```toml
//! [dependencies]
//! musli = { version = "0.0.130", features = ["storage"] }
//! ```
//!
//! <br>
//!
//! ## Design
//!
//! The heavy lifting is done by the [`Encode`] and [`Decode`] derives which are
//! documented in the [`derives`] module.
//!
//! Müsli operates based on the schema represented by the types which implement
//! these traits.
//!
//! ```
//! use musli::{Encode, Decode};
//!
//! #[derive(Encode, Decode)]
//! struct Person {
//!     /* .. fields .. */
//! }
//! ```
//!
//! > **Note** by default a field is identified by its *numerical index* which
//! > would change if they are re-ordered. Renaming fields and setting a default
//! > naming policy can be done by configuring the [`derives`].
//!
//! The binary serialization formats provided aim to efficiently and accurately
//! encode every type and data structure available in Rust. Each format comes
//! with [well-documented tradeoffs](#formats) and aims to be fully memory safe
//! to use.
//!
//! Internally we use the terms "encoding", "encode", and "decode" because it's
//! distinct from [`serde`]'s use of "serialization", "serialize", and
//! "deserialize" allowing for the clearer interoperability between the two
//! libraries. Encoding and decoding also has more of a "binary serialization"
//! vibe, which more closely reflects the focus of this framework.
//!
//! Müsli is designed on similar principles as [`serde`]. Relying on Rust's
//! powerful trait system to generate code which can largely be optimized away.
//! The end result should be very similar to handwritten, highly optimized code.
//!
//! As an example of this, these two functions both produce the same assembly
//! (built with `--release`):
//!
//! ```
//! # use musli::{Decode, Encode};
//! # use musli::mode::Binary;
//! # use musli::options::{self, Options, Integer, ByteOrder};
//! # use musli::storage::Encoding;
//! # type Result<T, E = musli::storage::Error> = core::result::Result<T, E>;
//! const OPTIONS: Options = options::new().fixed().native_byte_order().build();
//! const ENCODING: Encoding<OPTIONS> = Encoding::new().with_options();
//!
//! #[derive(Encode, Decode)]
//! #[musli(packed)]
//! pub struct Storage {
//!     left: u32,
//!     right: u32,
//! }
//!
//! fn with_musli(storage: &Storage) -> Result<[u8; 8]> {
//!     let mut array = [0; 8];
//!     ENCODING.encode(&mut array[..], storage)?;
//!     Ok(array)
//! }
//!
//! fn without_musli(storage: &Storage) -> Result<[u8; 8]> {
//!     let mut array = [0; 8];
//!     array[..4].copy_from_slice(&storage.left.to_ne_bytes());
//!     array[4..].copy_from_slice(&storage.right.to_ne_bytes());
//!     Ok(array)
//! }
//! ```
//!
//! <br>
//!
//! ## Müsli is different from [`serde`]
//!
//! **Müsli's data model does not speak Rust**. There are no
//! `serialize_struct_variant` methods which provides metadata about the type
//! being serialized. The [`Encoder`] and [`Decoder`] traits are agnostic on
//! this. Compatibility with Rust types is entirely handled using the [`Encode`]
//! and [`Decode`] derives in combination with [modes](#Modes).
//!
//! **We use GATs** to provide easier to use abstractions. GATs were not
//! available when serde was designed.
//!
//! **Everything is a [`Decoder`] or [`Encoder`]**. Field names are therefore
//! not limited to be strings or indexes, but can be named to [arbitrary
//! types][musli-name-type] if needed.
//!
//! **Visitor are only used when needed**. `serde` [completely uses visitors]
//! when deserializing and the corresponding method is treated as a "hint" to
//! the underlying format. The deserializer is then free to call any method on
//! the visitor depending on what the underlying format actually contains. In
//! Müsli, we swap this around. If the caller wants to decode an arbitrary type
//! it calls [`decode_any`]. The format can then either signal the appropriate
//! underlying type or call [`Visitor::visit_unknown`] telling the implementer
//! that it does not have access to type information.
//!
//! **We've invented [*moded encoding*](#Modes)** allowing the same Rust types
//! to be encoded in many different ways with much greater control over how
//! things encoded. By default we include the [`Binary`] and [`Text`] modes
//! providing sensible defaults for binary and text-based formats.
//!
//! **Müsli fully supports [no-std and no-alloc]** from the ground up without
//! compromising on features using safe and efficient [scoped allocations].
//!
//! **We support [detailed tracing]** when decoding for much improved
//! diagnostics of *where* something went wrong.
//!
//! <br>
//!
//! ## Formats
//!
//! Formats are currently distinguished by supporting various degrees of
//! *upgrade stability*. A fully upgrade stable encoding format must tolerate
//! that one model can add fields that an older version of the model should be
//! capable of ignoring.
//!
//! Partial upgrade stability can still be useful as is the case of the
//! [`musli::storage`] format below, because reading from storage only requires
//! decoding to be upgrade stable. So if correctly managed with
//! `#[musli(default)]` this will never result in any readers seeing unknown
//! fields.
//!
//! The available formats and their capabilities are:
//!
//! | | `reorder` | `missing` | `unknown` | `self` |
//! |-|-|-|-|-|
//! | [`musli::packed`] (with `#[musli(packed)]`) | ✗ | ✗ | ✗ | ✗ |
//! | [`musli::storage`]                          | ✔ | ✔ | ✗ | ✗ |
//! | [`musli::wire`]                             | ✔ | ✔ | ✔ | ✗ |
//! | [`musli::descriptive`]                      | ✔ | ✔ | ✔ | ✔ |
//! | [`musli::json`] [^json]                     | ✔ | ✔ | ✔ | ✔ |
//!
//! `reorder` determines whether fields must occur in exactly the order in which
//! they are specified in their type. Reordering fields in such a type would
//! cause unknown but safe behavior of some kind. This is only suitable for
//! communication where the data models of each client are strictly
//! synchronized.
//!
//! `missing` determines if reading can handle missing fields through something
//! like `Option<T>`. This is suitable for on-disk storage, because it means
//! that new optional fields can be added as the schema evolves.
//!
//! `unknown` determines if the format can skip over unknown fields. This is
//! suitable for network communication. At this point you've reached [*upgrade
//! stability*](#upgrade-stability). Some level of introspection is possible
//! here, because the serialized format must contain enough information about
//! fields to know what to skip which usually allows for reasoning about basic
//! types.
//!
//! `self` determines if the format is self-descriptive. Allowing the structure
//! of the data to be fully reconstructed from its serialized state. These
//! formats do not require models to decode and can be converted to and from
//! dynamic containers such as [`musli::value`] for introspection. Such formats
//! also allows for type-coercions to be performed, so that a signed number can
//! be correctly read as an unsigned number if it fits in the destination type.
//!
//! For every feature you drop, the format becomes more compact and efficient.
//! [`musli::storage`] using `#[musli(packed)]` for example is roughly as compact
//! as [`bincode`] while [`musli::wire`] is comparable in size to something like
//! [`protobuf`]. All formats are primarily byte-oriented, but some might
//! perform [bit packing] if the benefits are obvious.
//!
//! [^json]: This is strictly not a binary serialization, but it was implemented
//! as a litmus test to ensure that Müsli has the necessary framework features
//! to support it. Luckily, the implementation is also quite good!
//!
//! <br>
//!
//! ## Upgrade stability
//!
//! The following is an example of *full upgrade stability* using
//! [`musli::wire`]. `Version1` can be decoded from an instance of `Version2`
//! because it understands how to skip fields which are part of `Version2`.
//! We're also explicitly adding `#[musli(name = ..)]` to the fields to ensure
//! that they don't change in case they are re-ordered.
//!
//! ```
//! use musli::{Encode, Decode};
//!
//! #[derive(Debug, PartialEq, Encode, Decode)]
//! struct Version1 {
//!     #[musli(Binary, name = 0)]
//!     name: String,
//! }
//!
//! #[derive(Debug, PartialEq, Encode, Decode)]
//! struct Version2 {
//!     #[musli(Binary, name = 0)]
//!     name: String,
//!     #[musli(Binary, name = 1)]
//!     #[musli(default)]
//!     age: Option<u32>,
//! }
//!
//! let version2 = musli::wire::to_vec(&Version2 {
//!     name: String::from("Aristotle"),
//!     age: Some(61),
//! })?;
//!
//! let version1: Version1 = musli::wire::decode(version2.as_slice())?;
//! # Ok::<_, musli::wire::Error>(())
//! ```
//!
//! The following is an example of *partial upgrade stability* using
//! [`musli::storage`] on the same data models. Note how `Version2` can be
//! decoded from `Version1` but *not* the other way around making it suitable
//! for on-disk storage where the schema can evolve from older to newer
//! versions.
//!
//! ```
//! # use musli::{Encode, Decode};
//! # #[derive(Debug, PartialEq, Encode, Decode)]
//! # struct Version1 { name: String }
//! # #[derive(Debug, PartialEq, Encode, Decode)]
//! # struct Version2 { name: String, #[musli(default)] age: Option<u32> }
//! # fn main() -> Result<(), Box<dyn core::error::Error>> {
//! let version2 = musli::storage::to_vec(&Version2 {
//!     name: String::from("Aristotle"),
//!     age: Some(61),
//! })?;
//!
//! assert!(musli::storage::decode::<_, Version1>(version2.as_slice()).is_err());
//!
//! let version1 = musli::storage::to_vec(&Version1 {
//!     name: String::from("Aristotle"),
//! })?;
//!
//! let version2: Version2 = musli::storage::decode(version1.as_slice())?;
//! # Ok(()) }
//! ```
//!
//! <br>
//!
//! ## Modes
//!
//! In Müsli in contrast to [`serde`] the same model can be serialized in
//! different ways. Instead of requiring the use of distinct models we support
//! implementing different *modes* for a single model.
//!
//! A mode is a type parameter, which allows for different attributes to apply
//! depending on which mode an encoder is configured to use. A mode can apply to
//! *any* musli attributes giving you a lot of flexibility.
//!
//! If a mode is not specified, an implementation will apply to all modes (`M`),
//! if at least one mode is specified it will be implemented for all modes which
//! are present in a model and [`Binary`] and [`Text`]. This way, an encoding
//! which uses [`Binary`] or [`Text`] which are the default modes should always
//! work.
//!
//! For more information on how to configure modes, see [`derives`].
//!
//! Below is a simple example of how we can use two modes to provide two
//! completely different formats using a single struct:
//!
//! ```
//! use musli::{Decode, Encode};
//! use musli::json::Encoding;
//!
//! enum Alt {}
//!
//! #[derive(Decode, Encode)]
//! #[musli(Text, name_all = "name")]
//! #[musli(mode = Alt, packed)]
//! struct Word<'a> {
//!     text: &'a str,
//!     teineigo: bool,
//! }
//!
//! const TEXT: Encoding = Encoding::new();
//! const ALT: Encoding<Alt> = Encoding::new().with_mode();
//!
//! let word = Word {
//!     text: "あります",
//!     teineigo: true,
//! };
//!
//! let out = TEXT.to_string(&word)?;
//! assert_eq!(out, r#"{"text":"あります","teineigo":true}"#);
//!
//! let out = ALT.to_string(&word)?;
//! assert_eq!(out, r#"["あります",true]"#);
//! # Ok::<_, musli::json::Error>(())
//! ```
//!
//! <br>
//!
//! ## Going very fast
//!
//! With the previous sections it should be apparent that speed is primarily a
//! game of tradeoffs. If we make every tradeoff in favor of speed Müsli is
//! designed to be the fastest framework out there.
//!
//! The tradeoffs we will be showcasing to achieve speed here are:
//!
//! * *Pre-allocate serialization space*. This avoids all allocations during
//!   serialization. The tradeoff is that if the data we are serializing
//!   contains dynamically sized information which goes beyond the pre-allocated
//!   space, we will error.
//! * *Use fixed-sized integers and floats*. We use more space, but the cost of
//!   serializing numerical fields essentially boils down to copying them.
//! * *Use a native byte order*. With this we avoid any byte-swapping
//!   operations. But our data becomes less portable.
//! * *Use a packed format*. This doesn't allow for any upgrades, but we avoid
//!   paying the overhead of serializing field identifiers.
//! * *Use the [`Slice` allocator]*. This avoids all heap allocations using the
//!   system allocator. While the system allocator is quite efficient and
//!   normally shouldn't be avoided, the slice allocator is a fixed-slab
//!   allocator. The tradeoff here is that we will error in case we run out of
//!   memory, but we only need to use the allocator if the types being
//!   serialized (or the format) demands it.
//! * *Disable error handling*. Code generation will be able to remove
//!   everything related to error handling, like allocations. To do this we can
//!   make use of the [default context] without configuring it for tracing. If
//!   an error happens, we are only informed of that fact through a zero-sized
//!   marker type.
//!
//! We achieve this through the following methods:
//!
//! ```
//! use musli::alloc::{Allocator, System};
//! use musli::context::{self, ErrorMarker as Error};
//! use musli::options::{self, Float, Integer, Width, Options};
//! use musli::storage::Encoding;
//! use musli::{Decode, Encode};
//! use musli::alloc::Slice;
//!
//! enum Packed {}
//!
//! const OPTIONS: Options = options::new().fixed().native_byte_order().build();
//! const ENCODING: Encoding<OPTIONS, Packed> = Encoding::new().with_options().with_mode();
//!
//! #[inline]
//! pub fn encode<'buf, T, A>(buf: &'buf mut [u8], value: &T, alloc: A) -> Result<&'buf [u8], Error>
//! where
//!     T: Encode<Packed>,
//!     A: Allocator,
//! {
//!     let cx = context::new_in(alloc);
//!     let w = ENCODING.to_slice_with(&cx, &mut buf[..], value)?;
//!     Ok(&buf[..w])
//! }
//!
//! #[inline]
//! pub fn decode<'buf, T, A>(buf: &'buf [u8], alloc: A) -> Result<T, Error>
//! where
//!     T: Decode<'buf, Packed, A>,
//!     A: Allocator,
//! {
//!     let cx = context::new_in(alloc);
//!     ENCODING.from_slice_with(&cx, buf)
//! }
//! ```
//!
//! We also need some cooperation from the types being serialized since they
//! need to use the `Packed` mode we defined just above:
//!
//! ```
//! use musli::{Encode, Decode};
//! # enum Packed {}
//!
//! #[derive(Encode, Decode)]
//! #[musli(mode = Packed, packed)]
//! struct Person {
//!     name: String,
//!     age: u32,
//! }
//! ```
//!
//! Using the framework above also needs a bit of prep, namely the slice
//! allocator need to be initialized:
//!
//! ```
//! use musli::alloc::{ArrayBuffer, Slice};
//!
//! let mut buf = ArrayBuffer::new();
//! let alloc = Slice::new(&mut buf);
//! ```
//!
//! That's it! You are now using Müsli in the fastest possible mode. Feel free
//! to use it to "beat" any benchmarks. In fact, the `musli_packed` mode in our
//! internal [benchmarks] beat pretty much every framework with these methods.
//!
//! > My hope is that this should illustrate why you shouldn't blindly trust
//! > benchmarks. Sometimes code is not fully optimized, but most of the time
//! > there is a tradeoff. If a benchmark doesn't tell you what tradeoffs are
//! > being made, don't just naively trust a number.
//!
//! <br>
//!
//! ## Unsafety
//!
//! This is a non-exhaustive list of unsafe use in this crate, and why they are
//! used:
//!
//! * A `mem::transmute` in `Tag::kind`. Which guarantees that converting into
//!   the `Kind` enum which is `#[repr(u8)]` is as efficient as possible.
//!
//! * A largely unsafe `SliceReader` which provides more efficient reading than
//!   the default `Reader` impl for `&[u8]` does. Since it can perform most of
//!   the necessary comparisons directly on the pointers.
//!
//! * Some unsafety related to UTF-8 handling in `musli::json`, because we check
//!   UTF-8 validity internally ourselves (like `serde_json`).
//!
//! * `FixedBytes<N>`, which is a stack-based container that can operate over
//!   uninitialized data. Its implementation is largely unsafe. With it
//!   stack-based serialization can be performed which is useful in no-std
//!   environments.
//!
//! * Some `unsafe` is used for owned `String` decoding in all binary formats to
//!   support faster string processing through [`simdutf8`]. Disabling the
//!   `simdutf8` feature (enabled by default) removes the use of this unsafe.
//!
//! To ensure this library is correctly implemented with regards to memory
//! safety, extensive testing and fuzzing is performed using `miri`. See
//! [`tests`] for more information.
//!
//! <br>
//!
//! [`Binary`]: <https://docs.rs/musli/latest/musli/mode/enum.Binary.html>
//! [`bincode`]: <https://docs.rs/bincode>
//! [`data_model`]: <https://docs.rs/musli/latest/musli/_help/data_model/>
//! [`decode_any`]: https://docs.rs/musli/latest/musli/trait.Decoder.html#method.decode_any
//! [`Decode`]: <https://docs.rs/musli/latest/musli/de/trait.Decode.html>
//! [`Decoder`]: <https://docs.rs/musli/latest/musli/trait.Decoder.html>
//! [`derives`]: <https://docs.rs/musli/latest/musli/_help/derives/>
//! [`Encode`]: <https://docs.rs/musli/latest/musli/en/trait.Encode.html>
//! [`Encoder`]: <https://docs.rs/musli/latest/musli/trait.Encoder.html>
//! [`musli::descriptive`]: <https://docs.rs/musli/latest/musli/descriptive/>
//! [`musli::json`]: <https://docs.rs/musli/latest/musli/json/>
//! [`musli::packed`]: <https://docs.rs/musli/latest/musli/packed/>
//! [`musli::serde`]: <https://docs.rs/musli/latest/musli/serde/>
//! [`musli::storage`]: <https://docs.rs/musli/latest/musli/storage/>
//! [`musli::value`]: <https://docs.rs/musli/latest/musli/value/>
//! [`musli::wire`]: <https://docs.rs/musli/latest/musli/wire/>
//! [`protobuf`]: <https://developers.google.com/protocol-buffers>
//! [`serde`]: <https://serde.rs>
//! [`simdutf8`]: <https://docs.rs/simdutf8>
//! [`Slice` allocator]: <https://docs.rs/musli/latest/musli/alloc/struct.Slice.html>
//! [`tests`]: <https://github.com/udoprog/musli/tree/main/tests>
//! [`Text`]: <https://docs.rs/musli/latest/musli/mode/enum.Text.html>
//! [`Visitor::visit_unknown`]: https://docs.rs/musli/latest/musli/de/trait.Visitor.html#method.visit_unknown
//! [benchmarks]: <https://udoprog.github.io/musli/benchmarks/>
//! [bit packing]: <https://github.com/udoprog/musli/blob/main/crates/musli/src/descriptive/tag.rs>
//! [completely uses visitors]: https://docs.rs/serde/latest/serde/trait.Deserializer.html#tymethod.deserialize_u32
//! [default context]: <https://docs.rs/musli/latest/musli/context/new_in.html>
//! [detailed tracing]: <https://udoprog.github.io/rust/2023-05-22/abductive-diagnostics-for-musli.html>
//! [musli-name-type]: <https://docs.rs/musli/latest/musli/_help/derives/#muslinametype--type>
//! [no-std and no-alloc]: <https://github.com/udoprog/musli/blob/main/no-std/examples/>
//! [scoped allocations]: <https://docs.rs/musli/latest/musli/trait.Context.html#tymethod.alloc>
//! [size comparisons]: <https://udoprog.github.io/musli/benchmarks/#size-comparisons>
//! [zerocopy]: <https://docs.rs/musli-zerocopy>

#![deny(missing_docs)]
#![allow(clippy::module_inception)]
#![no_std]
#![cfg_attr(doc_cfg, feature(doc_cfg))]

#[cfg(feature = "alloc")]
extern crate alloc as rust_alloc;

#[cfg(feature = "std")]
extern crate std;

pub mod macros;

#[cfg(test)]
mod tests;

#[cfg(feature = "json")]
mod dec2flt;

pub mod _help {
    //! Detailed documentation for Müsli
    //!
    //! * [The data model of Müsli][data_model].
    //! * [Deriving `Encode` and `Decode`][derives].

    #[doc = include_str!("../help/data_model.md")]
    pub mod data_model {}

    #[doc = include_str!("../help/derives.md")]
    pub mod derives {}
}

pub mod de;
pub mod en;

#[doc(inline)]
pub use musli_core::hint;
#[doc(inline)]
pub use musli_core::mode;

#[doc(inline)]
pub use musli_core::Context;

#[doc(inline)]
pub use self::de::{decoder, Decode, Decoder};

#[doc(inline)]
pub use self::en::{encoder, Encode, Encoder};

#[doc(hidden)]
pub use musli_core::__priv;

pub mod alloc;
#[doc(inline)]
pub use self::alloc::Allocator;

pub mod descriptive;
pub mod json;
pub mod packed;
pub mod serde;
pub mod storage;
pub mod value;
pub mod wire;

pub mod context;

pub mod compat;

pub mod fixed;
#[doc(inline)]
pub use self::fixed::FixedBytes;

pub mod options;
#[doc(inline)]
pub use self::options::Options;

pub mod reader;
#[doc(inline)]
pub use self::reader::{IntoReader, Reader};

pub mod wrap;

pub mod writer;
#[doc(inline)]
pub use self::writer::{IntoWriter, Writer};

pub mod no_std;

mod int;
mod str;

use crate::alloc::Disabled;
use crate::mode::Binary;

/// Test if the given type `T` is marked with the `#[musli(packed)]` attribute,
/// and is bitwise encodeable in the [`Binary`] mode.
///
/// See the [help section for `#[musli(packed)]`][help] for more information.
///
/// [help]: crate::_help::derives#muslipacked
#[inline]
pub const fn is_bitwise_encode<T>() -> bool
where
    T: Encode<Binary>,
{
    T::IS_BITWISE_ENCODE
}

/// Test if the given type `T` is marked with the `#[musli(packed)]` attribute,
/// and is bitwise encodeable in the [`Binary`] mode using the [`Disabled`]
/// allocator.
///
/// See the [help section for `#[musli(packed)]`][help] for more information.
///
/// [help]: crate::_help::derives#muslipacked
#[inline]
pub const fn is_bitwise_decode<T>() -> bool
where
    T: for<'de> Decode<'de, Binary, Disabled>,
{
    T::IS_BITWISE_DECODE
}
