miniconf/
key.rs

1use core::{convert::Infallible, iter::Fuse};
2
3use serde::Serialize;
4
5use crate::{DescendError, Internal, KeyError, Schema};
6
7/// Convert a key into a node index given an internal node schema
8pub trait Key {
9    /// Convert the key `self` to a `usize` index
10    fn find(&self, internal: &Internal) -> Option<usize>;
11}
12
13impl<T: Key + ?Sized> Key for &T {
14    #[inline]
15    fn find(&self, internal: &Internal) -> Option<usize> {
16        (**self).find(internal)
17    }
18}
19
20impl<T: Key + ?Sized> Key for &mut T {
21    #[inline]
22    fn find(&self, internal: &Internal) -> Option<usize> {
23        (**self).find(internal)
24    }
25}
26
27/// Capability to yield and look up [`Key`]s
28pub trait Keys {
29    /// Look up the next key in a [`Internal`] and convert to `usize` index.
30    ///
31    /// This must be fused (like [`core::iter::FusedIterator`]).
32    fn next(&mut self, internal: &Internal) -> Result<usize, KeyError>;
33
34    /// Finalize the keys, ensure there are no more.
35    ///
36    /// This must be fused.
37    fn finalize(&mut self) -> Result<(), KeyError>;
38
39    /// Chain another `Keys` to this one.
40    #[inline]
41    fn chain<U: IntoKeys>(self, other: U) -> Chain<Self, U::IntoKeys>
42    where
43        Self: Sized,
44    {
45        Chain(self, other.into_keys())
46    }
47
48    /// Track depth
49    #[inline]
50    fn track(self) -> Track<Self>
51    where
52        Self: Sized,
53    {
54        Track {
55            inner: self,
56            depth: 0,
57        }
58    }
59
60    /// Track whether a leaf node is reached
61    #[inline]
62    fn short(self) -> Short<Self>
63    where
64        Self: Sized,
65    {
66        Short {
67            inner: self,
68            leaf: false,
69        }
70    }
71}
72
73impl<T: Keys + ?Sized> Keys for &mut T {
74    #[inline]
75    fn next(&mut self, internal: &Internal) -> Result<usize, KeyError> {
76        (**self).next(internal)
77    }
78
79    #[inline]
80    fn finalize(&mut self) -> Result<(), KeyError> {
81        (**self).finalize()
82    }
83}
84
85/// Be converted into a `Keys`
86pub trait IntoKeys {
87    /// The specific `Keys` implementor.
88    type IntoKeys: Keys;
89
90    /// Convert `self` into a `Keys` implementor.
91    fn into_keys(self) -> Self::IntoKeys;
92}
93
94/// Look up an `IntoKeys` in a `Schema` and transcode it.
95pub trait Transcode {
96    /// The possible error when transcoding.
97    ///
98    /// Use this to indicate no space or unencodable/invalid values
99    type Error;
100
101    /// Perform a node lookup of a `K: IntoKeys` on a `Schema` and transcode it.
102    ///
103    /// This modifies `self` such that afterwards `Self: IntoKeys` can be used on `M` again.
104    /// It returns a `Node` with node type and depth information.
105    ///
106    /// Returning `Err(ValueError::Absent)` indicates that there was insufficient
107    /// capacity and a key could not be encoded at the given depth.
108    fn transcode(
109        &mut self,
110        schema: &Schema,
111        keys: impl IntoKeys,
112    ) -> Result<(), DescendError<Self::Error>>;
113}
114
115impl<T: Transcode + ?Sized> Transcode for &mut T {
116    type Error = T::Error;
117    #[inline]
118    fn transcode(
119        &mut self,
120        schema: &Schema,
121        keys: impl IntoKeys,
122    ) -> Result<(), DescendError<Self::Error>> {
123        (**self).transcode(schema, keys)
124    }
125}
126
127/// Track leaf node encounter
128///
129/// This records whether a leaf node has been reached during [`Keys`] and [`Transcode`].
130#[derive(Clone, Debug, Default, PartialEq, PartialOrd, Hash, Serialize)]
131pub struct Short<K> {
132    /// The inner Keys
133    inner: K,
134    /// The inner keys terminates at a leaf node
135    leaf: bool,
136}
137
138impl<K> Short<K> {
139    /// Create a new `Short`
140    #[inline]
141    pub fn new(inner: K) -> Self {
142        Self { inner, leaf: false }
143    }
144
145    /// Whether a leaf node as been encountered
146    #[inline]
147    pub fn leaf(&self) -> bool {
148        self.leaf
149    }
150
151    /// Borrow the inner `Keys`
152    #[inline]
153    pub fn inner(&self) -> &K {
154        &self.inner
155    }
156
157    /// Split into inner `Keys` and leaf node flag
158    #[inline]
159    pub fn into_inner(self) -> (K, bool) {
160        (self.inner, self.leaf)
161    }
162}
163
164impl<K: Keys> IntoKeys for &mut Short<K> {
165    type IntoKeys = Self;
166
167    #[inline]
168    fn into_keys(self) -> Self::IntoKeys {
169        self.leaf = false;
170        self
171    }
172}
173
174impl<K: Keys> Keys for Short<K> {
175    #[inline]
176    fn next(&mut self, internal: &Internal) -> Result<usize, KeyError> {
177        self.inner.next(internal)
178    }
179
180    #[inline]
181    fn finalize(&mut self) -> Result<(), KeyError> {
182        self.inner.finalize()?;
183        self.leaf = true;
184        Ok(())
185    }
186}
187
188impl<T: Transcode> Transcode for Short<T> {
189    type Error = T::Error;
190
191    #[inline]
192    fn transcode(
193        &mut self,
194        schema: &Schema,
195        keys: impl IntoKeys,
196    ) -> Result<(), DescendError<Self::Error>> {
197        self.leaf = false;
198        match self.inner.transcode(schema, keys) {
199            Err(DescendError::Key(KeyError::TooShort)) => Ok(()),
200            Ok(()) | Err(DescendError::Key(KeyError::TooLong)) => {
201                self.leaf = true;
202                Ok(())
203            }
204            ret => ret,
205        }
206    }
207}
208
209/// Track key depth
210///
211/// This tracks the depth during [`Keys`] and [`Transcode`].
212#[derive(Clone, Debug, Default, PartialEq, PartialOrd, Hash, Serialize)]
213pub struct Track<K> {
214    /// The inner keys
215    inner: K,
216    /// The keys terminate at the given depth
217    depth: usize,
218}
219
220impl<K> Track<K> {
221    /// Create a new `Track`
222    #[inline]
223    pub fn new(inner: K) -> Self {
224        Self { inner, depth: 0 }
225    }
226
227    /// Whether a leaf node as been encountered
228    #[inline]
229    pub fn depth(&self) -> usize {
230        self.depth
231    }
232
233    /// Borrow the inner `Keys`
234    #[inline]
235    pub fn inner(&self) -> &K {
236        &self.inner
237    }
238
239    /// Split into inner `Keys` and leaf node flag
240    #[inline]
241    pub fn into_inner(self) -> (K, usize) {
242        (self.inner, self.depth)
243    }
244}
245
246impl<K: Keys> IntoKeys for &mut Track<K> {
247    type IntoKeys = Self;
248
249    #[inline]
250    fn into_keys(self) -> Self::IntoKeys {
251        self.depth = 0;
252        self
253    }
254}
255
256impl<K: Keys> Keys for Track<K> {
257    #[inline]
258    fn next(&mut self, internal: &Internal) -> Result<usize, KeyError> {
259        let k = self.inner.next(internal);
260        if k.is_ok() {
261            self.depth += 1;
262        }
263        k
264    }
265
266    #[inline]
267    fn finalize(&mut self) -> Result<(), KeyError> {
268        self.inner.finalize()
269    }
270}
271
272impl<T: Transcode> Transcode for Track<T> {
273    type Error = T::Error;
274
275    #[inline]
276    fn transcode(
277        &mut self,
278        schema: &Schema,
279        keys: impl IntoKeys,
280    ) -> Result<(), DescendError<Self::Error>> {
281        self.depth = 0;
282        let mut tracked = keys.into_keys().track();
283        let ret = self.inner.transcode(schema, &mut tracked);
284        self.depth = tracked.depth;
285        ret
286    }
287}
288
289/// Shim to provide the bare lookup/Track/Short without transcoding target
290impl Transcode for () {
291    type Error = Infallible;
292    #[inline]
293    fn transcode(
294        &mut self,
295        schema: &Schema,
296        keys: impl IntoKeys,
297    ) -> Result<(), DescendError<Self::Error>> {
298        schema.descend(keys.into_keys(), |_, _| Ok(()))
299    }
300}
301
302/// [`Keys`]/[`IntoKeys`] for Iterators of [`Key`]
303#[derive(Debug, Clone)]
304#[repr(transparent)]
305pub struct KeysIter<T>(Fuse<T>);
306
307impl<T: Iterator> KeysIter<T> {
308    #[inline]
309    fn new(inner: T) -> Self {
310        Self(inner.fuse())
311    }
312}
313
314impl<T> Keys for KeysIter<T>
315where
316    T: Iterator,
317    T::Item: Key,
318{
319    #[inline]
320    fn next(&mut self, internal: &Internal) -> Result<usize, KeyError> {
321        let n = self.0.next().ok_or(KeyError::TooShort)?;
322        n.find(internal).ok_or(KeyError::NotFound)
323    }
324
325    #[inline]
326    fn finalize(&mut self) -> Result<(), KeyError> {
327        match self.0.next() {
328            Some(_) => Err(KeyError::TooLong),
329            None => Ok(()),
330        }
331    }
332}
333
334impl<T> IntoKeys for T
335where
336    T: IntoIterator,
337    <T::IntoIter as Iterator>::Item: Key,
338{
339    type IntoKeys = KeysIter<T::IntoIter>;
340
341    #[inline]
342    fn into_keys(self) -> Self::IntoKeys {
343        KeysIter::new(self.into_iter())
344    }
345}
346
347impl<T> IntoKeys for KeysIter<T>
348where
349    T: Iterator,
350    T::Item: Key,
351{
352    type IntoKeys = KeysIter<T>;
353
354    #[inline]
355    fn into_keys(self) -> Self::IntoKeys {
356        self
357    }
358}
359
360/// Concatenate two `Keys` of different types
361pub struct Chain<T, U>(T, U);
362
363impl<T: Keys, U: Keys> Keys for Chain<T, U> {
364    #[inline]
365    fn next(&mut self, internal: &Internal) -> Result<usize, KeyError> {
366        match self.0.next(internal) {
367            Err(KeyError::TooShort) => self.1.next(internal),
368            ret => ret,
369        }
370    }
371
372    #[inline]
373    fn finalize(&mut self) -> Result<(), KeyError> {
374        self.0.finalize().and_then(|_| self.1.finalize())
375    }
376}
377
378impl<T: Keys, U: Keys> IntoKeys for Chain<T, U> {
379    type IntoKeys = Self;
380
381    #[inline]
382    fn into_keys(self) -> Self::IntoKeys {
383        self
384    }
385}