1use core::{iter::Fuse, num::NonZero};
2
3use serde::Serialize;
4
5use crate::Traversal;
6
7#[derive(Clone, Debug, PartialEq, PartialOrd, Hash, Serialize)]
11pub enum KeyLookup {
12 Named(&'static [&'static str]),
14 Numbered(NonZero<usize>),
16 Homogeneous(NonZero<usize>),
18}
19
20impl KeyLookup {
21 #[inline]
23 pub const fn named(names: &'static [&'static str]) -> Self {
24 if names.is_empty() {
25 panic!("Must have at least one child");
26 }
27 Self::Named(names)
28 }
29
30 #[inline]
32 pub const fn homogeneous(len: usize) -> Self {
33 match NonZero::new(len) {
34 Some(len) => Self::Homogeneous(len),
35 None => panic!("Must have at least one child"),
36 }
37 }
38
39 #[inline]
41 pub const fn numbered(len: usize) -> Self {
42 match NonZero::new(len) {
43 Some(len) => Self::Numbered(len),
44 None => panic!("Must have at least one child"),
45 }
46 }
47
48 #[inline]
50 pub const fn len(&self) -> NonZero<usize> {
51 match self {
52 Self::Named(names) => match NonZero::new(names.len()) {
53 Some(len) => len,
54 None => panic!("Must have at least one child"),
55 },
56 Self::Numbered(len) | Self::Homogeneous(len) => *len,
57 }
58 }
59
60 #[inline]
62 pub fn lookup(&self, index: usize) -> Result<Option<&'static str>, Traversal> {
63 match self {
64 Self::Named(names) => match names.get(index) {
65 Some(name) => Ok(Some(name)),
66 None => Err(Traversal::NotFound(1)),
67 },
68 Self::Numbered(len) | Self::Homogeneous(len) => {
69 if index >= len.get() {
70 Err(Traversal::NotFound(1))
71 } else {
72 Ok(None)
73 }
74 }
75 }
76 }
77}
78
79pub trait Key {
81 fn find(&self, lookup: &KeyLookup) -> Result<usize, Traversal>;
83}
84
85impl<T: Key> Key for &T
86where
87 T: Key + ?Sized,
88{
89 #[inline]
90 fn find(&self, lookup: &KeyLookup) -> Result<usize, Traversal> {
91 (**self).find(lookup)
92 }
93}
94
95impl<T: Key> Key for &mut T
96where
97 T: Key + ?Sized,
98{
99 #[inline]
100 fn find(&self, lookup: &KeyLookup) -> Result<usize, Traversal> {
101 (**self).find(lookup)
102 }
103}
104
105macro_rules! impl_key_integer {
107 ($($t:ty)+) => {$(
108 impl Key for $t {
109 #[inline]
110 fn find(&self, lookup: &KeyLookup) -> Result<usize, Traversal> {
111 (*self)
112 .try_into()
113 .ok()
114 .filter(|i| *i < lookup.len().get())
115 .ok_or(Traversal::NotFound(1))
116 }
117 }
118 )+};
119}
120impl_key_integer!(usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128);
121
122impl Key for str {
124 #[inline]
125 fn find(&self, lookup: &KeyLookup) -> Result<usize, Traversal> {
126 match lookup {
127 KeyLookup::Named(names) => names.iter().position(|n| *n == self),
128 KeyLookup::Homogeneous(len) | KeyLookup::Numbered(len) => {
129 self.parse().ok().filter(|i| *i < len.get())
130 }
131 }
132 .ok_or(Traversal::NotFound(1))
133 }
134}
135
136pub trait Keys {
138 fn next(&mut self, lookup: &KeyLookup) -> Result<usize, Traversal>;
142
143 fn finalize(&mut self) -> Result<(), Traversal>;
147
148 #[inline]
150 fn chain<U: IntoKeys>(self, other: U) -> Chain<Self, U::IntoKeys>
151 where
152 Self: Sized,
153 {
154 Chain(self, other.into_keys())
155 }
156}
157
158impl<T> Keys for &mut T
159where
160 T: Keys + ?Sized,
161{
162 #[inline]
163 fn next(&mut self, lookup: &KeyLookup) -> Result<usize, Traversal> {
164 (**self).next(lookup)
165 }
166
167 #[inline]
168 fn finalize(&mut self) -> Result<(), Traversal> {
169 (**self).finalize()
170 }
171}
172
173#[derive(Debug, Clone)]
175#[repr(transparent)]
176pub struct KeysIter<T>(Fuse<T>);
177
178impl<T: Iterator> KeysIter<T> {
179 #[inline]
180 fn new(inner: T) -> Self {
181 Self(inner.fuse())
182 }
183}
184
185impl<T> Keys for KeysIter<T>
186where
187 T: Iterator,
188 T::Item: Key,
189{
190 #[inline]
191 fn next(&mut self, lookup: &KeyLookup) -> Result<usize, Traversal> {
192 self.0.next().ok_or(Traversal::TooShort(0))?.find(lookup)
193 }
194
195 #[inline]
196 fn finalize(&mut self) -> Result<(), Traversal> {
197 self.0
198 .next()
199 .is_none()
200 .then_some(())
201 .ok_or(Traversal::TooLong(0))
202 }
203}
204
205pub trait IntoKeys {
207 type IntoKeys: Keys;
209
210 fn into_keys(self) -> Self::IntoKeys;
212}
213
214impl<T> IntoKeys for T
215where
216 T: IntoIterator,
217 <T::IntoIter as Iterator>::Item: Key,
218{
219 type IntoKeys = KeysIter<T::IntoIter>;
220
221 #[inline]
222 fn into_keys(self) -> Self::IntoKeys {
223 KeysIter::new(self.into_iter())
224 }
225}
226
227impl<T> IntoKeys for KeysIter<T>
228where
229 T: Iterator,
230 T::Item: Key,
231{
232 type IntoKeys = KeysIter<T>;
233
234 #[inline]
235 fn into_keys(self) -> Self::IntoKeys {
236 self
237 }
238}
239
240pub struct Chain<T, U>(T, U);
242
243impl<T, U> Chain<T, U> {
244 #[inline]
246 pub fn new(t: T, u: U) -> Self {
247 Self(t, u)
248 }
249}
250
251impl<T: Keys, U: Keys> Keys for Chain<T, U> {
252 #[inline]
253 fn next(&mut self, lookup: &KeyLookup) -> Result<usize, Traversal> {
254 match self.0.next(lookup) {
255 Err(Traversal::TooShort(_)) => self.1.next(lookup),
256 ret => ret,
257 }
258 }
259
260 #[inline]
261 fn finalize(&mut self) -> Result<(), Traversal> {
262 self.0.finalize().and_then(|()| self.1.finalize())
263 }
264}
265
266impl<T: Keys, U: Keys> IntoKeys for Chain<T, U> {
267 type IntoKeys = Self;
268
269 #[inline]
270 fn into_keys(self) -> Self::IntoKeys {
271 self
272 }
273}