//! Principled encoding and decoding of values, relative to a context shared by both the encoder and the decoder.
//!
//! The traits in this module enable (a generalisation of) [delta encoding](https://en.wikipedia.org/wiki/Delta_encoding): instead of encoding a value in islotation, you encode it relative to some context shared between the encoder and the decoder. This can allow you to omit certain information from the encodings, because a decoder can infer it from the context.
//!
//! A concrete example: you want to keep a record of some books being borrowed from a library. An absolute (i.e., non-relative) encoding of such a record might include the ISBNs of the books, the name of the person who borrowed them, and their address. But an encoding *relative to a library card* would get to omit the name and the address, because those are found on the library card already. A decoder needs access to the same library card to decode successfully, it would reconstruct the missing information simply by copying it from the library card.
//!
//! This module is structured analogously to the [`codec`](super::codec) module, with [`RelativeEncodable`] and [`RelativeDecodable`] taking on the roles of [`Encodable`](super::codec::Encodable) and [`Decodable`](super::codec::Decodable) respectively. Both traits take a `RelativeTo` type argument, denoting the type of values relative to which you can encode and decode.
//!
//! Formally, a relative encoding relation is any ternary relation over `(T, RelativeTo, &[Symbol])` such that fixing any one value `rel` of type `RelativeTo` in the ternary relation induces a "normal" [encoding relation](crate::codec) for `T` and `&[Symbol]`. That is, the encodings relative to any fixed value must be according to a total, injective, and prefix-free function. But these properties do not need to hold when comparing encodings relative to nonequal values. For example, if two different persons borrow the same book, the encodings of those records relative to the persons’ respective library cards would be equal.
//!
//! It is *not* required that *every* value of type `T` can be encoded relative to *every* value of type `RelativeTo`. For example, a relative encoding could specify how to encode strings relative to any of their prefixes. The [`RelativeEncodable::can_be_encoded_relative_to`] method returns for any `T` whether it can be encoded relative to any `RelativeTo`. Calling [`RelativeEncodable::relative_encode`] with an invalid pair of value-to-encode and value-to-encode-relative-to is allowed to panic.
//!
//! ## Extended Example
//!
//! An example demonstrating how to encode and decode bytestrings relative to a prefix of theirs.
//!
//! ```
//! use ufotofu::codec::endian::U64BE;
//! use ufotofu::codec_prelude::*;
//!
//! /// A `Vec<u8>` that can be encoded relative to any of its prefixes,
//! /// by encoding the length of all non-prefix data, followed by that non-prefix data.
//! #[derive(Debug, PartialEq, Eq, Clone)]
//! struct PrefixEncodedBytes(Vec<u8>);
//!
//! impl RelativeEncodable<Vec<u8>> for PrefixEncodedBytes {
//! async fn relative_encode<C>(&self, rel: &Vec<u8>, consumer: &mut C)
//! -> Result<(), C::Error>
//! where
//! C: BulkConsumer<Item = u8> + ?Sized,
//! {
//! // Encode the number of bytes which will follow, as a big-endian u64.
//! consumer
//! .consume_encoded(&U64BE((self.0.len() - rel.len()) as u64))
//! .await?;
//!
//! // Encode exactly the bytes which cannot be simply copied from `rel` when decoding.
//! consumer
//! .consume_full_slice(&self.0[rel.len()..])
//! .await
//! .map_err(|err| err.reason)?;
//!
//! Ok(())
//! }
//!
//! /// You can encode `self` relative to a bytestring iff the bytestring prefixes `self`.
//! fn can_be_encoded_relative_to(&self, rel: &Vec<u8>) -> bool {
//! self.0.starts_with(rel)
//! }
//! }
//!
//! impl RelativeEncodableKnownLength<Vec<u8>> for PrefixEncodedBytes {
//! fn len_of_relative_encoding(&self, rel: &Vec<u8>) -> usize {
//! // 8 bytes for the length of the content we have to encode,
//! // and then the length of that content.
//! 8 + (self.0.len() - rel.len())
//! }
//! }
//!
//! impl RelativeDecodable<Vec<u8>> for PrefixEncodedBytes {
//! // The only thing that can go wrong is if the producer does not provide enough bytes.
//! // This is covered by `DecodeError::UnexpectedEndOfInput` and `DecodeError::ProducerError`
//! // already, so the error for other kinds of invalid encodings can be the empty type.
//! type ErrorReason = Infallible;
//!
//! async fn relative_decode<P>(
//! rel: &Vec<u8>,
//! producer: &mut P,
//! ) -> Result<Self, DecodeError<P::Final, P::Error, Self::ErrorReason>>
//! where
//! P: BulkProducer<Item = u8> + ?Sized,
//! Self: Sized,
//! {
//! // Decode how much data will follow.
//! let mut bytes_to_decode = U64BE::decode(producer).await?.0 as usize;
//!
//! // Allocate the vec to return, prefilled with the data in `rel`.
//! let mut decoded = rel.clone();
//!
//! // Keep appending data to the vec we want to return.
//! while bytes_to_decode > 0 {
//! match producer
//! .expose_items_sync(|items| {
//! let min = core::cmp::min(items.len(), bytes_to_decode);
//!
//! decoded.extend_from_slice(&items[..min]);
//! bytes_to_decode -= min;
//!
//! (min, ())
//! })
//! .await?
//! {
//! Right(fin) => {
//! // If we hit the end of the producer before we got sufficiently
//! // many bytes, we emit an error.
//! return Err(DecodeError::UnexpectedEndOfInput(fin));
//! }
//! Left(()) => { /* continue decoding */ }
//! }
//! }
//!
//! Ok(Self(decoded))
//! }
//! }
//!
//! impl RelativeDecodableCanonic<Vec<u8>> for PrefixEncodedBytes {
//! type ErrorCanonic = Self::ErrorReason;
//!
//! async fn relative_decode_canonic<P>(
//! rel: &Vec<u8>,
//! producer: &mut P,
//! ) -> Result<Self, DecodeError<P::Final, P::Error, Self::ErrorCanonic>>
//! where
//! P: BulkProducer<Item = u8> + ?Sized,
//! Self: Sized,
//! {
//! // The "normal" relative decoding function is already canonic, because
//! // there is only one valid encoding for every combination of `self` and `rel`.
//! Self::relative_decode(rel, producer).await
//! }
//! }
//! ```
//!
mod relative_encodable;
pub use relative_encodable::*;
mod relative_decodable;
pub use relative_decodable::*;
#[cfg(feature = "dev")]
pub mod proptest;