#![warn(missing_docs)]
#![deny(unsafe_code)]
#![cfg_attr(not(any(feature = "std", doc)), no_std)]
#![cfg_attr(feature = "doc_cfg", feature(doc_cfg))]
extern crate alloc;
use alloc::boxed::Box;
use alloc::collections::VecDeque;
use core::borrow::Borrow;
use core::fmt::{self, Debug};
use core::iter::{DoubleEndedIterator, ExactSizeIterator};
use core::mem;
use rand::Rng;
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
pub mod map;
use map::{Map, MapFrom, MapFromSlice, MapOps, MapOpsSlice};
use map::{OwnedSliceKey, SliceKey};
#[cfg_attr(
feature = "serde",
derive(Serialize, Deserialize),
serde(bound(serialize = "T: Serialize, M: Map<T>")),
serde(bound(deserialize = "T: Deserialize<'de>, M: Map<T>"))
)]
struct FrequencyMap<T, M: Map<T>> {
#[cfg_attr(
feature = "serde",
serde(serialize_with = "MapOps::serialize"),
serde(deserialize_with = "MapOps::deserialize")
)]
map: <M as MapFrom<T>>::To<usize>,
total: usize,
}
impl<T: Debug, M: Map<T>> Debug for FrequencyMap<T, M> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("FrequencyMap")
.field("map", &map::MapDebug::new(&self.map))
.field("total", &self.total)
.finish()
}
}
impl<T: Clone, M: Map<T>> Clone for FrequencyMap<T, M> {
fn clone(&self) -> Self {
Self {
map: self.map.clone(),
total: self.total,
}
}
}
impl<T, M: Map<T>> Default for FrequencyMap<T, M> {
fn default() -> Self {
Self {
map: Default::default(),
total: 0,
}
}
}
#[cfg_attr(
feature = "serde",
derive(Serialize, Deserialize),
serde(bound(serialize = "T: Serialize, M: Map<T>")),
serde(bound(deserialize = "T: Deserialize<'de>, M: Map<T>"))
)]
pub struct Chain<T, M: Map<T> = map::BTree> {
#[cfg_attr(
feature = "serde",
serde(serialize_with = "MapOps::serialize"),
serde(deserialize_with = "MapOps::deserialize")
)]
map: <M as MapFromSlice<T>>::To<Box<FrequencyMap<T, M>>>,
depth: usize,
#[cfg_attr(feature = "serde", serde(skip))]
buf: VecDeque<T>,
}
pub type BTreeChain<T> = Chain<T, map::BTree>;
#[cfg(feature = "std")]
#[cfg_attr(feature = "doc_cfg", doc(cfg(feature = "std")))]
pub type HashChain<T> = Chain<T, map::Hash>;
impl<T, M: Map<T>> Chain<T, M> {
pub fn new(depth: usize) -> Self {
Self {
map: Default::default(),
depth,
buf: Default::default(),
}
}
pub fn depth(&self) -> usize {
self.depth
}
fn take_buf(&mut self) -> VecDeque<T> {
let mut buf = mem::take(&mut self.buf);
buf.clear();
if buf.capacity() == 0 {
buf.reserve_exact(self.depth);
}
buf
}
pub fn add_all<I>(&mut self, items: I, edges: AddEdges)
where
I: IntoIterator<Item = T>,
T: Clone,
{
let mut buf = self.take_buf();
let mut iter = items.into_iter();
let mut item_opt = iter.next();
while let Some(item) = item_opt {
debug_assert!(buf.len() <= self.depth);
let next = iter.next();
if buf.len() == self.depth || edges.has_start() {
if next.is_some() || edges.has_end() {
self.add_with_key(&buf, Some(item.clone()));
} else {
self.add_with_key(&mut buf, Some(item));
break;
}
}
if buf.len() == self.depth {
buf.pop_front();
}
buf.push_back(item);
item_opt = next;
}
if !buf.is_empty() && edges.has_end() {
self.add_with_key(&mut buf, None);
}
self.buf = buf;
}
pub fn add<I>(&mut self, items: I, next: Option<T>)
where
I: IntoIterator<Item = T>,
{
let mut buf = self.take_buf();
buf.extend(items.into_iter().take(self.depth));
self.add_with_key(&mut buf, next);
self.buf = buf;
}
fn add_with_key<S>(&mut self, key: S, next: Option<T>)
where
S: SliceKey<T> + Into<OwnedSliceKey<T>>,
{
debug_assert!(key.get(self.depth()).is_none());
let freq = self.map.slice_get_or_insert_with(key, Default::default);
if let Some(v) = next {
*freq.map.get_or_insert_with(v, Default::default) += 1;
}
freq.total += 1;
}
#[cfg(feature = "std")]
#[cfg_attr(feature = "doc_cfg", doc(cfg(feature = "std")))]
pub fn generate(&self) -> Generator<'_, T, rand::rngs::ThreadRng, M> {
self.generate_with_rng(rand::thread_rng())
}
pub fn generate_with_rng<R: Rng>(&self, rng: R) -> Generator<'_, T, R, M> {
Generator::new(self, rng)
}
#[cfg(feature = "std")]
#[cfg_attr(feature = "doc_cfg", doc(cfg(feature = "std")))]
pub fn get<'a, B>(&'a self, items: &[B]) -> Option<&'a T>
where
B: Borrow<T>,
{
self.get_with_rng(items, rand::thread_rng())
}
pub fn get_with_rng<'a, B, R>(
&'a self,
items: &[B],
rng: R,
) -> Option<&'a T>
where
B: Borrow<T>,
R: Rng,
{
self.get_with_key(items, rng)
}
fn get_with_key<S, R>(&self, items: S, mut rng: R) -> Option<&T>
where
S: SliceKey<T>,
R: Rng,
{
let freq = self.map.slice_get(&items)?;
let mut n = rng.gen_range(0..freq.total);
for (item, count) in freq.map.iter() {
n = if let Some(n) = n.checked_sub(*count) {
n
} else {
return Some(item);
}
}
None
}
}
impl<T: Debug, M: Map<T>> Debug for Chain<T, M> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Chain")
.field("map", &map::MapDebug::new(&self.map))
.field("depth", &self.depth)
.field("buf", &self.buf)
.finish()
}
}
impl<T: Clone, M: Map<T>> Clone for Chain<T, M> {
fn clone(&self) -> Self {
Self {
map: self.map.clone(),
depth: self.depth,
buf: Default::default(),
}
}
}
#[derive(Clone, Copy, PartialEq, Eq)]
pub enum AddEdges {
Start,
End,
Both,
Neither,
}
impl AddEdges {
fn has_start(&self) -> bool {
matches!(self, Self::Start | Self::Both)
}
fn has_end(&self) -> bool {
matches!(self, Self::End | Self::Both)
}
}
pub struct Generator<'a, T, R, M: Map<T>> {
chain: &'a Chain<T, M>,
rng: R,
buf: VecDeque<&'a T>,
}
impl<'a, T, R, M: Map<T>> Generator<'a, T, R, M> {
pub fn new(chain: &'a Chain<T, M>, rng: R) -> Self {
let mut buf = VecDeque::new();
buf.reserve_exact(chain.depth);
Self {
chain,
rng,
buf,
}
}
#[rustfmt::skip]
pub fn state(
&self,
) -> impl '_
+ Clone
+ DoubleEndedIterator<Item = &T>
+ ExactSizeIterator
{
self.buf.iter().copied()
}
pub fn set_state<I>(&mut self, state: I)
where
I: IntoIterator<Item = &'a T>,
{
self.buf.clear();
let iter = state.into_iter().take(self.chain.depth());
self.buf.extend(iter);
}
}
impl<'a, T, R, M> Iterator for Generator<'a, T, R, M>
where
T: Clone,
R: Rng,
M: Map<T>,
{
type Item = &'a T;
fn next(&mut self) -> Option<&'a T> {
let next = self.chain.get_with_key(&self.buf, &mut self.rng)?;
debug_assert!(self.buf.len() <= self.chain.depth());
if self.buf.len() == self.chain.depth() {
self.buf.pop_front();
}
self.buf.push_back(next);
Some(next)
}
}