1use core::fmt::Write;
2
3#[cfg(feature = "alloc")]
4use alloc::vec::Vec;
5
6use serde::{Deserialize, Serialize};
7
8use crate::{DescendError, Internal, IntoKeys, Key, Schema, Track, Transcode};
9
10macro_rules! impl_key_integer {
12 ($($t:ty)+) => {$(
13 impl Key for $t {
14 #[inline]
15 fn find(&self, internal: &Internal) -> Option<usize> {
16 (*self).try_into().ok().filter(|i| *i < internal.len().get())
17 }
18 }
19 )+};
20}
21impl_key_integer!(usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128);
22
23#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize, Default)]
25pub struct Indices<T: ?Sized> {
26 len: usize,
27 data: T,
28}
29
30impl<T> Indices<T> {
31 pub fn new(data: T, len: usize) -> Self {
33 Self { len, data }
34 }
35
36 #[inline]
38 pub fn len(&self) -> usize {
39 self.len
40 }
41
42 #[inline]
44 pub fn is_empty(&self) -> bool {
45 self.len == 0
46 }
47
48 pub fn into_inner(self) -> (T, usize) {
50 (self.data, self.len)
51 }
52}
53
54impl<T> From<T> for Indices<T> {
55 #[inline]
56 fn from(value: T) -> Self {
57 Self {
58 len: 0,
59 data: value,
60 }
61 }
62}
63
64impl<U, T: AsRef<[U]> + ?Sized> AsRef<[U]> for Indices<T> {
65 #[inline]
66 fn as_ref(&self) -> &[U] {
67 &self.data.as_ref()[..self.len]
68 }
69}
70
71impl<'a, U, T: ?Sized> IntoIterator for &'a Indices<T>
72where
73 &'a T: IntoIterator<Item = U>,
74{
75 type Item = U;
76
77 type IntoIter = core::iter::Take<<&'a T as IntoIterator>::IntoIter>;
78
79 #[inline]
80 fn into_iter(self) -> Self::IntoIter {
81 (&self.data).into_iter().take(self.len)
82 }
83}
84
85impl<T: AsMut<[usize]> + ?Sized> Transcode for Indices<T> {
86 type Error = <[usize] as Transcode>::Error;
87
88 fn transcode(
89 &mut self,
90 schema: &Schema,
91 keys: impl IntoKeys,
92 ) -> Result<(), DescendError<Self::Error>> {
93 let mut slic = Track::new(self.data.as_mut());
94 let ret = slic.transcode(schema, keys);
95 self.len = slic.depth();
96 ret
97 }
98}
99
100macro_rules! impl_transcode_slice {
101 ($($t:ty)+) => {$(
102 impl Transcode for [$t] {
103 type Error = ();
104
105 fn transcode(&mut self, schema: &Schema, keys: impl IntoKeys) -> Result<(), DescendError<Self::Error>> {
106 let mut it = self.iter_mut();
107 schema.descend(keys.into_keys(), |_meta, idx_schema| {
108 if let Some((index, internal)) = idx_schema {
109 debug_assert!(internal.len().get() <= <$t>::MAX as _);
110 let i = index.try_into().or(Err(()))?;
111 let idx = it.next().ok_or(())?;
112 *idx = i;
113 }
114 Ok(())
115 })
116 }
117 }
118 )+};
119}
120impl_transcode_slice!(usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128);
121
122#[cfg(feature = "alloc")]
123impl<T> Transcode for Vec<T>
124where
125 usize: TryInto<T>,
126{
127 type Error = <usize as TryInto<T>>::Error;
128
129 fn transcode(
130 &mut self,
131 schema: &Schema,
132 keys: impl IntoKeys,
133 ) -> Result<(), DescendError<Self::Error>> {
134 schema.descend(keys.into_keys(), |_meta, idx_schema| {
135 if let Some((index, _schema)) = idx_schema {
136 self.push(index.try_into()?);
137 }
138 Ok(())
139 })
140 }
141}
142
143#[cfg(feature = "heapless")]
144impl<T, const N: usize> Transcode for heapless::Vec<T, N>
145where
146 usize: TryInto<T>,
147{
148 type Error = ();
149
150 fn transcode(
151 &mut self,
152 schema: &Schema,
153 keys: impl IntoKeys,
154 ) -> Result<(), DescendError<Self::Error>> {
155 schema.descend(keys.into_keys(), |_meta, idx_schema| {
156 if let Some((index, _schema)) = idx_schema {
157 let i = index.try_into().or(Err(()))?;
158 self.push(i).or(Err(()))?;
159 }
160 Ok(())
161 })
162 }
163}
164
165impl Key for str {
169 #[inline]
170 fn find(&self, internal: &Internal) -> Option<usize> {
171 internal.get_index(self)
172 }
173}
174
175#[derive(Debug, Default, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
185#[repr(transparent)]
186#[serde(transparent)]
187pub struct Path<T: ?Sized, const S: char>(pub T);
188
189impl<T: ?Sized, const S: char> Path<T, S> {
190 #[inline]
192 pub const fn separator(&self) -> char {
193 S
194 }
195}
196
197impl<T, const S: char> Path<T, S> {
198 #[inline]
200 pub fn into_inner(self) -> T {
201 self.0
202 }
203}
204
205impl<T: AsRef<str> + ?Sized, const S: char> AsRef<str> for Path<T, S> {
206 fn as_ref(&self) -> &str {
207 self.0.as_ref()
208 }
209}
210
211impl<T: core::fmt::Display, const S: char> core::fmt::Display for Path<T, S> {
212 #[inline]
213 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
214 self.0.fmt(f)
215 }
216}
217
218#[derive(Copy, Clone, Default, Debug, PartialEq, PartialOrd, Serialize, Deserialize)]
220pub struct PathIter<'a> {
221 data: Option<&'a str>,
222 sep: char,
223}
224
225impl<'a> PathIter<'a> {
226 #[inline]
228 pub fn new(data: Option<&'a str>, sep: char) -> Self {
229 Self { data, sep }
230 }
231
232 #[inline]
236 pub fn root(data: &'a str, sep: char) -> Self {
237 let mut s = Self::new(Some(data), sep);
238 s.next();
247 s
248 }
249}
250
251impl<'a> Iterator for PathIter<'a> {
252 type Item = &'a str;
253
254 fn next(&mut self) -> Option<Self::Item> {
255 self.data.map(|s| {
256 let pos = s
257 .chars()
258 .map_while(|c| (c != self.sep).then_some(c.len_utf8()))
259 .sum();
260 let (left, right) = s.split_at(pos);
261 self.data = right.get(self.sep.len_utf8()..);
262 left
263 })
264 }
265}
266
267impl core::iter::FusedIterator for PathIter<'_> {}
268
269impl<'a, T: AsRef<str> + ?Sized, const S: char> IntoKeys for Path<&'a T, S> {
270 type IntoKeys = <PathIter<'a> as IntoKeys>::IntoKeys;
271
272 #[inline]
273 fn into_keys(self) -> Self::IntoKeys {
274 PathIter::root(self.0.as_ref(), S).into_keys()
275 }
276}
277
278impl<'a, T: AsRef<str> + ?Sized, const S: char> IntoKeys for &'a Path<T, S> {
279 type IntoKeys = <Path<&'a str, S> as IntoKeys>::IntoKeys;
280
281 #[inline]
282 fn into_keys(self) -> Self::IntoKeys {
283 PathIter::root(self.0.as_ref(), S).into_keys()
284 }
285}
286
287impl<T: Write + ?Sized, const S: char> Transcode for Path<T, S> {
288 type Error = core::fmt::Error;
289
290 fn transcode(
291 &mut self,
292 schema: &Schema,
293 keys: impl IntoKeys,
294 ) -> Result<(), DescendError<Self::Error>> {
295 schema.descend(keys.into_keys(), |_meta, idx_schema| {
296 if let Some((index, internal)) = idx_schema {
297 self.0.write_char(S)?;
298 let mut buf = itoa::Buffer::new();
299 let name = internal
300 .get_name(index)
301 .unwrap_or_else(|| buf.format(index));
302 debug_assert!(!name.contains(S));
303 self.0.write_str(name)
304 } else {
305 Ok(())
306 }
307 })
308 }
309}
310
311#[cfg(test)]
312mod test {
313 use super::*;
314
315 #[test]
316 fn strsplit() {
317 use heapless::Vec;
318 for p in ["/d/1", "/a/bccc//d/e/", "", "/", "a/b", "a"] {
319 let a: Vec<_, 10> = PathIter::root(p, '/').collect();
320 let b: Vec<_, 10> = p.split('/').skip(1).collect();
321 assert_eq!(a, b);
322 }
323 }
324}