Skip to content

Block generation & buffering API design #31

@dhardy

Description

@dhardy

Status quo (derived from last release): we have

pub trait BlockRngCore {
    type Item;

    type Results: AsRef<[Self::Item]> + AsMut<[Self::Item]> + Default;

    fn generate(&mut self, results: &mut Self::Results);
}

pub trait CryptoBlockRng: BlockRngCore {}

#[derive(Clone)]
pub struct BlockRng<R: BlockRngCore> {
    results: R::Results,
    index: usize,
    pub core: R,
}

impl<R: BlockRngCore<Item = u32>> RngCore for BlockRng<R> {}

#[derive(Clone)]
pub struct BlockRng64<R: BlockRngCore + ?Sized> {
    results: R::Results,
    index: usize,
    half_used: bool, // true if only half of the previous result is used
    pub core: R,
}

impl<R: BlockRngCore<Item = u64>> RngCore for BlockRng64<R> {}

Issue: the results buffer is internal, which makes it hard to do things like implement serde support externally. #30 allows this; the result is somewhat ugly but acceptable in my opinion.

Issue: BlockRng64 shouldn't need to be separate from BlockRng (if we ignore the half_used optimisation), however Rust does not (yet) support deconflicting implementations over associated types (i.e. the two impls above are considered to conflict if both apply to BlockRng).

Issue: BlockRngCore::Results supports variable-sized buffer types like Vec<u32> which it really shouldn't.

Issue: BlockRngCore::Results requires a Default bound (for construction), but [u32; 64] doesn't (yet) support this. Both chacha20 and rand_chacha crates use a custom Array type to work around this. Rust should fix this in the future: rust-lang/rust#61415.

Issue: this is quite a lot of code for what is supposed to just be an RNG-interface crate.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions