//! Low-level primitives for data encoding.
//!
//! These primitives work directly with [`WriteBuffer`](crate::WriteBuffer) instances.
//! Each primitive encodes one marker [`Marker`](crate::Marker) variant, depending on the data type, and the associated data.
//! The data is commited to the buffers only if there is enough space availabe to write the marker and the marker argument, if any.
//! All encoding primitives check for space availability before commiting data and they return [`OutOfMemory`](crate::Error::OutOfMemory) in the case that there is not enough space in the buffer for the respective encoding.
//!
//! On success, each encoding function returns the [`Marker`](crate::Marker) used for that particular encoding.
//! The returned marker may be inspected to determine the amount of buffer space used by the encoding.
//!
//! # Unsigned
//! Unsigned integer values are encoded by using one of the functions [`write_unsigned`], [`write_u8`], [`write_u16`], [`write_u32`] and [`write_u64`].
//! The [`write_unsigned`] function will encode its parameter using the most efficient representation, depending on its value.
//! The other functions will encode the value using their specific representations.
//!
//! # Signed
//! Similar to unsigned values, signed integer values are encoded by using one of the functions [`write_signed`], [`write_i8`], [`write_i16`], [`write_i32`] and [`write_i64`].
//! The same principles apply to signed value encodings.
//!
//! # Floating point
//! Single and double precision floating point values are encoded using one of the functions [`write_f32`] and [`write_f64`].
//! Both functions encode their specific marker and the floating point data as either a 32-bit or 64-bit marker argument following the marker.
//!
//! # Containers
//! The supported containers are arrays and maps.
//! The library supports fixed-size, as well as flexible container encodings.
//! Arrays are encoded using the [`write_array`] function while maps are encoded using the [`write_map`] function.
//! Both functions work based on the same principles.
//!
//! The elements of a container follow immediately after the container length encoding.
//! There is no restriction applied to the data types of contained elements.
//! Therefore, the elements of a container may have arbitrary data types.
//! In the case of flexible containers, the user must explicitly terminate the container using the [`write_terminator`] function.
//!
//! ## Fixed-size encodings
//! ```
//! use petra::encode::*;
//! use petra::WriteBuffer;
//!
//! let mut data = [0u8; 1024];
//! let mut buffer = WriteBuffer::from(&mut data);
//!
//! // Encode the marker and length associated with a fixed-size array of 3 elements.
//! write_array(&mut buffer, Some(3));
//!
//! // Here we must encode the three elements of the array.
//! write_unsigned(&mut buffer, 10);
//! write_str(&mut buffer, "ok");
//! write_bool(&mut buffer, true);
//!
//! // The array is terminated automatically at this point.
//! // The next marker to be written is not part of the array.
//! ```
//!
//! Maps are encoded similarly, with the difference that each map element is a key-value pair, so it requires two encodings per element.
//!
//! ## Flexible encodings
//! ```
//! use petra::encode::*;
//! use petra::WriteBuffer;
//!
//! let mut data = [0u8; 1024];
//! let mut buffer = WriteBuffer::from(&mut data);
//!
//! // Encode the marker for a flexible map.
//! write_map(&mut buffer, None);
//!
//! // Here we may encode as many elements as we wish, in key-value pairs because this is a map.
//! write_str(&mut buffer, "first key");
//! write_unsigned(&mut buffer, 0);
//!
//! write_str(&mut buffer, "second key");
//! write_bool(&mut buffer, true);
//!
//! // And so on..
//!
//! // When we are done with encoding key-value pairs, we can terminate the container.
//! write_terminator(&mut buffer);
//!
//! // The next marker to be written is not part of the array.
//! ```
//!
//! # Strings and byte arrays
//! Strings are encoded using the [`write_str`] function while byte arrays (or binary data) are encoded using the [`write_bin`] function.
//! UTF-8 strings are not yet accepted. Any string containing characters outside of the ASCII range is rejected with the [`BadEncoding`](crate::Error::BadEncoding) error.
//! Both functions will encode their respective markers and the string or binary data using the most efficient representation.
//! For the encoding to complete successfuly, the buffer must have enough space for the marker, the length encoding and the string or binary data itself.
//!
//! # Boolean
//! Boolean values are encoded as immediate values using the [`write_bool`] function.
//!
//! # Null
//! The unit `()` or null is encoded using the [`write_null`] function.

mod array;
mod ascii;
mod bin;
mod boolean;
mod float;
mod map;
mod null;
mod signed;
mod terminator;
mod unsigned;

pub use array::*;
pub use ascii::*;
pub use bin::*;
pub use boolean::*;
pub use float::*;
pub use map::*;
pub use null::*;
pub use signed::*;
pub use terminator::*;
pub use unsigned::*;

#[cfg(test)]
mod tests;
