//! Serializing byte buffers as hex strings with `serde`.
//!
//! # Problem
//!
//! Sometimes, you need to serialize a byte buffer (say, a newtype around `[u8; 32]` or `Vec<u8>`)
//! as a hex string. The problem is, the newtype in question can be defined in another crate
//! (for example, cryptographic types from [`sodiumoxide`]), so you can't implement `Serialize` /
//! `Deserialize` for the type due to Rust orphaning rules. (Or maybe `Serialize` / `Deserialize`
//! *are* implemented, but not in the desirable way.)
//!
//! # Solution
//!
//! The core of this crate is the [`Hex`] trait. It provides methods `serialize`
//! and `deserialize`, which signatures match the ones expected by `serde`. These methods
//! use the other two required methods of the trait. As all trait methods have no `self` argument,
//! the trait *can* be implemented for external types; the implementor may be an empty `enum`
//! designated specifically for this purpose. The implementor can then be used
//! for (de)serialization with the help of the `#[serde(with)]` attribute.
//!
//! [`ConstHex`] is an analogue of [`Hex`] that can be used if the serialized buffer has
//! constant length known in compile time.
//!
//! # Crate Features
//!
//! - `alloc` (enabled by default). Enables types that depend on the `alloc` crate:
//! [`Hex`] and [`HexForm`].
//! - `const_len` (disabled by default). Enables types that depend on const generics:
//! [`ConstHex`] and [`ConstHexForm`].
//!
//! [`sodiumoxide`]: https://crates.io/crates/sodiumoxide
//!
//! # Examples
//!
//! ```
//! // Assume this type is defined in an external crate.
//! pub struct Buffer([u8; 8]);
//!
//! impl Buffer {
//! pub fn from_slice(slice: &[u8]) -> Option<Self> {
//! // snip
//! # unimplemented!()
//! }
//! }
//!
//! impl AsRef<[u8]> for Buffer {
//! fn as_ref(&self) -> &[u8] {
//! &self.0
//! }
//! }
//!
//! // We define in our crate:
//! use hex_buffer_serde::Hex;
//! use serde_derive::{Deserialize, Serialize};
//!
//! # use std::borrow::Cow;
//! struct BufferHex; // a single-purpose type for use in `#[serde(with)]`
//! impl Hex<Buffer> for BufferHex {
//! type Error = &'static str;
//!
//! fn create_bytes(buffer: &Buffer) -> Cow<[u8]> {
//! buffer.as_ref().into()
//! }
//!
//! fn from_bytes(bytes: &[u8]) -> Result<Buffer, Self::Error> {
//! Buffer::from_slice(bytes).ok_or_else(|| "invalid byte length")
//! }
//! }
//!
//! #[derive(Serialize, Deserialize)]
//! pub struct Example {
//! #[serde(with = "BufferHex")]
//! buffer: Buffer,
//! // other fields...
//! }
//!
//! # fn main() {}
//! ```
//!
//! ## Use with internal types
//!
//! The crate could still be useful if you have control over the serialized buffer type.
//! `Hex<T>` has a blanket implementation for types `T` satisfying certain constraints:
//! `AsRef<[u8]>` and `TryFrom<&[u8]>`. If these constraints are satisfied, you can
//! use `HexForm::<T>` in `#[serde(with)]`:
//!
//! ```
//! // It is necessary for `Hex` to be in scope in order
//! // for `serde`-generated code to use its `serialize` / `deserialize` methods.
//! use hex_buffer_serde::{Hex, HexForm};
//! # use serde_derive::*;
//! use core::{array::TryFromSliceError, convert::TryFrom};
//!
//! pub struct OurBuffer([u8; 8]);
//!
//! impl TryFrom<&[u8]> for OurBuffer {
//! type Error = TryFromSliceError;
//!
//! fn try_from(slice: &[u8]) -> Result<Self, Self::Error> {
//! // snip
//! # unimplemented!()
//! }
//! }
//!
//! impl AsRef<[u8]> for OurBuffer {
//! fn as_ref(&self) -> &[u8] {
//! &self.0
//! }
//! }
//!
//! #[derive(Serialize, Deserialize)]
//! pub struct Example {
//! #[serde(with = "HexForm::<OurBuffer>")]
//! buffer: OurBuffer,
//! // other fields...
//! }
//!
//! # fn main() {}
//! ```
// Documentation settings.
// Linter settings.
extern crate alloc;
pub use ;
pub use ;
compile_error!;
doctest!;