use std::{ convert::TryInto, sync::{Arc, Mutex}, }; #[derive(Debug, Default, PartialEq, Eq, PartialOrd, Ord)] struct Inner { counter: Vec, } #[derive(Clone, Debug)] pub struct Generator { current: Arc>, } #[derive(Debug, Default, PartialEq, Eq, PartialOrd, Ord)] pub struct Path { inner: Vec, } #[derive(Debug)] pub enum PathError { Format, Length, Range, } impl Inner { fn next(&mut self) -> Vec { let mut modified_depth = 0; for (depth, count) in self.counter.iter_mut().enumerate().rev() { if *count < 999 { *count += 1; modified_depth = depth; break; } else { *count = 0; } } if modified_depth == 0 { self.counter.push(0); } self.counter.clone() } } impl Generator { pub fn new() -> Self { Self::from_existing(Path { inner: vec![] }) } pub fn from_existing(existing: Path) -> Self { Generator { current: Arc::new(Mutex::new(Inner { counter: existing.inner, })), } } pub fn next(&self) -> Path { let inner = self.current.lock().unwrap().next(); Path { inner } } } impl Path { pub fn from_be_bytes(bytes: Vec) -> Result { let inner = bytes .chunks(2) .map(|chunk| { let be_bytes: [u8; 2] = chunk.try_into().map_err(|_| PathError::Length)?; Ok(u16::from_be_bytes(be_bytes)) }) .collect::>()?; Self::from_vec(inner) } pub fn to_be_bytes(&self) -> Vec { self.inner .iter() .flat_map(|num| num.to_be_bytes()) .collect() } pub fn into_inner(self) -> Vec { self.inner } pub fn from_vec(inner: Vec) -> Result { if inner.is_empty() { return Ok(Path { inner }); } if inner.len().saturating_sub(1) != inner[0].into() { return Err(PathError::Format); } for elem in inner.iter() { if *elem > 999 { return Err(PathError::Range); } } Ok(Path { inner }) } pub fn to_strings(&self) -> Vec { self.inner .iter() .map(|dir| { if *dir > 99 { format!("{}", dir) } else if *dir > 9 { format!("0{}", dir) } else { format!("00{}", dir) } }) .collect() } } impl std::fmt::Display for PathError { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { PathError::Format => { write!(f, "Invalid path format") } PathError::Length => { write!(f, "Invalid segment length") } PathError::Range => { write!(f, "Invalid segment format") } } } } impl std::error::Error for PathError {} impl Default for Generator { fn default() -> Self { Self::new() } }