use core::{
fmt::Write,
iter::Copied,
ops::{Deref, DerefMut},
slice::Iter,
};
use serde::{Deserialize, Serialize};
use crate::{Error, IntoKeys, KeysIter, Traversal, TreeKey};
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
pub enum NodeType {
Leaf,
Internal,
}
impl NodeType {
#[inline]
pub const fn is_leaf(&self) -> bool {
matches!(self, Self::Leaf)
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
pub struct Node {
pub depth: usize,
pub typ: NodeType,
}
impl Node {
#[inline]
pub const fn depth(&self) -> usize {
self.depth
}
#[inline]
pub const fn typ(&self) -> NodeType {
self.typ
}
#[inline]
pub const fn is_leaf(&self) -> bool {
self.typ.is_leaf()
}
#[inline]
pub const fn leaf(depth: usize) -> Self {
Self {
depth,
typ: NodeType::Leaf,
}
}
#[inline]
pub const fn internal(depth: usize) -> Self {
Self {
depth,
typ: NodeType::Internal,
}
}
}
impl From<Node> for usize {
fn from(value: Node) -> Self {
value.depth
}
}
impl TryFrom<Result<usize, Error<()>>> for Node {
type Error = Traversal;
fn try_from(value: Result<usize, Error<()>>) -> Result<Self, Traversal> {
match value {
Ok(depth) => Ok(Node::leaf(depth)),
Err(Error::Traversal(Traversal::TooShort(depth))) => Ok(Node::internal(depth)),
Err(Error::Inner(depth, ())) => Err(Traversal::TooShort(depth)),
Err(Error::Traversal(err)) => Err(err),
Err(Error::Finalization(())) => unreachable!(),
}
}
}
pub trait Transcode {
fn transcode<M, const Y: usize, K>(&mut self, keys: K) -> Result<Node, Traversal>
where
M: TreeKey<Y> + ?Sized,
K: IntoKeys;
}
impl Transcode for () {
fn transcode<M, const Y: usize, K>(&mut self, keys: K) -> Result<Node, Traversal>
where
M: TreeKey<Y> + ?Sized,
K: IntoKeys,
{
M::traverse_by_key(keys.into_keys(), |_index, _name, _len| Ok::<_, ()>(())).try_into()
}
}
#[derive(Debug, Default, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
#[repr(transparent)]
#[serde(transparent)]
pub struct Path<T: ?Sized, const S: char>(pub T);
impl<T: ?Sized, const S: char> Path<T, S> {
pub const fn separator(&self) -> char {
S
}
}
impl<T, const S: char> Path<T, S> {
pub fn into_inner(self) -> T {
self.0
}
}
impl<T: ?Sized, const S: char> Deref for Path<T, S> {
type Target = T;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl<T: ?Sized, const S: char> DerefMut for Path<T, S> {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}
impl<T, const S: char> From<T> for Path<T, S> {
fn from(value: T) -> Self {
Path(value)
}
}
#[derive(Copy, Clone, Default, Debug, PartialEq, PartialOrd, Serialize, Deserialize)]
#[repr(transparent)]
pub struct PathIter<'a, const S: char>(Option<&'a str>);
impl<'a, const S: char> PathIter<'a, S> {
#[inline]
fn new(s: &'a str) -> Self {
let mut s = Self(Some(s));
s.next();
s
}
}
impl<'a, const S: char> Iterator for PathIter<'a, S> {
type Item = &'a str;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
self.0.map(|s| {
let pos = s
.chars()
.map_while(|c| (c != S).then_some(c.len_utf8()))
.sum();
let (left, right) = s.split_at(pos);
self.0 = right.get(S.len_utf8()..);
left
})
}
}
impl<'a, T: AsRef<str> + ?Sized, const S: char> IntoKeys for &'a Path<T, S> {
type IntoKeys = KeysIter<PathIter<'a, S>>;
fn into_keys(self) -> Self::IntoKeys {
PathIter::<'a, S>::new(self.0.as_ref()).into_keys()
}
}
impl<T: Write + ?Sized, const S: char> Transcode for Path<T, S> {
fn transcode<M, const Y: usize, K>(&mut self, keys: K) -> Result<Node, Traversal>
where
M: TreeKey<Y> + ?Sized,
K: IntoKeys,
{
M::traverse_by_key(keys.into_keys(), |index, name, _len| {
self.0
.write_char(S)
.and_then(|()| {
let mut buf = itoa::Buffer::new();
let name = name.unwrap_or_else(|| buf.format(index));
debug_assert!(!name.contains(S));
self.0.write_str(name)
})
.or(Err(()))
})
.try_into()
}
}
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
#[repr(transparent)]
#[serde(transparent)]
pub struct Indices<T: ?Sized>(pub T);
impl<T: ?Sized> Deref for Indices<T> {
type Target = T;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl<T: ?Sized> DerefMut for Indices<T> {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}
impl<const D: usize> Default for Indices<[usize; D]> {
fn default() -> Self {
Self([0; D])
}
}
impl<T> Indices<T> {
pub fn into_inner(self) -> T {
self.0
}
}
impl<const D: usize> From<Indices<[usize; D]>> for [usize; D] {
fn from(value: Indices<[usize; D]>) -> Self {
value.0
}
}
impl<T> From<T> for Indices<T> {
fn from(value: T) -> Self {
Self(value)
}
}
impl<'a, T: AsRef<[usize]> + ?Sized> IntoKeys for &'a Indices<T> {
type IntoKeys = KeysIter<Copied<Iter<'a, usize>>>;
fn into_keys(self) -> Self::IntoKeys {
self.0.as_ref().iter().copied().into_keys()
}
}
impl<T: AsMut<[usize]> + ?Sized> Transcode for Indices<T> {
fn transcode<M, const Y: usize, K>(&mut self, keys: K) -> Result<Node, Traversal>
where
M: TreeKey<Y> + ?Sized,
K: IntoKeys,
{
let mut it = self.0.as_mut().iter_mut();
M::traverse_by_key(keys.into_keys(), |index, _name, _len| {
it.next().ok_or(()).map(|idx| {
*idx = index;
})
})
.try_into()
}
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn strsplit() {
use heapless::Vec;
for p in ["/d/1", "/a/bccc//d/e/", "", "/", "a/b", "a"] {
let a: Vec<_, 10> = PathIter::<'_, '/'>::new(p).collect();
let b: Vec<_, 10> = p.split('/').skip(1).collect();
assert_eq!(a, b);
}
}
}