#![cfg(feature = "proptest")]
use core::fmt::Debug;
use core::num::{NonZeroUsize, Wrapping};
use core::ops::Range;
extern crate alloc;
use alloc::vec::Vec;
use proptest::prelude::*;
use proptest::num::usize::{Any as AnyUsize, ANY as ANY_USIZE};
use proptest::strategy::Map as PropMap;
use crate::RingBuffer;
use crate::prop::BufferStrategy;
use crate::storage::{ArrayStorage, HeapStorage};
use super::MaskingBuffer;
impl<T, const N: usize> Arbitrary for MaskingBuffer<ArrayStorage<T, N>>
where T: Arbitrary + Debug {
type Parameters = T::Parameters;
type Strategy = ArrayStrategy<T::Strategy, N>;
fn arbitrary_with(args: Self::Parameters) -> Self::Strategy {
arb_array(T::arbitrary_with(args))
}
}
impl<T: Arbitrary + Debug> Arbitrary for MaskingBuffer<HeapStorage<T>> {
type Parameters = T::Parameters;
type Strategy = HeapStrategy<T::Strategy>;
fn arbitrary_with(args: Self::Parameters) -> Self::Strategy {
arb_heap(T::arbitrary_with(args))
}
}
pub type ArrayStrategy<T, const N: usize> = PropMap<
(AnyUsize, BufferStrategy<Just<NonZeroUsize>, T>),
fn (
(usize, (NonZeroUsize, Vec<<T as Strategy>::Value>))
) -> MaskingBuffer<ArrayStorage<<T as Strategy>::Value, N>>,
>;
pub fn arb_array<T: Strategy, const N: usize>(
arb_item: T
) -> ArrayStrategy<T, N> {
fn mapper<T: Strategy, const N: usize>(
(cur, (cap, items)): (usize, (NonZeroUsize, Vec<T::Value>))
) -> MaskingBuffer<ArrayStorage<T::Value, N>> {
assert_eq!(cap.get(), N);
let mut buffer = MaskingBuffer {
cur: Wrapping(cur), len: 0,
data: ArrayStorage::new(),
};
for item in items.into_iter() {
assert!(buffer.enqueue(item).is_none());
}
buffer
}
assert!(N.is_power_of_two(),
"`MaskingBuffer` requires a power-of-two capacity!");
let capacity = Just(NonZeroUsize::new(N).unwrap());
(ANY_USIZE, BufferStrategy::new(capacity, arb_item))
.prop_map(mapper::<T, N> as _)
}
pub fn arb_array_paired<T: Strategy, const N: usize>(
arb_item: T
) -> impl Strategy<Value = (
MaskingBuffer<ArrayStorage<T::Value, N>>,
Vec<T::Value>,
)> where T::Value: Clone {
assert!(N.is_power_of_two(),
"`MaskingBuffer` requires a power-of-two capacity!");
let capacity = Just(NonZeroUsize::new(N).unwrap());
(ANY_USIZE, BufferStrategy::new(capacity, arb_item))
.prop_map(|(cur, (cap, items))| {
assert_eq!(cap.get(), N);
let mut buffer = MaskingBuffer {
cur: Wrapping(cur), len: 0,
data: ArrayStorage::new(),
};
for item in items.iter() {
assert!(buffer.enqueue(item.clone()).is_none());
}
(buffer, items)
})
}
pub fn arb_array_empty<T: Debug, const N: usize>(
) -> impl Strategy<Value = MaskingBuffer<ArrayStorage<T, N>>> {
ANY_USIZE.prop_map(|cur| MaskingBuffer {
cur: Wrapping(cur),
len: 0,
data: ArrayStorage::new(),
})
}
pub type HeapStrategy<T> = PropMap<
(AnyUsize, BufferStrategy<PropMap<Range<u32>, fn(u32) -> NonZeroUsize>, T>),
fn (
(usize, (NonZeroUsize, Vec<<T as Strategy>::Value>))
) -> MaskingBuffer<HeapStorage<<T as Strategy>::Value>>,
>;
pub fn arb_heap<T: Strategy>(arb_item: T) -> HeapStrategy<T> {
fn mapper<T: Strategy>(
(cur, (cap, items)): (usize, (NonZeroUsize, Vec<T::Value>))
) -> MaskingBuffer<HeapStorage<T::Value>> {
let mut buffer = MaskingBuffer {
cur: Wrapping(cur), len: 0,
data: HeapStorage::with_capacity(cap),
};
for item in items.into_iter() {
assert!(buffer.enqueue(item).is_none());
}
buffer
}
fn capacity_mapper(exp: u32) -> NonZeroUsize {
NonZeroUsize::new(1usize << exp).unwrap()
}
let capacity = (0u32 .. 14u32).prop_map(capacity_mapper as _);
(ANY_USIZE, BufferStrategy::new(capacity, arb_item))
.prop_map(mapper::<T> as _)
}
pub fn arb_heap_paired<T: Strategy>(
arb_item: T
) -> impl Strategy<Value = (
MaskingBuffer<HeapStorage<T::Value>>,
Vec<T::Value>,
)> where T::Value: Clone {
fn capacity_mapper(exp: u32) -> NonZeroUsize {
NonZeroUsize::new(1usize << exp).unwrap()
}
let capacity = (0u32 .. 14u32).prop_map(capacity_mapper);
(ANY_USIZE, BufferStrategy::new(capacity, arb_item))
.prop_map(|(cur, (cap, items))| {
let mut buffer = MaskingBuffer {
cur: Wrapping(cur), len: 0,
data: HeapStorage::with_capacity(cap),
};
for item in items.iter() {
assert!(buffer.enqueue(item.clone()).is_none());
}
(buffer, items)
})
}
pub fn arb_heap_empty<T: Debug>(
) -> impl Strategy<Value = MaskingBuffer<HeapStorage<T>>> {
(ANY_USIZE, (0u32 .. 14u32)).prop_map(|(cur, cap)| MaskingBuffer {
cur: Wrapping(cur),
len: 0,
data: HeapStorage::with_capacity(
NonZeroUsize::new(1usize << cap).unwrap()),
})
}