diff --git a/src/morethantext/cache.rs b/src/morethantext/cache.rs index d5d0f5e..0c4936b 100644 --- a/src/morethantext/cache.rs +++ b/src/morethantext/cache.rs @@ -1,9 +1,78 @@ use super::{ErrorCode, FromCache, MTTError, Store, ToCache, ENTRY}; use async_std::{channel::Receiver, path::PathBuf}; -use std::collections::HashMap; +use rand::{distributions::Alphanumeric, thread_rng, Rng}; +use std::{collections::{HashMap, VecDeque}, iter::Iterator}; + +struct IDGenerator { + ids: Option>, +} + +impl IDGenerator { + fn new() -> Self { + Self { + ids: None, + } + } + + fn with_ids(ids: T) -> Self where T: Into>, D: Into { + let id_list = ids.into(); + let mut data = VecDeque::new(); + for id in id_list { + data.push_back(id.into()); + } + Self { + ids: Some(data), + } + } +} + +impl Iterator for IDGenerator { + type Item = String; + + fn next(&mut self) -> Option { + match &self.ids { + Some(id_list) => { + let mut ids = id_list.clone(); + let output = match ids.pop_front() { + Some(id) => Some(id.to_string()), + None => None, + }; + self.ids = Some(ids); + output + } + None => Some(thread_rng().sample_iter(&Alphanumeric).take(64).collect()), + } + } +} + +#[cfg(test)] +mod genid { + use super::*; + + #[test] + fn unique_ids() { + let mut gen = IDGenerator::new(); + let mut output: Vec = Vec::new(); + for _ in 0..10 { + let id = gen.next().unwrap(); + assert!(!output.contains(&id), "{} found in {:?}", id, output); + output.push(id); + } + } + + #[test] + fn controlled_ids() { + let ids = ["one", "two", "three"]; + let mut gen = IDGenerator::with_ids(ids.clone()); + for id in ids { + assert_eq!(id, gen.next().unwrap()); + } + } +} pub struct Cache { data: HashMap, + ids: IDGenerator, } impl Cache { @@ -13,7 +82,10 @@ impl Cache { { let mut data = HashMap::new(); data.insert(ENTRY.to_string(), Store::new()); - Self { data: data } + Self { + data: data, + ids: IDGenerator::new(), + } } pub async fn listen(&mut self, listener: Receiver) {