1use core::{
2 fmt::Write,
3 ops::{Deref, DerefMut},
4};
5
6use serde::{Deserialize, Serialize};
7
8use crate::{Error, IntoKeys, KeysIter, Traversal, TreeKey};
9
10#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
12pub enum NodeType {
13 Leaf,
17
18 Internal,
22}
23
24impl NodeType {
25 #[inline]
27 pub const fn is_leaf(&self) -> bool {
28 matches!(self, Self::Leaf)
29 }
30}
31
32#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
34pub struct Node {
35 pub depth: usize,
39
40 pub typ: NodeType,
42}
43
44impl Node {
45 #[inline]
47 pub const fn depth(&self) -> usize {
48 self.depth
49 }
50
51 #[inline]
53 pub const fn typ(&self) -> NodeType {
54 self.typ
55 }
56
57 #[inline]
59 pub const fn is_leaf(&self) -> bool {
60 self.typ.is_leaf()
61 }
62
63 #[inline]
65 pub const fn leaf(depth: usize) -> Self {
66 Self {
67 depth,
68 typ: NodeType::Leaf,
69 }
70 }
71
72 #[inline]
74 pub const fn internal(depth: usize) -> Self {
75 Self {
76 depth,
77 typ: NodeType::Internal,
78 }
79 }
80}
81
82impl From<Node> for usize {
83 #[inline]
84 fn from(value: Node) -> Self {
85 value.depth
86 }
87}
88
89impl TryFrom<Result<usize, Error<()>>> for Node {
91 type Error = Traversal;
92
93 #[inline]
94 fn try_from(value: Result<usize, Error<()>>) -> Result<Self, Traversal> {
95 match value {
96 Ok(depth) => Ok(Node::leaf(depth)),
97 Err(Error::Traversal(Traversal::TooShort(depth))) => Ok(Node::internal(depth)),
98 Err(Error::Inner(depth, ())) => Err(Traversal::TooShort(depth)),
99 Err(Error::Traversal(err)) => Err(err),
100 Err(Error::Finalization(())) => unreachable!(),
101 }
102 }
103}
104
105pub trait Transcode {
107 fn transcode<M, K>(&mut self, keys: K) -> Result<Node, Traversal>
115 where
116 M: TreeKey + ?Sized,
117 K: IntoKeys;
118}
119
120impl<T: Transcode + ?Sized> Transcode for &mut T {
121 fn transcode<M, K>(&mut self, keys: K) -> Result<Node, Traversal>
122 where
123 M: TreeKey + ?Sized,
124 K: IntoKeys,
125 {
126 T::transcode::<M, _>(self, keys)
127 }
128}
129
130impl Transcode for () {
132 fn transcode<M, K>(&mut self, keys: K) -> Result<Node, Traversal>
133 where
134 M: TreeKey + ?Sized,
135 K: IntoKeys,
136 {
137 M::traverse_by_key(keys.into_keys(), |_, _, _| Ok(())).try_into()
138 }
139}
140
141#[derive(Debug, Default, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
151#[repr(transparent)]
152#[serde(transparent)]
153pub struct Path<T: ?Sized, const S: char>(pub T);
154
155impl<T: ?Sized, const S: char> Path<T, S> {
156 #[inline]
158 pub const fn separator(&self) -> char {
159 S
160 }
161}
162
163impl<T, const S: char> Path<T, S> {
164 #[inline]
166 pub fn into_inner(self) -> T {
167 self.0
168 }
169}
170
171impl<T: ?Sized, const S: char> Deref for Path<T, S> {
172 type Target = T;
173 #[inline]
174 fn deref(&self) -> &Self::Target {
175 &self.0
176 }
177}
178
179impl<T: ?Sized, const S: char> DerefMut for Path<T, S> {
180 #[inline]
181 fn deref_mut(&mut self) -> &mut Self::Target {
182 &mut self.0
183 }
184}
185
186impl<T, const S: char> From<T> for Path<T, S> {
187 #[inline]
188 fn from(value: T) -> Self {
189 Path(value)
190 }
191}
192
193impl<T: core::fmt::Display, const S: char> core::fmt::Display for Path<T, S> {
194 #[inline]
195 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
196 self.0.fmt(f)
197 }
198}
199
200#[derive(Copy, Clone, Default, Debug, PartialEq, PartialOrd, Serialize, Deserialize)]
202#[repr(transparent)]
203pub struct PathIter<'a, const S: char>(Option<&'a str>);
204
205impl<'a, const S: char> PathIter<'a, S> {
206 #[inline]
208 pub fn new(s: Option<&'a str>) -> Self {
209 Self(s)
210 }
211
212 #[inline]
216 pub fn root(s: &'a str) -> Self {
217 let mut s = Self::new(Some(s));
218 s.next();
225 s
226 }
227}
228
229impl<'a, const S: char> Iterator for PathIter<'a, S> {
230 type Item = &'a str;
231
232 fn next(&mut self) -> Option<Self::Item> {
233 self.0.map(|s| {
234 let pos = s
235 .chars()
236 .map_while(|c| (c != S).then_some(c.len_utf8()))
237 .sum();
238 let (left, right) = s.split_at(pos);
239 self.0 = right.get(S.len_utf8()..);
240 left
241 })
242 }
243}
244
245impl<const S: char> core::iter::FusedIterator for PathIter<'_, S> {}
246
247impl<'a, T: AsRef<str> + ?Sized, const S: char> IntoKeys for Path<&'a T, S> {
248 type IntoKeys = KeysIter<PathIter<'a, S>>;
249
250 #[inline]
251 fn into_keys(self) -> Self::IntoKeys {
252 PathIter::<'a, S>::root(self.0.as_ref()).into_keys()
253 }
254}
255
256impl<'a, T: AsRef<str> + ?Sized, const S: char> IntoKeys for &'a Path<T, S> {
257 type IntoKeys = KeysIter<PathIter<'a, S>>;
258
259 #[inline]
260 fn into_keys(self) -> Self::IntoKeys {
261 Path(&self.0).into_keys()
262 }
263}
264
265impl<T: Write + ?Sized, const S: char> Transcode for Path<T, S> {
266 fn transcode<M, K>(&mut self, keys: K) -> Result<Node, Traversal>
267 where
268 M: TreeKey + ?Sized,
269 K: IntoKeys,
270 {
271 M::traverse_by_key(keys.into_keys(), |index, name, _len| {
272 self.0.write_char(S).or(Err(()))?;
273 let mut buf = itoa::Buffer::new();
274 let name = name.unwrap_or_else(|| buf.format(index));
275 debug_assert!(!name.contains(S));
276 self.0.write_str(name).or(Err(()))
277 })
278 .try_into()
279 }
280}
281
282#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
284#[repr(transparent)]
285#[serde(transparent)]
286pub struct Indices<T: ?Sized>(pub T);
287
288impl<T: ?Sized> Deref for Indices<T> {
289 type Target = T;
290 #[inline]
291 fn deref(&self) -> &Self::Target {
292 &self.0
293 }
294}
295
296impl<T: ?Sized> DerefMut for Indices<T> {
297 #[inline]
298 fn deref_mut(&mut self) -> &mut Self::Target {
299 &mut self.0
300 }
301}
302
303impl<T> Indices<T> {
304 #[inline]
306 pub fn into_inner(self) -> T {
307 self.0
308 }
309}
310
311impl<T> From<T> for Indices<T> {
312 #[inline]
313 fn from(value: T) -> Self {
314 Self(value)
315 }
316}
317
318impl<const D: usize, T: Copy + Default> Default for Indices<[T; D]> {
319 #[inline]
320 fn default() -> Self {
321 Self([Default::default(); D])
322 }
323}
324
325impl<const D: usize, T> From<Indices<[T; D]>> for [T; D] {
326 #[inline]
327 fn from(value: Indices<[T; D]>) -> Self {
328 value.0
329 }
330}
331
332impl<T: core::fmt::Display> core::fmt::Display for Indices<T> {
333 #[inline]
334 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
335 self.0.fmt(f)
336 }
337}
338
339impl<T: IntoKeys> IntoKeys for Indices<T> {
340 type IntoKeys = T::IntoKeys;
341 #[inline]
342 fn into_keys(self) -> Self::IntoKeys {
343 self.0.into_keys()
344 }
345}
346
347impl<T: AsMut<[usize]> + ?Sized> Transcode for Indices<T> {
348 #[inline]
349 fn transcode<M, K>(&mut self, keys: K) -> Result<Node, Traversal>
350 where
351 M: TreeKey + ?Sized,
352 K: IntoKeys,
353 {
354 self.0.as_mut().transcode::<M, _>(keys)
355 }
356}
357
358macro_rules! impl_transcode_slice {
359 ($($t:ty)+) => {$(
360 impl Transcode for [$t] {
361 fn transcode<M, K>(&mut self, keys: K) -> Result<Node, Traversal>
362 where
363 M: TreeKey + ?Sized,
364 K: IntoKeys,
365 {
366 let mut it = self.iter_mut();
367 M::traverse_by_key(keys.into_keys(), |index, _name, _len| {
368 let idx = it.next().ok_or(())?;
369 *idx = index.try_into().or(Err(()))?;
370 Ok(())
371 })
372 .try_into()
373 }
374 }
375 )+};
376}
377impl_transcode_slice!(usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128);
378
379#[cfg(feature = "alloc")]
380impl<T> Transcode for Vec<T>
381where
382 usize: TryInto<T>,
383{
384 fn transcode<M, K>(&mut self, keys: K) -> Result<Node, Traversal>
385 where
386 M: TreeKey + ?Sized,
387 K: IntoKeys,
388 {
389 M::traverse_by_key(keys.into_keys(), |index, _name, _len| {
390 self.push(index.try_into().or(Err(()))?);
391 Ok(())
392 })
393 .try_into()
394 }
395}
396
397#[cfg(test)]
398mod test {
399 use super::*;
400
401 #[test]
402 fn strsplit() {
403 use heapless::Vec;
404 for p in ["/d/1", "/a/bccc//d/e/", "", "/", "a/b", "a"] {
405 let a: Vec<_, 10> = PathIter::<'_, '/'>::root(p).collect();
406 let b: Vec<_, 10> = p.split('/').skip(1).collect();
407 assert_eq!(a, b);
408 }
409 }
410}