entropic 0.1.1

Traits for converting Rust data structures to/from unstructured bytes
Documentation
#[cfg(feature = "alloc")]
use core::ffi::CStr;

use core::ops::RangeInclusive;

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

/// A sink for writing entropy bytes to when converting an [`Entropic`] object into entropy.
#[derive(Clone)]
pub struct Sink<'a, I: Iterator<Item = &'a mut u8>, E: EntropyScheme> {
    iter: I,
    scheme: E,
}

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

    /// Converts the passed `entropic` value to bytes and writes them to the sink.
    #[inline]
    pub fn put_entropic<T: Entropic>(&mut self, entropic: &T) -> Result<usize, EntropicError> {
        entropic.to_entropy_sink(self)
    }

    /// Converts the value within the given range into bytes and writes them to the sink.
    #[inline]
    pub fn put_uniform_range<T: Int>(
        &mut self,
        range: RangeInclusive<T>,
        value: T,
    ) -> Result<usize, EntropicError> {
        self.scheme.put_uniform_range(&mut self.iter, range, value)
    }

    /// Converts the value within the given ranges into bytes and writes them to the sink.
    #[inline]
    pub fn put_uniform_ranges<T: Int, const L: usize>(
        &mut self,
        ranges: &[RangeInclusive<T>; L],
        value: T,
    ) -> Result<usize, EntropicError> {
        self.scheme
            .put_uniform_ranges(&mut self.iter, ranges, value)
    }

    /// Converts the length value within the given bound into bytes and writes them to the sink.
    #[inline]
    pub fn put_bounded_len(
        &mut self,
        range: RangeInclusive<usize>,
        value: usize,
    ) -> Result<usize, EntropicError> {
        self.scheme.put_bounded_len(&mut self.iter, range, value)
    }

    /// Converts the length value into bytes and writes them to the sink.
    #[inline]
    pub fn put_unbounded_len(&mut self, value: usize) -> Result<usize, EntropicError> {
        self.scheme.put_unbounded_len(&mut self.iter, value)
    }

    /// Converts the boolean value into bytes and writes them to the sink.
    #[inline]
    pub fn put_bool(&mut self, value: bool) -> Result<usize, EntropicError> {
        self.scheme.put_bool(&mut self.iter, value)
    }

    /// Converts the char value into bytes and writes them to the sink.
    #[inline]
    pub fn put_char(&mut self, value: char) -> Result<usize, EntropicError> {
        self.scheme.put_char(&mut self.iter, value)
    }

    /// Converts the String value into bytes and writes them to the sink.
    #[cfg(feature = "alloc")]
    #[inline]
    pub fn put_string(&mut self, value: &str) -> Result<usize, EntropicError> {
        self.scheme.put_string(&mut self.iter, value)
    }

    /// Converts the CString value into bytes and writes them to the sink.
    #[cfg(feature = "alloc")]
    #[inline]
    pub fn put_cstring(&mut self, value: &CStr) -> Result<usize, EntropicError> {
        self.scheme.put_cstring(&mut self.iter, value)
    }

    /// Writes the byte value to the sink.
    #[inline]
    pub fn put_byte(&mut self, value: u8) -> Result<usize, EntropicError> {
        self.scheme.put_byte(&mut self.iter, value)
    }

    /// Writes the slice of bytes to the sink.
    #[inline]
    pub fn put_slice(&mut self, slice: &[u8]) -> Result<usize, EntropicError> {
        self.scheme.put_slice(&mut self.iter, slice)
    }

    /// Writes the array of bytes to the sink.
    #[inline]
    pub fn put_bytearray<const T: usize>(
        &mut self,
        value: [u8; T],
    ) -> Result<usize, EntropicError> {
        self.scheme.put_bytearray(&mut self.iter, value)
    }

    /// Converts the Option/Result choice into bytes and writes it to the sink.
    #[inline]
    pub fn put_optional(&mut self, value: bool) -> Result<usize, EntropicError> {
        self.scheme.put_optional(&mut self.iter, value)
    }
}

/// An iterable type that can be used as a sink for writing entropy bytes to.
pub trait AsSink<'a> {
    type I: Iterator<Item = &'a mut u8>;

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

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

    #[inline]
    fn to_sink<E: EntropyScheme>(self) -> Sink<'a, Self::I, E> {
        Sink::new(self.into_iter())
    }
}