entropic 0.1.1

Traits for converting Rust data structures to/from unstructured bytes
Documentation
use core::ops::RangeInclusive;

#[cfg(feature = "alloc")]
use alloc::{ffi::CString, string::String};

use crate::prelude::*;
use crate::Int;

/// A source for reading entropy bytes from when constructing an [`Entropic`] object.
pub struct Source<'a, I: Iterator<Item = &'a u8>, E: EntropyScheme> {
    pub(crate) iter: I,
    scheme: E,
}

impl<'a, I: Iterator<Item = &'a u8>, E: EntropyScheme> Source<'a, I, E> {
    /// Constructs a new entropy source from the given iterator.
    #[inline]
    pub fn new(iter: I) -> Self {
        Self {
            iter,
            scheme: E::default(),
        }
    }

    /// Converts the passed bytes to an entropy object.
    #[inline]
    pub fn get_entropic<T: Entropic>(&mut self) -> Result<T, EntropicError> {
        T::from_entropy_source(self)
    }

    /// Constructs a value within the given range from entropy source bytes.
    #[inline]
    pub fn get_uniform_range<T: Int>(
        &mut self,
        range: RangeInclusive<T>,
    ) -> Result<T, EntropicError> {
        self.scheme.get_uniform_range(&mut self.iter, range)
    }

    /// Constructs a value within the given ranges from entropy source bytes.
    #[inline]
    pub fn get_uniform_ranges<T: Int, const L: usize>(
        &mut self,
        ranges: &[RangeInclusive<T>; L],
    ) -> Result<T, EntropicError> {
        self.scheme.get_uniform_ranges(&mut self.iter, ranges)
    }

    /// Constructs a length value within the given bound from entropy source bytes.
    #[inline]
    pub fn get_bounded_len(
        &mut self,
        range: RangeInclusive<usize>,
    ) -> Result<usize, EntropicError> {
        self.scheme.get_bounded_len(&mut self.iter, range)
    }

    /// Constructs a length value from entropy source bytes.
    #[inline]
    pub fn get_unbounded_len(&mut self) -> Result<usize, EntropicError> {
        self.scheme.get_unbounded_len(&mut self.iter)
    }

    /// Constructs a boolean value from entropy source bytes.
    #[inline]
    pub fn get_bool(&mut self) -> Result<bool, EntropicError> {
        self.scheme.get_bool(&mut self.iter)
    }

    /// Constructs a char value from entropy source bytes.
    #[inline]
    pub fn get_char(&mut self) -> Result<char, EntropicError> {
        self.scheme.get_char(&mut self.iter)
    }

    /// Constructs a string value from entropy source bytes.
    #[cfg(feature = "alloc")]
    #[inline]
    pub fn get_string(&mut self) -> Result<String, EntropicError> {
        self.scheme.get_string(&mut self.iter)
    }

    /// Constructs a cstring value from entropy source bytes.
    #[cfg(feature = "alloc")]
    #[inline]
    pub fn get_cstring(&mut self) -> Result<CString, EntropicError> {
        self.scheme.get_cstring(&mut self.iter)
    }

    /// Constructs a byte value from entropy source bytes.
    #[inline]
    pub fn get_byte(&mut self) -> Result<u8, EntropicError> {
        self.scheme.get_byte(&mut self.iter)
    }

    /// Constructs a slice of bytes from entropy source bytes.
    #[inline]
    pub fn get_slice(&mut self, slice: &mut [u8]) -> Result<(), EntropicError> {
        self.scheme.get_slice(&mut self.iter, slice)
    }

    /// Constructs an array of bytes from entropy source bytes.
    #[inline]
    pub fn get_bytearray<const T: usize>(&mut self) -> Result<[u8; T], EntropicError> {
        self.scheme.get_bytearray(&mut self.iter)
    }

    /// Chooses an Option/Result choice from entropy source bytes.
    #[inline]
    pub fn get_optional(&mut self) -> Result<bool, EntropicError> {
        self.scheme.get_optional(&mut self.iter)
    }
}

// A source from which entropy can be drawn to create an object.
pub trait AsSource<'a> {
    type I: Iterator<Item = &'a u8>;

    /// Converts the given type into a [`Source`] to read entropy bytes from.
    fn to_source<E: EntropyScheme>(self) -> Source<'a, Self::I, E>;
}

// Implement `AsSource` for anything that is a cloneable iterator
impl<'a, T: IntoIterator<Item = &'a u8> + Clone> AsSource<'a> for T {
    type I = T::IntoIter;

    #[inline]
    fn to_source<E: EntropyScheme>(self) -> Source<'a, Self::I, E> {
        Source {
            iter: self.into_iter(),
            scheme: E::default(),
        }
    }
}