Split Rng into RngCore and extension Rng: RngCore

This commit is contained in:
Diggory Hardy 2018-01-25 17:34:28 +00:00
parent 45717eb094
commit 60a6c72e2d
16 changed files with 115 additions and 72 deletions

View File

@ -9,7 +9,7 @@ mod distributions;
use std::mem::size_of;
use test::{black_box, Bencher};
use rand::{StdRng, Rng, NewRng};
use rand::{StdRng, RngCore, NewRng};
#[bench]
fn rand_f32(b: &mut Bencher) {

View File

@ -9,7 +9,7 @@ const BYTES_LEN: usize = 1024;
use std::mem::size_of;
use test::{black_box, Bencher};
use rand::{Rng, NewRng, StdRng, OsRng, JitterRng, EntropyRng};
use rand::{RngCore, Rng, NewRng, StdRng, OsRng, JitterRng, EntropyRng};
use rand::{XorShiftRng, Hc128Rng, IsaacRng, Isaac64Rng, ChaChaRng};
use rand::reseeding::ReseedingRng;

View File

@ -279,7 +279,7 @@ fn ziggurat<R: Rng, P, Z>(
#[cfg(test)]
mod tests {
use {Rng, Rand};
use {Rng, RngCore, Rand};
use impls;
use super::{RandSample, WeightedChoice, Weighted, Sample, IndependentSample};
@ -293,7 +293,7 @@ mod tests {
// 0, 1, 2, 3, ...
struct CountingRng { i: u32 }
impl Rng for CountingRng {
impl RngCore for CountingRng {
fn next_u32(&mut self) -> u32 {
self.i += 1;
self.i - 1

View File

@ -8,7 +8,7 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
//! Helper functions for implementing `Rng` functions.
//! Helper functions for implementing `RngCore` functions.
//!
//! For cross-platform reproducibility, these functions all use Little Endian:
//! least-significant part first. For example, `next_u64_via_u32` takes `u32`
@ -27,10 +27,10 @@ use core::ptr::copy_nonoverlapping;
use core::slice;
use core::cmp::min;
use core::mem::size_of;
use Rng;
use RngCore;
/// Implement `next_u64` via `next_u32`, little-endian order.
pub fn next_u64_via_u32<R: Rng+?Sized>(rng: &mut R) -> u64 {
pub fn next_u64_via_u32<R: RngCore + ?Sized>(rng: &mut R) -> u64 {
// Use LE; we explicitly generate one value before the next.
let x = rng.next_u32() as u64;
let y = rng.next_u32() as u64;
@ -59,12 +59,12 @@ macro_rules! fill_bytes_via {
}
/// Implement `fill_bytes` via `next_u32`, little-endian order.
pub fn fill_bytes_via_u32<R: Rng+?Sized>(rng: &mut R, dest: &mut [u8]) {
pub fn fill_bytes_via_u32<R: RngCore + ?Sized>(rng: &mut R, dest: &mut [u8]) {
fill_bytes_via!(rng, next_u32, 4, dest)
}
/// Implement `fill_bytes` via `next_u64`, little-endian order.
pub fn fill_bytes_via_u64<R: Rng+?Sized>(rng: &mut R, dest: &mut [u8]) {
pub fn fill_bytes_via_u64<R: RngCore + ?Sized>(rng: &mut R, dest: &mut [u8]) {
fill_bytes_via!(rng, next_u64, 8, dest)
}
@ -158,12 +158,12 @@ pub fn fill_via_u64_chunks(src: &[u64], dest: &mut [u8]) -> (usize, usize) {
}
/// Implement `next_u32` via `fill_bytes`, little-endian order.
pub fn next_u32_via_fill<R: Rng+?Sized>(rng: &mut R) -> u32 {
pub fn next_u32_via_fill<R: RngCore + ?Sized>(rng: &mut R) -> u32 {
impl_uint_from_fill!(rng, u32, 4)
}
/// Implement `next_u64` via `fill_bytes`, little-endian order.
pub fn next_u64_via_fill<R: Rng+?Sized>(rng: &mut R) -> u64 {
pub fn next_u64_via_fill<R: RngCore + ?Sized>(rng: &mut R) -> u64 {
impl_uint_from_fill!(rng, u64, 8)
}

View File

@ -16,7 +16,7 @@
//! Non-physical true random number generator based on timing jitter.
use {Rng, Error, ErrorKind, impls};
use {RngCore, Error, ErrorKind, impls};
use core::{fmt, mem, ptr};
#[cfg(feature="std")]
@ -746,7 +746,7 @@ fn black_box<T>(dummy: T) -> T {
}
}
impl Rng for JitterRng {
impl RngCore for JitterRng {
fn next_u32(&mut self) -> u32 {
// We want to use both parts of the generated entropy
if self.data_half_used {

View File

@ -355,7 +355,22 @@ pub trait Rand : Sized {
}
/// A random number generator.
pub trait Rng {
///
/// This trait encapsulates the low-level functionality common to all
/// generators, and is the "back end", to be implemented by generators.
/// Several extension traits exist:
///
/// * [`Rng`] provides high-level generic functionality built on top of
/// `RngCore`
/// * [`SeedableRng`] is another "back end" trait covering creation and
/// seeding of algorithmic RNGs (PRNGs)
/// * [`NewRng`] is a high-level trait providing a convenient way to create
/// freshly-seeded PRNGs
///
/// [`Rng`]: trait.Rng.html
/// [`SeedableRng`]: trait.SeedableRng.html
/// [`NewRng`]: trait.NewRng.html
pub trait RngCore {
/// Return the next random `u32`.
///
/// Implementations of this trait must implement at least one of
@ -457,7 +472,7 @@ pub trait Rng {
/// # Example
///
/// ```rust
/// use rand::{thread_rng, Rng};
/// use rand::{thread_rng, RngCore};
///
/// let mut v = [0u8; 13579];
/// thread_rng().fill_bytes(&mut v);
@ -478,11 +493,26 @@ pub trait Rng {
/// Other than error handling, this method is identical to [`fill_bytes`], and
/// has a default implementation simply wrapping [`fill_bytes`].
///
/// [`fill_bytes`]: trait.Rng.html#method.fill_bytes
/// [`fill_bytes`]: trait.RngCore.html#method.fill_bytes
fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error> {
Ok(self.fill_bytes(dest))
}
}
/// An automatically-implemented extension trait on [`RngCore`] providing high-level
/// generic methods for sampling values and other convenience methods.
///
/// Users should "use" this trait to enable its extension methods on [`RngCore`]
/// or require this type directly (i.e. `<R: Rng>`). Since `Rng`
/// extends `RngCore` and every `RngCore` implements `Rng`, usage of the two
/// traits is somewhat interchangeable.
///
/// This functionality is provided as an extension trait to allow separation
/// between the backend (the [`RngCore`] providing randomness) and the front-end
/// (converting that randomness to the desired type and distribution).
///
/// [`RngCore`]: trait.RngCore.html
pub trait Rng: RngCore {
/// Return a random value of a `Rand` type.
///
/// # Example
@ -543,7 +573,7 @@ pub trait Rng {
/// println!("{}", m);
/// ```
fn gen_range<T: PartialOrd + SampleRange>(&mut self, low: T, high: T) -> T where Self: Sized {
assert!(low < high, "Rng.gen_range called with low >= high");
assert!(low < high, "Rng::gen_range called with low >= high");
Range::new(low, high).ind_sample(self)
}
@ -637,7 +667,9 @@ pub trait Rng {
}
}
impl<'a, R: Rng + ?Sized> Rng for &'a mut R {
impl<R: RngCore> Rng for R {}
impl<'a, R: RngCore + ?Sized> RngCore for &'a mut R {
#[inline]
fn next_u32(&mut self) -> u32 {
(**self).next_u32()
@ -670,7 +702,7 @@ impl<'a, R: Rng + ?Sized> Rng for &'a mut R {
}
#[cfg(any(feature="std", feature="alloc"))]
impl<R: Rng + ?Sized> Rng for Box<R> {
impl<R: RngCore + ?Sized> RngCore for Box<R> {
#[inline]
fn next_u32(&mut self) -> u32 {
(**self).next_u32()
@ -714,7 +746,7 @@ pub struct Generator<'a, T, R:'a> {
_marker: marker::PhantomData<fn() -> T>,
}
impl<'a, T: Rand, R: Rng> Iterator for Generator<'a, T, R> {
impl<'a, T: Rand, R: RngCore> Iterator for Generator<'a, T, R> {
type Item = T;
fn next(&mut self) -> Option<T> {
@ -733,7 +765,7 @@ pub struct AsciiGenerator<'a, R:'a> {
rng: &'a mut R,
}
impl<'a, R: Rng> Iterator for AsciiGenerator<'a, R> {
impl<'a, R: RngCore> Iterator for AsciiGenerator<'a, R> {
type Item = char;
fn next(&mut self) -> Option<char> {
@ -747,7 +779,15 @@ impl<'a, R: Rng> Iterator for AsciiGenerator<'a, R> {
/// A random number generator that can be explicitly seeded.
///
/// Each pseudo-random number generator (PRNG) should implement this.
/// This trait encapsulates the low-level functionality common to all
/// pseudo-random number generators (PRNGs, or algorithmic generators).
///
/// Normally users should use the [`NewRng`] extension trait, excepting when a
/// fixed seed must be used, in which case usage of [`SeedableRng::from_seed`]
/// is recommended.
///
/// [`NewRng`]: trait.NewRng.html
/// [`SeedableRng::from_seed`]: #tymethod.from_seed
pub trait SeedableRng: Sized {
/// Seed type, which is restricted to types mutably-dereferencable as `u8`
/// arrays (we recommend `[u8; N]` for some `N`).
@ -777,8 +817,12 @@ pub trait SeedableRng: Sized {
/// Create a new PRNG seeded from another `Rng`.
///
/// This is the recommended way to initialize PRNGs. The [`NewRng`] trait
/// provides a convenient new method based on `from_rng`.
/// This is the recommended way to initialize PRNGs with fresh entropy. The
/// [`NewRng`] trait provides a convenient new method based on `from_rng`.
///
/// Usage of this method is not recommended when reproducibility is required
/// since implementing PRNGs are not required to fix Endianness and are
/// allowed to modify implementations in new releases.
///
/// It is important to use a good source of randomness to initialize the
/// PRNG. Cryptographic PRNG may be rendered insecure when seeded from a
@ -799,12 +843,11 @@ pub trait SeedableRng: Sized {
///
/// PRNG implementations are allowed to assume that a good RNG is provided
/// for seeding, and that it is cryptographically secure when appropriate.
/// There are no reproducibility requirements like endianness conversion.
///
/// [`NewRng`]: trait.NewRng.html
/// [`OsRng`]: os/struct.OsRng.html
/// [`XorShiftRng`]: prng/xorshift/struct.XorShiftRng.html
fn from_rng<R: Rng>(rng: &mut R) -> Result<Self, Error> {
fn from_rng<R: RngCore>(rng: &mut R) -> Result<Self, Error> {
let mut seed = Self::Seed::default();
rng.try_fill_bytes(seed.as_mut())?;
Ok(Self::from_seed(seed))
@ -816,7 +859,7 @@ pub trait SeedableRng: Sized {
/// pseudo-random number generators (PRNGs).
///
/// This is the recommended way to create PRNGs, unless a deterministic seed is
/// desired (in which case `SeedableRng::from_seed` should be used).
/// desired (in which case [`SeedableRng::from_seed`] should be used).
///
/// Note: this trait is automatically implemented for any PRNG implementing
/// [`SeedableRng`] and is not intended to be implemented by users.
@ -831,6 +874,7 @@ pub trait SeedableRng: Sized {
/// ```
///
/// [`SeedableRng`]: trait.SeedableRng.html
/// [`SeedableRng::from_seed`]: trait.SeedableRng.html#tymethod.from_seed
#[cfg(feature="std")]
pub trait NewRng: SeedableRng {
/// Creates a new instance, automatically seeded with fresh entropy.
@ -894,7 +938,7 @@ pub struct Closed01<F>(pub F);
#[derive(Clone, Debug)]
pub struct StdRng(IsaacWordRng);
impl Rng for StdRng {
impl RngCore for StdRng {
fn next_u32(&mut self) -> u32 {
self.0.next_u32()
}
@ -989,7 +1033,7 @@ pub fn thread_rng() -> ThreadRng {
}
#[cfg(feature="std")]
impl Rng for ThreadRng {
impl RngCore for ThreadRng {
#[inline]
fn next_u32(&mut self) -> u32 {
self.rng.borrow_mut().next_u32()
@ -1053,7 +1097,7 @@ impl EntropyRng {
}
#[cfg(feature="std")]
impl Rng for EntropyRng {
impl RngCore for EntropyRng {
fn next_u32(&mut self) -> u32 {
impls::next_u32_via_fill(self)
}
@ -1222,13 +1266,13 @@ mod test {
use impls;
#[cfg(feature="std")]
use super::{random, thread_rng, EntropyRng};
use super::{Rng, SeedableRng, StdRng};
use super::{RngCore, Rng, SeedableRng, StdRng};
#[cfg(feature="alloc")]
use alloc::boxed::Box;
pub struct TestRng<R> { inner: R }
impl<R: Rng> Rng for TestRng<R> {
impl<R: RngCore> RngCore for TestRng<R> {
fn next_u32(&mut self) -> u32 {
self.inner.next_u32()
}
@ -1259,7 +1303,7 @@ mod test {
}
struct ConstRng { i: u64 }
impl Rng for ConstRng {
impl RngCore for ConstRng {
fn next_u32(&mut self) -> u32 { self.i as u32 }
fn next_u64(&mut self) -> u64 { self.i }
@ -1398,7 +1442,7 @@ mod test {
fn test_rng_trait_object() {
let mut rng = rng(109);
{
let mut r = &mut rng as &mut Rng;
let mut r = &mut rng as &mut RngCore;
r.next_u32();
let r2 = &mut r;
r2.gen::<i32>();
@ -1409,7 +1453,7 @@ mod test {
assert_eq!(r2.gen_range(0, 1), 0);
}
{
let mut r = Box::new(rng) as Box<Rng>;
let mut r = Box::new(rng) as Box<RngCore>;
r.next_u32();
r.gen::<i32>();
let mut v = [1, 1, 1];

View File

@ -17,7 +17,7 @@ use std::io::Read;
#[allow(unused)] use std::path::Path;
#[allow(unused)] use std::sync::{Once, Mutex, ONCE_INIT};
use {Rng, Error, ErrorKind, impls};
use {RngCore, Error, ErrorKind, impls};
/// A random number generator that retrieves randomness straight from
/// the operating system.
@ -54,7 +54,7 @@ impl OsRng {
}
}
impl Rng for OsRng {
impl RngCore for OsRng {
fn next_u32(&mut self) -> u32 {
impls::next_u32_via_fill(self)
}
@ -577,7 +577,6 @@ mod imp {
#[cfg(all(target_arch = "wasm32", not(target_os = "emscripten")))]
mod imp {
use std::io;
use Rng;
#[derive(Debug)]
pub struct OsRng;
@ -595,7 +594,7 @@ mod imp {
#[cfg(test)]
mod test {
use std::sync::mpsc::channel;
use Rng;
use RngCore;
use OsRng;
use std::thread;

View File

@ -11,7 +11,7 @@
//! The ChaCha random number generator.
use core::fmt;
use {Rng, SeedableRng};
use {RngCore, SeedableRng};
use {impls, le};
const SEED_WORDS: usize = 8; // 8 words for the 256-bit key
@ -108,7 +108,7 @@ impl ChaChaRng {
/// # Examples
///
/// ```rust
/// use rand::{Rng, ChaChaRng};
/// use rand::{RngCore, ChaChaRng};
///
/// let mut ra = ChaChaRng::new_unseeded();
/// println!("{:?}", ra.next_u32());
@ -139,7 +139,7 @@ impl ChaChaRng {
/// # Examples
///
/// ```rust
/// use rand::{Rng, ChaChaRng};
/// use rand::{RngCore, ChaChaRng};
///
/// let mut rng1 = ChaChaRng::new_unseeded(); // Use `ChaChaRng::new()` or
/// // `ChaChaRng::from_rng()`
@ -170,7 +170,7 @@ impl ChaChaRng {
/// # Examples
///
/// ```rust
/// use rand::{Rng, ChaChaRng};
/// use rand::{RngCore, ChaChaRng};
///
/// let mut rng = ChaChaRng::new_unseeded(); // Use `ChaChaRng::new()` or
/// // `ChaChaRng::from_rng()`
@ -215,7 +215,7 @@ impl ChaChaRng {
}
}
impl Rng for ChaChaRng {
impl RngCore for ChaChaRng {
#[inline]
fn next_u32(&mut self) -> u32 {
// Using a local variable for `index`, and checking the size avoids a
@ -272,7 +272,7 @@ impl SeedableRng for ChaChaRng {
#[cfg(test)]
mod test {
use {Rng, SeedableRng};
use {RngCore, SeedableRng};
use super::ChaChaRng;
#[test]

View File

@ -11,7 +11,7 @@
//! The HC-128 random number generator.
use core::{fmt, slice};
use {Rng, SeedableRng};
use {RngCore, SeedableRng};
use {impls, le};
const SEED_WORDS: usize = 8; // 128 bit key followed by 128 bit iv
@ -290,7 +290,7 @@ impl Hc128 {
}
}
impl Rng for Hc128Rng {
impl RngCore for Hc128Rng {
#[inline]
fn next_u32(&mut self) -> u32 {
if self.index >= 16 {
@ -408,7 +408,7 @@ impl SeedableRng for Hc128Rng {
#[cfg(test)]
mod test {
use {Rng, SeedableRng};
use {RngCore, SeedableRng};
use super::Hc128Rng;
#[test]

View File

@ -13,7 +13,7 @@
use core::{fmt, slice};
use core::num::Wrapping as w;
use {Rng, SeedableRng, Error};
use {RngCore, SeedableRng, Error};
use {impls, le};
#[allow(non_camel_case_types)]
@ -213,7 +213,7 @@ impl IsaacRng {
}
}
impl Rng for IsaacRng {
impl RngCore for IsaacRng {
#[inline]
fn next_u32(&mut self) -> u32 {
// Using a local variable for `index`, and checking the size avoids a
@ -347,7 +347,7 @@ impl SeedableRng for IsaacRng {
init(seed_extended, 2)
}
fn from_rng<R: Rng>(rng: &mut R) -> Result<Self, Error> {
fn from_rng<R: RngCore>(rng: &mut R) -> Result<Self, Error> {
// Custom `from_rng` implementation that fills a seed with the same size
// as the entire state.
let mut seed = [w(0u32); RAND_SIZE];
@ -367,7 +367,7 @@ impl SeedableRng for IsaacRng {
#[cfg(test)]
mod test {
use {Rng, SeedableRng};
use {RngCore, SeedableRng};
use super::IsaacRng;
#[test]

View File

@ -13,7 +13,7 @@
use core::{fmt, slice};
use core::num::Wrapping as w;
use {Rng, SeedableRng, Error};
use {RngCore, SeedableRng, Error};
use {impls, le};
#[allow(non_camel_case_types)]
@ -199,7 +199,7 @@ impl Isaac64Rng {
}
}
impl Rng for Isaac64Rng {
impl RngCore for Isaac64Rng {
#[inline]
fn next_u32(&mut self) -> u32 {
// Using a local variable for `index`, and checking the size avoids a
@ -322,7 +322,7 @@ impl SeedableRng for Isaac64Rng {
init(seed_extended, 2)
}
fn from_rng<R: Rng>(rng: &mut R) -> Result<Self, Error> {
fn from_rng<R: RngCore>(rng: &mut R) -> Result<Self, Error> {
// Custom `from_rng` implementation that fills a seed with the same size
// as the entire state.
let mut seed = [w(0u64); RAND_SIZE];
@ -342,7 +342,7 @@ impl SeedableRng for Isaac64Rng {
#[cfg(test)]
mod test {
use {Rng, SeedableRng};
use {RngCore, SeedableRng};
use super::Isaac64Rng;
#[test]

View File

@ -12,7 +12,7 @@
use core::num::Wrapping as w;
use core::{fmt, slice};
use {Rng, SeedableRng, Error};
use {RngCore, SeedableRng, Error};
use {impls, le};
/// An Xorshift[1] random number
@ -58,7 +58,7 @@ impl XorShiftRng {
}
}
impl Rng for XorShiftRng {
impl RngCore for XorShiftRng {
#[inline]
fn next_u32(&mut self) -> u32 {
let x = self.x;
@ -102,7 +102,7 @@ impl SeedableRng for XorShiftRng {
}
}
fn from_rng<R: Rng>(rng: &mut R) -> Result<Self, Error> {
fn from_rng<R: RngCore>(rng: &mut R) -> Result<Self, Error> {
let mut seed_u32 = [0u32; 4];
loop {
unsafe {
@ -125,7 +125,7 @@ impl SeedableRng for XorShiftRng {
#[cfg(test)]
mod tests {
use {Rng, SeedableRng};
use {RngCore, SeedableRng};
use super::XorShiftRng;
#[test]

View File

@ -255,13 +255,13 @@ impl<T: SeedableRng> Rand for T {
#[cfg(test)]
mod tests {
use impls;
use {Rng, Open01, Closed01};
use {RngCore, Rng, Open01, Closed01};
const EPSILON32: f32 = ::core::f32::EPSILON;
const EPSILON64: f64 = ::core::f64::EPSILON;
struct ConstantRng(u64);
impl Rng for ConstantRng {
impl RngCore for ConstantRng {
fn next_u32(&mut self) -> u32 {
let ConstantRng(v) = *self;
v as u32

View File

@ -12,7 +12,7 @@
use std::io::Read;
use {Rng, Error, ErrorKind, impls};
use {RngCore, Error, ErrorKind, impls};
/// An RNG that reads random bytes straight from a `Read`. This will
@ -45,7 +45,7 @@ impl<R: Read> ReadRng<R> {
}
}
impl<R: Read> Rng for ReadRng<R> {
impl<R: Read> RngCore for ReadRng<R> {
fn next_u32(&mut self) -> u32 {
impls::next_u32_via_fill(self)
}
@ -70,7 +70,7 @@ impl<R: Read> Rng for ReadRng<R> {
#[cfg(test)]
mod test {
use super::ReadRng;
use Rng;
use RngCore;
#[test]
fn test_reader_rng_u64() {

View File

@ -11,7 +11,7 @@
//! A wrapper around another PRNG that reseeds it after it
//! generates a certain number of random bytes.
use {Rng, SeedableRng, Error, ErrorKind};
use {RngCore, SeedableRng, Error, ErrorKind};
/// A wrapper around any PRNG which reseeds the underlying PRNG after it has
/// generated a certain number of random bytes.
@ -62,7 +62,7 @@ pub struct ReseedingRng<R, Rsdr> {
bytes_until_reseed: i64,
}
impl<R: Rng+SeedableRng, Rsdr: Rng> ReseedingRng<R, Rsdr> {
impl<R: RngCore + SeedableRng, Rsdr: RngCore> ReseedingRng<R, Rsdr> {
/// Create a new `ReseedingRng` with the given parameters.
///
/// # Arguments
@ -143,7 +143,7 @@ impl<R: Rng+SeedableRng, Rsdr: Rng> ReseedingRng<R, Rsdr> {
}
}
impl<R: Rng+SeedableRng, Rsdr: Rng> Rng for ReseedingRng<R, Rsdr> {
impl<R: RngCore + SeedableRng, Rsdr: RngCore> RngCore for ReseedingRng<R, Rsdr> {
fn next_u32(&mut self) -> u32 {
let value = self.rng.next_u32();
self.bytes_until_reseed -= 4;
@ -184,13 +184,13 @@ impl<R: Rng+SeedableRng, Rsdr: Rng> Rng for ReseedingRng<R, Rsdr> {
mod test {
use {impls, le};
use super::{ReseedingRng};
use {SeedableRng, Rng, Error};
use {SeedableRng, RngCore, Error};
struct Counter {
i: u32
}
impl Rng for Counter {
impl RngCore for Counter {
fn next_u32(&mut self) -> u32 {
self.i += 1;
// very random
@ -215,7 +215,7 @@ mod test {
#[derive(Debug, Clone)]
struct ResetCounter;
impl Rng for ResetCounter {
impl RngCore for ResetCounter {
fn next_u32(&mut self) -> u32 { unimplemented!() }
fn next_u64(&mut self) -> u64 { unimplemented!() }
fn fill_bytes(&mut self, _dest: &mut [u8]) { unimplemented!() }

View File

@ -227,7 +227,7 @@ fn sample_indices_cache<R>(
#[cfg(test)]
mod test {
use super::*;
use {XorShiftRng, SeedableRng};
use {XorShiftRng, RngCore, SeedableRng};
#[cfg(not(feature="std"))]
use alloc::Vec;