storage_path_generator/
lib.rs1use std::{
2 convert::TryInto,
3 sync::{Arc, Mutex},
4};
5
6#[derive(Debug, Default, PartialEq, Eq, PartialOrd, Ord)]
7struct Inner {
8 counter: Vec<u16>,
9}
10
11#[derive(Clone, Debug)]
12pub struct Generator {
13 current: Arc<Mutex<Inner>>,
14}
15
16#[derive(Debug, Default, PartialEq, Eq, PartialOrd, Ord)]
17pub struct Path {
18 inner: Vec<u16>,
19}
20
21#[derive(Debug)]
22pub enum PathError {
23 Format,
24 Length,
25 Range,
26}
27
28impl Inner {
29 fn next(&mut self) -> Vec<u16> {
30 let mut modified_depth = 0;
31
32 for (depth, count) in self.counter.iter_mut().enumerate().rev() {
33 if *count < 999 {
34 *count += 1;
35 modified_depth = depth;
36 break;
37 } else {
38 *count = 0;
39 }
40 }
41
42 if modified_depth == 0 {
43 self.counter.push(0);
44 }
45
46 self.counter.clone()
47 }
48}
49
50impl Generator {
51 pub fn new() -> Self {
52 Self::from_existing(Path { inner: vec![] })
53 }
54
55 pub fn from_existing(existing: Path) -> Self {
56 Generator {
57 current: Arc::new(Mutex::new(Inner {
58 counter: existing.inner,
59 })),
60 }
61 }
62
63 pub fn next(&self) -> Path {
64 let inner = self.current.lock().unwrap().next();
65
66 Path { inner }
67 }
68}
69
70impl Path {
71 pub fn from_be_bytes(bytes: Vec<u8>) -> Result<Self, PathError> {
72 let inner = bytes
73 .chunks(2)
74 .map(|chunk| {
75 let be_bytes: [u8; 2] = chunk.try_into().map_err(|_| PathError::Length)?;
76 Ok(u16::from_be_bytes(be_bytes))
77 })
78 .collect::<Result<_, PathError>>()?;
79
80 Self::from_vec(inner)
81 }
82
83 pub fn to_be_bytes(&self) -> Vec<u8> {
84 self.inner
85 .iter()
86 .flat_map(|num| num.to_be_bytes())
87 .collect()
88 }
89
90 pub fn into_inner(self) -> Vec<u16> {
91 self.inner
92 }
93
94 pub fn from_vec(inner: Vec<u16>) -> Result<Self, PathError> {
95 if inner.is_empty() {
96 return Ok(Path { inner });
97 }
98
99 if inner.len().saturating_sub(1) != inner[0].into() {
100 return Err(PathError::Format);
101 }
102
103 for elem in inner.iter() {
104 if *elem > 999 {
105 return Err(PathError::Range);
106 }
107 }
108
109 Ok(Path { inner })
110 }
111
112 pub fn to_strings(&self) -> Vec<String> {
113 self.inner
114 .iter()
115 .map(|dir| {
116 if *dir > 99 {
117 format!("{}", dir)
118 } else if *dir > 9 {
119 format!("0{}", dir)
120 } else {
121 format!("00{}", dir)
122 }
123 })
124 .collect()
125 }
126}
127
128impl std::fmt::Display for PathError {
129 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
130 match self {
131 PathError::Format => {
132 write!(f, "Invalid path format")
133 }
134 PathError::Length => {
135 write!(f, "Invalid segment length")
136 }
137 PathError::Range => {
138 write!(f, "Invalid segment format")
139 }
140 }
141 }
142}
143
144impl std::error::Error for PathError {}
145
146impl Default for Generator {
147 fn default() -> Self {
148 Self::new()
149 }
150}