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