121 lines
2.6 KiB
Rust
121 lines
2.6 KiB
Rust
use parking_lot::Mutex;
|
|
use std::{convert::TryInto, sync::Arc};
|
|
|
|
#[derive(Debug, Default, PartialEq, Eq, PartialOrd, Ord)]
|
|
struct Inner {
|
|
counter: Vec<u16>,
|
|
}
|
|
|
|
#[derive(Clone, Debug)]
|
|
pub struct Generator {
|
|
current: Arc<Mutex<Inner>>,
|
|
}
|
|
|
|
#[derive(Debug, Default, PartialEq, Eq, PartialOrd, Ord)]
|
|
pub struct Path {
|
|
inner: Vec<u16>,
|
|
}
|
|
|
|
#[derive(Debug)]
|
|
pub struct PathError;
|
|
|
|
impl Inner {
|
|
fn next(&mut self) -> Vec<u16> {
|
|
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().next();
|
|
|
|
Path { inner }
|
|
}
|
|
}
|
|
|
|
impl Path {
|
|
pub fn from_be_bytes(bytes: Vec<u8>) -> Result<Self, PathError> {
|
|
let inner = bytes
|
|
.chunks(2)
|
|
.map(|chunk| {
|
|
let be_bytes: [u8; 2] = chunk.try_into().map_err(|_| PathError)?;
|
|
Ok(u16::from_be_bytes(be_bytes))
|
|
})
|
|
.collect::<Result<_, PathError>>()?;
|
|
|
|
Self::from_vec(inner)
|
|
}
|
|
|
|
pub fn to_be_bytes(&self) -> Vec<u8> {
|
|
self.inner
|
|
.iter()
|
|
.flat_map(|num| num.to_be_bytes())
|
|
.collect()
|
|
}
|
|
|
|
pub fn into_inner(self) -> Vec<u16> {
|
|
self.inner
|
|
}
|
|
|
|
pub fn from_vec(inner: Vec<u16>) -> Result<Self, PathError> {
|
|
if inner.is_empty() {
|
|
return Ok(Path { inner });
|
|
}
|
|
|
|
if inner.len().saturating_sub(1) != inner[0].into() {
|
|
return Err(PathError);
|
|
}
|
|
|
|
for elem in inner.iter() {
|
|
if *elem > 999 {
|
|
return Err(PathError);
|
|
}
|
|
}
|
|
|
|
Ok(Path { inner })
|
|
}
|
|
|
|
pub fn to_strings(&self) -> Vec<String> {
|
|
self.inner
|
|
.iter()
|
|
.map(|dir| {
|
|
if *dir > 99 {
|
|
format!("{}", dir)
|
|
} else if *dir > 9 {
|
|
format!("0{}", dir)
|
|
} else {
|
|
format!("00{}", dir)
|
|
}
|
|
})
|
|
.collect()
|
|
}
|
|
}
|