entropic 0.1.1

Traits for converting Rust data structures to/from unstructured bytes
Documentation
#![cfg_attr(not(feature = "std"), no_std)]

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

#[doc(hidden)]
pub mod prelude;
pub mod scheme;

mod entropic;
mod sink;
mod source;

use core::{fmt, ops};

#[cfg(feature = "derive")]
pub use entropic_derive::Entropic;

pub use crate::entropic::*;
pub use sink::*;
pub use source::*;

/// An error in converting to/from entropy.
#[derive(Debug)]
#[non_exhaustive]
pub enum EntropicError {
    /// The byte range of the [`Source`]/[`Sink`] wasn't long enough to cover the number of bytes
    /// produced or consumed by the entropy call.
    InsufficientBytes,
    /// The range passed into an entropy function (such as for [`get_uniform_range()`](scheme::EntropyScheme::get_uniform_range)
    /// or [`put_bounded_len()`](scheme::EntropyScheme::put_bounded_len)) was not an element in that range.
    InvalidRange,
    /// The value passed into a range (such as for [`put_uniform_range()`](scheme::EntropyScheme::put_uniform_range)
    /// or [`put_bounded_len()`](scheme::EntropyScheme::put_bounded_len)) was not an element in that range.
    ValueOutOfRange,
    /// An attempt to access a mutex-locked data structure failed during entropic operations.
    PoisonedLock,
    /// An internal invariant within `entropic` failed.
    Internal,
}

mod private {
    /// A subtrait that indicates the trait is sealed against implementation by any more types.
    pub trait Sealed {}

    macro_rules! impl_sealed {
        ( $( $ty:ty),* ) => {
            $(
                impl Sealed for $ty { }
            )*
        }
    }

    impl_sealed!(i8, i16, i32, i64, i128, isize, u8, u16, u32, u64, u128, usize);
}

// Credit for most of the `Int` trait code goes to the authors of the `arbitrary` crate
// Licensed under MIT/Apache2

/// A trait that is implemented for all of the primitive integers:
///
/// * `u8`
/// * `u16`
/// * `u32`
/// * `u64`
/// * `u128`
/// * `usize`
/// * `i8`
/// * `i16`
/// * `i32`
/// * `i64`
/// * `i128`
/// * `isize`
///
/// Don't implement this trait yourself.
pub trait Int:
    private::Sealed
    + Copy
    + fmt::Debug
    + fmt::Display
    + PartialOrd
    + Ord
    + ops::Sub<Self, Output = Self>
    + ops::Rem<Self, Output = Self>
    + ops::Shr<Self, Output = Self>
    + ops::Shr<usize, Output = Self>
    + ops::Shl<usize, Output = Self>
    + ops::BitOr<Self, Output = Self>
{
    #[doc(hidden)]
    type Unsigned: Int;

    #[doc(hidden)]
    const ZERO: Self;

    #[doc(hidden)]
    const ONE: Self;

    #[doc(hidden)]
    const MIN: Self;

    #[doc(hidden)]
    const MAX: Self;

    #[doc(hidden)]
    fn checked_ilog2(self) -> Option<u32>;

    #[doc(hidden)]
    fn from_u8(b: u8) -> Self;

    #[doc(hidden)]
    fn to_u8(self) -> u8;

    #[doc(hidden)]
    fn from_usize(u: usize) -> Self;

    #[doc(hidden)]
    fn checked_add(self, rhs: Self) -> Option<Self>;

    #[doc(hidden)]
    fn checked_sub(self, rhs: Self) -> Option<Self>;

    #[doc(hidden)]
    fn wrapping_add(self, rhs: Self) -> Self;

    #[doc(hidden)]
    fn wrapping_sub(self, rhs: Self) -> Self;

    #[doc(hidden)]
    fn to_unsigned(self) -> Self::Unsigned;

    #[doc(hidden)]
    fn from_unsigned(unsigned: Self::Unsigned) -> Self;
}

macro_rules! impl_int {
    ( $( $ty:ty : $unsigned_ty: ty),* ) => {
        $(
            impl Int for $ty {
                type Unsigned = $unsigned_ty;

                const ZERO: Self = 0;

                const ONE: Self = 1;

                const MIN: Self = Self::MIN;

                const MAX: Self = Self::MAX;

                fn checked_ilog2(self) -> Option<u32> {
                    self.checked_ilog2()
                }

                fn from_u8(b: u8) -> Self {
                    b as Self
                }

                fn to_u8(self) -> u8 {
                    // SAFETY: cannot panic--takes the first element of a non-empty array
                    // Note that this is checked at compile time as well
                    self.to_le_bytes()[0]
                }

                fn from_usize(u: usize) -> Self {
                    u as Self
                }

                fn checked_add(self, rhs: Self) -> Option<Self> {
                    <$ty>::checked_add(self, rhs)
                }

                fn checked_sub(self, rhs: Self) -> Option<Self> {
                    <$ty>::checked_sub(self, rhs)
                }

                fn wrapping_add(self, rhs: Self) -> Self {
                    <$ty>::wrapping_add(self, rhs)
                }

                fn wrapping_sub(self, rhs: Self) -> Self {
                    <$ty>::wrapping_sub(self, rhs)
                }

                fn to_unsigned(self) -> Self::Unsigned {
                    self as $unsigned_ty
                }

                fn from_unsigned(unsigned: $unsigned_ty) -> Self {
                    unsigned as Self
                }
            }
        )*
    }
}

impl_int! {
    u8: u8,
    u16: u16,
    u32: u32,
    u64: u64,
    u128: u128,
    usize: usize,
    i8: u8,
    i16: u16,
    i32: u32,
    i64: u64,
    i128: u128,
    isize: usize
}