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