//! `petra` is a simple binary encoding library with support for flexible containers.
//!
//! Heavily inspired by [MessagePack](https://msgpack.org/), `petra` aims to provide more or less the same features with an additional goal of supporting flexible maps and arrays.
//! There are both advantages and disadvantages associated with such a feature, therefore `petra` might not be the right tool for many jobs, but it is a useful tool to have around nevertheless.
//!
//! In a similar fashion to [MessagePack](https://msgpack.org/), `petra` uses 8-bit [`Marker`]s to delimit and discriminate data.
//! Markers are defined for a variety of data types and representations.
//! Each piece of data is preceeded by a marker identifying the type and lenght of the data.
//! For more information on the encoding format, please see the specifications.
//!
//! # Buffers
//! Two buffer variants are provided by the library: [`ReadBuffer`] and [`WriteBuffer`].
//! These buffers are at the core of the entire encoding and decoding mechanics of the library.
//! They wrap around references to data and provide reading and writing capabilities with cursor tracking and a few more features.
//!
//! # Encoding and decoding
//! The [`decode`] and [`encode`] modules provide low-level functions for reading and writing directly to and from [`ReadBuffer`] and [`WriteBuffer`] instances.
//! The higer-level [`de`] and [`ser`] modules provide standard [`Serializer`](serde::ser::Serializer) and [`Deserializer`](serde::de::Deserializer) implementations for working for arbitrary data types.
//!
//! # Examples
//! ## Serialization from a struct and manual data decoding
//! ```
//! use serde::Serialize;
//!
//! use petra::decode::*;
//! use petra::{Marker, ReadBuffer, WriteBuffer};
//! use petra::ser::Serializer;
//!
//! #[derive(Serialize)]
//! struct Foo {
//!     x: u8,
//!     y: String,
//! }
//!
//! let mut data = [0u8; 1024];
//! let mut buffer = WriteBuffer::from(&mut data);
//!
//! let mut ser = Serializer::from_buffer(&mut buffer);
//! let foo = Foo { x: 42, y: "it works".into() };
//!
//! foo.serialize(&mut ser);
//!
//! let mut buffer = buffer.into_read_buffer();
//!
//! // The struct `foo` is encoded as a map with two elements.
//! assert_eq!(read_map(&mut buffer), Ok(Some(2)));
//!
//! // The keys in the map are the field names.
//! // The values are u8 and str.
//!
//! // The first field.
//! assert_eq!(read_str(&mut buffer), Ok("x"));
//! assert_eq!(read_unsigned(&mut buffer), Ok(42));
//!
//! // The second field.
//! assert_eq!(read_str(&mut buffer), Ok("y"));
//! assert_eq!(read_str(&mut buffer), Ok("it works"));
//! ```
//!
//! ## Manual data encoding and deserialization into a struct
//! ```
//! use serde::Deserialize;
//!
//! use petra::encode::*;
//! use petra::{Marker, ReadBuffer, WriteBuffer};
//! use petra::de::Deserializer;
//!
//! #[derive(Debug, Deserialize, PartialEq)]
//! struct Foo<'a> {
//!     a: u16,
//!
//!     #[serde(borrow)]
//!     b: Vec<&'a str>,
//!
//!     c: bool,
//! }
//!
//! let mut data = [0u8; 1024];
//! let mut buffer = WriteBuffer::from(&mut data);
//!
//! // The struct `foo` is encoded as a map with three elements.
//! assert!(matches!(write_map(&mut buffer, Some(3)), Ok(Marker::ImmMap { len: 3 })));
//!
//! // The keys in the map are the field names.
//! // The values are of types u16, flexible array of String, and bool.
//!
//! // The first field.
//! assert!(matches!(write_str(&mut buffer, "a"), Ok(Marker::ImmStr { len: 1 })));
//! assert!(matches!(write_unsigned(&mut buffer, 1024), Ok(Marker::U16)));
//!
//! // The second field.
//! assert!(matches!(write_str(&mut buffer, "b"), Ok(Marker::ImmStr { len: 1 })));
//! assert!(matches!(write_array(&mut buffer, None), Ok(Marker::AFlex)));
//!
//! // Now we may encode any number of array elements of type String, let's say 2 elements.
//! {
//!     assert!(matches!(write_str(&mut buffer, "first"), Ok(Marker::ImmStr { len: 5 })));
//!     assert!(matches!(write_str(&mut buffer, "second"), Ok(Marker::ImmStr { len: 6 })));
//! }
//!
//! // And we terminate the flexible array.
//! assert!(matches!(write_terminator(&mut buffer), Ok(Marker::Term)));
//!
//! // The last field.
//! assert!(matches!(write_str(&mut buffer, "c"), Ok(Marker::ImmStr { len: 1 })));
//! assert!(matches!(write_bool(&mut buffer, true), Ok(Marker::Bool { value: true })));
//!
//! let mut buffer = buffer.into_read_buffer();
//! let mut de = Deserializer::from_buffer(&mut buffer);
//!
//! assert_eq!(
//!     Foo::deserialize(&mut de),
//!     Ok(Foo {
//!         a: 1024,
//!         b: vec!["first", "second"],
//!         c: true,
//!     }),
//! );
//! ```
#![cfg_attr(docsrs, feature(doc_auto_cfg))]
#![no_std]

mod buffers;
mod error;
mod marker;

pub mod decode;
pub mod encode;

#[cfg(feature = "serde")]
pub mod de;

#[cfg(feature = "serde")]
pub mod ser;

pub use buffers::*;
pub use error::*;
pub use marker::*;
