Skip to main content

musli_zerocopy/trie/
mod.rs

1//! A serialized prefix-trie.
2
3#[cfg(test)]
4mod tests;
5
6#[cfg(feature = "alloc")]
7#[cfg_attr(doc_cfg, doc(cfg(feature = "alloc")))]
8pub use self::factory::{Builder, store};
9#[cfg(feature = "alloc")]
10#[cfg_attr(doc_cfg, doc(cfg(feature = "alloc")))]
11mod factory;
12
13use self::walk::Walk;
14mod walk;
15
16use core::fmt;
17use core::marker::PhantomData;
18
19#[cfg(feature = "alloc")]
20use alloc::vec::Vec;
21
22use crate::endian::{ByteOrder, DefaultEndian};
23use crate::lossy_str::LossyStr;
24use crate::slice::{BinarySearch, Slice, binary_search_by};
25use crate::stack::ArrayStack;
26use crate::{Buf, DefaultSize, Error, Ref, Size, ZeroCopy};
27
28type StackEntry<'buf, T, E, F> = (LinksRef<T, E, F>, usize, &'buf [u8]);
29
30/// The flavor of a trie. Allows for customization of implementation details to
31/// for example use a more compact representation than the one provided by
32/// default in case there is a known upper bound on the number of elements or
33/// values.
34///
35/// # Examples
36///
37/// ```
38/// use musli_zerocopy::{trie, DefaultEndian, Error, OwnedBuf, ZeroCopy, ByteOrder};
39/// use musli_zerocopy::slice::Packed;
40///
41/// struct PackedTrie;
42///
43/// impl trie::Flavor for PackedTrie {
44///     // The maximum length of a string slice stored in the trie is `u8::MAX`.
45///     type String<E> = Packed<[u8], E, u32, u8>
46///     where
47///         E: ByteOrder;
48///
49///     // The max number of values stored in a single node is `u16::MAX`.
50///     type Values<T, E> = Packed<[T], E, u32, u16>
51///     where
52///         T: ZeroCopy,
53///         E: ByteOrder;
54///
55///     // The maximum number of children for a single node is `u8::MAX`.
56///     type Children<T, E> = Packed<[T], E, u32, u8>
57///     where
58///         T: ZeroCopy,
59///         E: ByteOrder;
60/// }
61///
62/// fn populate<F>(buf: &mut OwnedBuf, mut trie: trie::Builder<u32, F>) -> Result<trie::TrieRef<u32, DefaultEndian, F>, Error>
63/// where
64///     F: trie::Flavor
65/// {
66///     let a = buf.store_unsized("hello")?;
67///     let b = buf.store_unsized("hello world")?;
68///     trie.insert(buf, a, 1)?;
69///     trie.insert(buf, b, 2)?;
70///     trie.build(buf)
71/// }
72///
73/// let mut b1 = OwnedBuf::new();
74///
75/// let mut trie = trie::Builder::<u32, PackedTrie>::with_flavor();
76/// let trie = populate(&mut b1, trie)?;
77///
78/// assert_eq!(trie.get(&b1, "hello")?, Some(&[1][..]));
79/// assert_eq!(trie.get(&b1, "hello world")?, Some(&[2][..]));
80///
81/// let mut b2 = OwnedBuf::new();
82///
83/// let mut trie = trie::Builder::new();
84/// let trie = populate(&mut b2, trie)?;
85///
86/// assert_eq!(trie.get(&b2, "hello")?, Some(&[1][..]));
87/// assert_eq!(trie.get(&b2, "hello world")?, Some(&[2][..]));
88///
89/// assert!(b1.len() < b2.len());
90/// # Ok::<_, musli_zerocopy::Error>(())
91/// ```
92pub trait Flavor {
93    /// The type representing a string in the trie.
94    type String<E>: Slice<u8>
95    where
96        E: ByteOrder;
97
98    /// The type representing a collection of values in the trie.
99    type Values<T, E>: Slice<T>
100    where
101        T: ZeroCopy,
102        E: ByteOrder;
103
104    /// The type representing a collection of children in the trie.
105    type Children<T, E>: Slice<T>
106    where
107        T: ZeroCopy,
108        E: ByteOrder;
109}
110
111/// Marker type indicating the default trie [`Flavor`] to use for a given
112/// [`ByteOrder`] and [`Size`].
113pub struct DefaultFlavor<O = DefaultSize>(PhantomData<O>)
114where
115    O: Size;
116
117impl<O> Flavor for DefaultFlavor<O>
118where
119    O: Size,
120{
121    type String<E>
122        = Ref<[u8], E, O>
123    where
124        E: ByteOrder;
125
126    type Values<T, E>
127        = Ref<[T], E, O>
128    where
129        T: ZeroCopy,
130        E: ByteOrder;
131
132    type Children<T, E>
133        = Ref<[T], E, O>
134    where
135        T: ZeroCopy,
136        E: ByteOrder;
137}
138
139/// A stored reference to a trie.
140#[derive(ZeroCopy)]
141#[zero_copy(crate)]
142#[repr(C)]
143pub struct TrieRef<T, E = DefaultEndian, F = DefaultFlavor>
144where
145    T: ZeroCopy,
146    E: ByteOrder,
147    F: Flavor,
148{
149    links: LinksRef<T, E, F>,
150}
151
152impl<T, E, F> TrieRef<T, E, F>
153where
154    T: ZeroCopy,
155    E: ByteOrder,
156    F: Flavor,
157{
158    /// Debug print the current trie.
159    ///
160    /// This treats the keys as strings, with illegal unicode sequences being
161    /// replaced with the `U+FFFD` escape sequence.
162    ///
163    /// # Examples
164    ///
165    /// ```
166    /// use musli_zerocopy::{trie, OwnedBuf};
167    ///
168    /// let mut buf = OwnedBuf::new();
169    /// let a = buf.store(b"\xe2\x28\xa1")?.array_into_slice()?;
170    /// let b = buf.store_unsized("食べない")?;
171    ///
172    /// let mut trie = trie::Builder::new();
173    ///
174    /// trie.insert(&buf, b, 2)?;
175    /// trie.insert(&buf, a, 1)?;
176    ///
177    /// let trie = trie.build(&mut buf)?;
178    /// assert_eq!(format!("{:?}", trie.debug(&buf)), "{\"�(�\": 1, \"食べない\": 2}");
179    /// # Ok::<_, musli_zerocopy::Error>(())
180    /// ```
181    #[cfg(feature = "alloc")]
182    pub fn debug<'a, 'buf>(&'a self, buf: &'buf Buf) -> Debug<'a, 'buf, T, E, F>
183    where
184        T: fmt::Debug,
185    {
186        Debug { trie: self, buf }
187    }
188
189    /// Debug print the current trie, with a fixed iteration depth of `N`.
190    ///
191    /// This treats the keys as strings, with illegal unicode sequences being
192    /// replaced with the `U+FFFD` escape sequence.
193    ///
194    /// # Examples
195    ///
196    /// ```
197    /// use musli_zerocopy::{trie, OwnedBuf};
198    ///
199    /// let mut buf = OwnedBuf::new();
200    /// let a = buf.store(b"\xe2\x28\xa1")?.array_into_slice()?;
201    /// let b = buf.store_unsized("食べない")?;
202    ///
203    /// let mut trie = trie::Builder::new();
204    ///
205    /// trie.insert(&buf, b, 2)?;
206    /// trie.insert(&buf, a, 1)?;
207    ///
208    /// let trie = trie.build(&mut buf)?;
209    /// assert_eq!(format!("{:?}", trie.debug_fixed::<16>(&buf)), "{\"�(�\": 1, \"食べない\": 2}");
210    /// # Ok::<_, musli_zerocopy::Error>(())
211    /// ```
212    pub fn debug_fixed<'a, 'buf, const N: usize>(
213        &'a self,
214        buf: &'buf Buf,
215    ) -> DebugFixed<'a, 'buf, N, T, E, F>
216    where
217        T: fmt::Debug,
218    {
219        DebugFixed { trie: self, buf }
220    }
221
222    /// Get all values associated with the given string.
223    ///
224    /// # Examples
225    ///
226    /// ```
227    /// use musli_zerocopy::{trie, OwnedBuf};
228    ///
229    /// let mut buf = OwnedBuf::new();
230    ///
231    /// let values = [
232    ///     (buf.store_unsized("work")?, 1),
233    ///     (buf.store_unsized("worker")?, 2),
234    ///     (buf.store_unsized("workers")?, 3),
235    ///     (buf.store_unsized("working")?, 4),
236    ///     (buf.store_unsized("working")?, 5),
237    ///     (buf.store_unsized("working man")?, 6),
238    /// ];
239    ///
240    /// let trie = trie::store(&mut buf, values)?;
241    ///
242    /// assert_eq!(trie.get(&buf, "aard")?, None);
243    /// assert_eq!(trie.get(&buf, "worker")?, Some(&[2][..]));
244    /// assert_eq!(trie.get(&buf, "working")?, Some(&[4, 5][..]));
245    /// # Ok::<_, musli_zerocopy::Error>(())
246    /// ```
247    pub fn get<'buf, S>(&self, buf: &'buf Buf, string: &S) -> Result<Option<&'buf [T]>, Error>
248    where
249        S: ?Sized + AsRef<[u8]>,
250    {
251        let mut this = self.links;
252        let mut string = string.as_ref();
253
254        loop {
255            let search =
256                binary_search_by(buf, this.children, |c| Ok(buf.load(c.string)?.cmp(string)))?;
257
258            match search {
259                BinarySearch::Found(n) => {
260                    let child = this.children.get_unchecked(n);
261                    let child = buf.load(child)?;
262                    let values = buf.load(child.links.values)?;
263                    return Ok(Some(values));
264                }
265                BinarySearch::Missing(0) => {
266                    return Ok(None);
267                }
268                BinarySearch::Missing(n) => {
269                    let child = this.children.get_unchecked(n - 1);
270                    let child = buf.load(child)?;
271
272                    // Find common prefix and split nodes if necessary.
273                    let prefix = prefix(buf.load(child.string)?, string);
274
275                    if prefix == 0 {
276                        return Ok(None);
277                    }
278
279                    string = &string[prefix..];
280                    this = child.links;
281                }
282            };
283        }
284    }
285
286    /// Construct an iterator over all values in the trie.
287    ///
288    /// Note that the iteration order is unspecified and might change in future
289    /// versions.
290    ///
291    /// # Errors
292    ///
293    /// This errors in case the trie being iterated over is structurally
294    /// invalid.
295    ///
296    /// # Examples
297    ///
298    /// ```
299    /// use musli_zerocopy::{trie, OwnedBuf};
300    ///
301    /// let mut buf = OwnedBuf::new();
302    ///
303    /// let values = [
304    ///     (buf.store_unsized("work")?, 1),
305    ///     (buf.store_unsized("worker")?, 2),
306    ///     (buf.store_unsized("workers")?, 3),
307    ///     (buf.store_unsized("working")?, 4),
308    ///     (buf.store_unsized("working")?, 5),
309    ///     (buf.store_unsized("working man")?, 6),
310    ///     (buf.store_unsized("run")?, 7),
311    ///     (buf.store_unsized("running")?, 8),
312    /// ];
313    ///
314    /// let trie = trie::store(&mut buf, values)?;
315    ///
316    /// let mut values = trie.values(&buf).collect::<Result<Vec<_>, _>>()?;
317    /// values.sort();
318    /// assert!(values.into_iter().copied().eq([1, 2, 3, 4, 5, 6, 7, 8]));
319    /// # Ok::<_, musli_zerocopy::Error>(())
320    /// ```
321    #[cfg(feature = "alloc")]
322    pub fn values<'buf>(&self, buf: &'buf Buf) -> Values<'buf, T, E, F> {
323        Values {
324            iter: Walk::find(buf, self.links, &[]),
325        }
326    }
327
328    /// Construct an iterator over all values in the trie using a fixed max
329    /// iteration depth of `N`.
330    ///
331    /// Note that the iteration order is unspecified and might change in future
332    /// versions.
333    ///
334    /// # Errors
335    ///
336    /// This errors in case the trie being iterated over is structurally invalid
337    /// or if the iteration depth exceeds `N`.
338    ///
339    /// # Examples
340    ///
341    /// ```
342    /// use musli_zerocopy::{trie, OwnedBuf};
343    ///
344    /// let mut buf = OwnedBuf::new();
345    ///
346    /// let values = [
347    ///     (buf.store_unsized("work")?, 1),
348    ///     (buf.store_unsized("worker")?, 2),
349    ///     (buf.store_unsized("workers")?, 3),
350    ///     (buf.store_unsized("working")?, 4),
351    ///     (buf.store_unsized("working")?, 5),
352    ///     (buf.store_unsized("working man")?, 6),
353    ///     (buf.store_unsized("run")?, 7),
354    ///     (buf.store_unsized("running")?, 8),
355    /// ];
356    ///
357    /// let trie = trie::store(&mut buf, values)?;
358    ///
359    /// let mut values = trie.values_fixed::<16>(&buf).collect::<Result<Vec<_>, _>>()?;
360    /// values.sort();
361    /// assert!(values.into_iter().copied().eq([1, 2, 3, 4, 5, 6, 7, 8]));
362    /// # Ok::<_, musli_zerocopy::Error>(())
363    /// ```
364    pub fn values_fixed<'buf, const N: usize>(
365        &self,
366        buf: &'buf Buf,
367    ) -> ValuesFixed<'buf, N, T, E, F> {
368        ValuesFixed {
369            iter: Walk::find(buf, self.links, &[]),
370        }
371    }
372
373    /// Construct an iterator over values that are inside of the specified
374    /// `prefix` in the trie.
375    ///
376    /// Note that the iteration order is unspecified and might change in future
377    /// versions.
378    ///
379    /// # Errors
380    ///
381    /// This errors in case the trie being iterated over is structurally
382    /// invalid.
383    ///
384    /// # Examples
385    ///
386    /// ```
387    /// use musli_zerocopy::{trie, OwnedBuf};
388    ///
389    /// let mut buf = OwnedBuf::new();
390    ///
391    /// let values = [
392    ///     (buf.store_unsized("work")?, 1),
393    ///     (buf.store_unsized("worker")?, 2),
394    ///     (buf.store_unsized("workers")?, 3),
395    ///     (buf.store_unsized("working")?, 4),
396    ///     (buf.store_unsized("working")?, 5),
397    ///     (buf.store_unsized("working man")?, 6),
398    ///     (buf.store_unsized("run")?, 7),
399    ///     (buf.store_unsized("running")?, 8),
400    /// ];
401    ///
402    /// let trie = trie::store(&mut buf, values)?;
403    ///
404    /// let values = trie.values_in(&buf, "workin").collect::<Result<Vec<_>, _>>()?;
405    /// assert!(values.into_iter().copied().eq([4, 5, 6]));
406    ///
407    /// let values = trie.values_in(&buf, "wor").collect::<Result<Vec<_>, _>>()?;
408    /// assert!(values.into_iter().copied().eq([1, 2, 3, 4, 5, 6]));
409    ///
410    /// let values = trie.values_in(&buf, "runn").collect::<Result<Vec<_>, _>>()?;
411    /// assert!(values.into_iter().copied().eq([8]));
412    /// # Ok::<_, musli_zerocopy::Error>(())
413    /// ```
414    #[cfg(feature = "alloc")]
415    pub fn values_in<'a, 'buf, S>(
416        &self,
417        buf: &'buf Buf,
418        prefix: &'a S,
419    ) -> ValuesIn<'a, 'buf, T, E, F>
420    where
421        S: ?Sized + AsRef<[u8]>,
422    {
423        ValuesIn {
424            iter: Walk::find(buf, self.links, prefix.as_ref()),
425        }
426    }
427
428    /// Construct an iterator over values that are inside of the specified
429    /// `prefix` in the trie using a fixed max iteration depth of `N`.
430    ///
431    /// Note that the iteration order is unspecified and might change in future
432    /// versions.
433    ///
434    /// # Errors
435    ///
436    /// This errors in case the trie being iterated over is structurally
437    /// invalid or if the iteration depth exceeds `N`.
438    ///
439    /// # Examples
440    ///
441    /// ```
442    /// use musli_zerocopy::{trie, OwnedBuf};
443    ///
444    /// let mut buf = OwnedBuf::new();
445    ///
446    /// let values = [
447    ///     (buf.store_unsized("work")?, 1),
448    ///     (buf.store_unsized("worker")?, 2),
449    ///     (buf.store_unsized("workers")?, 3),
450    ///     (buf.store_unsized("working")?, 4),
451    ///     (buf.store_unsized("working")?, 5),
452    ///     (buf.store_unsized("working man")?, 6),
453    ///     (buf.store_unsized("run")?, 7),
454    ///     (buf.store_unsized("running")?, 8),
455    /// ];
456    ///
457    /// let trie = trie::store(&mut buf, values)?;
458    ///
459    /// let values = trie.values_in_fixed::<16, _>(&buf, "workin").collect::<Result<Vec<_>, _>>()?;
460    /// assert!(values.into_iter().copied().eq([4, 5, 6]));
461    ///
462    /// let values = trie.values_in_fixed::<16, _>(&buf, "wor").collect::<Result<Vec<_>, _>>()?;
463    /// assert!(values.into_iter().copied().eq([1, 2, 3, 4, 5, 6]));
464    ///
465    /// let values = trie.values_in_fixed::<16, _>(&buf, "runn").collect::<Result<Vec<_>, _>>()?;
466    /// assert!(values.into_iter().copied().eq([8]));
467    /// # Ok::<_, musli_zerocopy::Error>(())
468    /// ```
469    pub fn values_in_fixed<'a, 'buf, const N: usize, S>(
470        &self,
471        buf: &'buf Buf,
472        prefix: &'a S,
473    ) -> ValuesInFixed<'a, 'buf, N, T, E, F>
474    where
475        S: ?Sized + AsRef<[u8]>,
476    {
477        ValuesInFixed {
478            iter: Walk::find(buf, self.links, prefix.as_ref()),
479        }
480    }
481
482    /// Construct an iterator over all entries in the trie.
483    ///
484    /// Note that the iteration order is unspecified and might change in future
485    /// versions.
486    ///
487    /// # Errors
488    ///
489    /// This errors in case the trie being iterated over is structurally
490    /// invalid.
491    ///
492    /// # Examples
493    ///
494    /// ```
495    /// use std::str::from_utf8;
496    ///
497    /// use anyhow::Result;
498    /// use musli_zerocopy::{trie, OwnedBuf};
499    ///
500    /// // Helper to convert output to utf-8.
501    /// fn to_utf8<'buf, E>(result: Result<(&'buf [u8], &'buf i32), E>) -> Result<(&'buf str, i32)>
502    /// where
503    ///     anyhow::Error: From<E>
504    /// {
505    ///     let (k, v) = result?;
506    ///     Ok((from_utf8(k)?, *v))
507    /// }
508    ///
509    /// let mut buf = OwnedBuf::new();
510    ///
511    /// let values = [
512    ///     (buf.store_unsized("work")?, 1),
513    ///     (buf.store_unsized("worker")?, 2),
514    ///     (buf.store_unsized("workers")?, 3),
515    ///     (buf.store_unsized("working")?, 4),
516    ///     (buf.store_unsized("working")?, 5),
517    ///     (buf.store_unsized("working man")?, 6),
518    ///     (buf.store_unsized("run")?, 7),
519    ///     (buf.store_unsized("running")?, 8),
520    /// ];
521    ///
522    /// let trie = trie::store(&mut buf, values)?;
523    ///
524    /// let mut values = trie.iter(&buf)
525    ///     .map(to_utf8)
526    ///     .collect::<Result<Vec<_>>>()?;
527    /// values.sort();
528    ///
529    /// assert_eq! {
530    ///     values,
531    ///     [
532    ///         ("run", 7),
533    ///         ("running", 8),
534    ///         ("work", 1),
535    ///         ("worker", 2),
536    ///         ("workers", 3),
537    ///         ("working", 4),
538    ///         ("working", 5),
539    ///         ("working man", 6),
540    ///     ]
541    /// };
542    /// # Ok::<_, anyhow::Error>(())
543    /// ```
544    #[cfg(feature = "alloc")]
545    pub fn iter<'buf>(&self, buf: &'buf Buf) -> Iter<'buf, T, E, F> {
546        Iter {
547            iter: Walk::find(buf, self.links, &[]),
548        }
549    }
550
551    /// Construct an iterator over all entries in the trie using a fixed max
552    /// iteration depth of `N`
553    ///
554    /// Note that the iteration order is unspecified and might change in future
555    /// versions.
556    ///
557    /// # Errors
558    ///
559    /// This errors in case the trie being iterated over is structurally
560    /// invalid or if the iteration depth exceeds `N`.
561    ///
562    /// # Examples
563    ///
564    /// ```
565    /// use std::str::from_utf8;
566    ///
567    /// use anyhow::Result;
568    /// use musli_zerocopy::{trie, OwnedBuf};
569    ///
570    /// // Helper to convert output to utf-8.
571    /// fn to_utf8<'buf, E>(result: Result<(&'buf [u8], &'buf i32), E>) -> Result<(&'buf str, i32)>
572    /// where
573    ///     anyhow::Error: From<E>
574    /// {
575    ///     let (k, v) = result?;
576    ///     Ok((from_utf8(k)?, *v))
577    /// }
578    ///
579    /// let mut buf = OwnedBuf::new();
580    ///
581    /// let values = [
582    ///     (buf.store_unsized("work")?, 1),
583    ///     (buf.store_unsized("worker")?, 2),
584    ///     (buf.store_unsized("workers")?, 3),
585    ///     (buf.store_unsized("working")?, 4),
586    ///     (buf.store_unsized("working")?, 5),
587    ///     (buf.store_unsized("working man")?, 6),
588    ///     (buf.store_unsized("run")?, 7),
589    ///     (buf.store_unsized("running")?, 8),
590    /// ];
591    ///
592    /// let trie = trie::store(&mut buf, values)?;
593    ///
594    /// let mut values = trie.iter_fixed::<16>(&buf)
595    ///     .map(to_utf8)
596    ///     .collect::<Result<Vec<_>>>()?;
597    /// values.sort();
598    ///
599    /// assert_eq! {
600    ///     values,
601    ///     [
602    ///         ("run", 7),
603    ///         ("running", 8),
604    ///         ("work", 1),
605    ///         ("worker", 2),
606    ///         ("workers", 3),
607    ///         ("working", 4),
608    ///         ("working", 5),
609    ///         ("working man", 6),
610    ///     ]
611    /// };
612    /// # Ok::<_, anyhow::Error>(())
613    /// ```
614    pub fn iter_fixed<'buf, const N: usize>(&self, buf: &'buf Buf) -> IterFixed<'buf, N, T, E, F> {
615        IterFixed {
616            iter: Walk::find(buf, self.links, &[]),
617        }
618    }
619
620    /// Construct an iterator over all matching string prefixes in the trie
621    /// which also returns the string of the entries.
622    ///
623    /// Note that the iteration order is unspecified and might change in future
624    /// versions.
625    ///
626    /// # Errors
627    ///
628    /// This errors in case the trie being iterated over is structurally
629    /// invalid.
630    ///
631    /// # Examples
632    ///
633    /// ```
634    /// use std::str::from_utf8;
635    ///
636    /// use anyhow::Result;
637    /// use musli_zerocopy::{trie, OwnedBuf};
638    ///
639    /// // Helper to convert output to utf-8.
640    /// fn to_utf8<'buf, E>(result: Result<(&'buf [u8], &'buf i32), E>) -> Result<(&'buf str, i32)>
641    /// where
642    ///     anyhow::Error: From<E>
643    /// {
644    ///     let (k, v) = result?;
645    ///     Ok((from_utf8(k)?, *v))
646    /// }
647    ///
648    /// let mut buf = OwnedBuf::new();
649    ///
650    /// let values = [
651    ///     (buf.store_unsized("work")?, 1),
652    ///     (buf.store_unsized("worker")?, 2),
653    ///     (buf.store_unsized("workers")?, 3),
654    ///     (buf.store_unsized("working")?, 4),
655    ///     (buf.store_unsized("working")?, 5),
656    ///     (buf.store_unsized("working man")?, 6),
657    ///     (buf.store_unsized("run")?, 7),
658    ///     (buf.store_unsized("running")?, 8),
659    /// ];
660    ///
661    /// let trie = trie::store(&mut buf, values)?;
662    ///
663    /// let mut values = trie
664    ///     .iter_in(&buf, "workin")
665    ///     .map(to_utf8)
666    ///     .collect::<Result<Vec<_>>>()?;
667    /// values.sort();
668    ///
669    /// assert_eq!(values, [("working", 4), ("working", 5), ("working man", 6)]);
670    ///
671    /// let mut values = trie
672    ///     .iter_in(&buf, "wor")
673    ///     .map(to_utf8)
674    ///     .collect::<Result<Vec<_>>>()?;
675    /// values.sort();
676    ///
677    /// assert_eq! {
678    ///     values,
679    ///     [
680    ///         ("work", 1),
681    ///         ("worker", 2),
682    ///         ("workers", 3),
683    ///         ("working", 4),
684    ///         ("working", 5),
685    ///         ("working man", 6),
686    ///     ]
687    /// };
688    ///
689    /// let mut values = trie
690    ///     .iter_in(&buf, "runn")
691    ///     .map(to_utf8)
692    ///     .collect::<Result<Vec<_>>>()?;
693    /// values.sort();
694    ///
695    /// assert_eq!(values, [("running", 8)]);
696    /// # Ok::<_, anyhow::Error>(())
697    /// ```
698    #[cfg(feature = "alloc")]
699    pub fn iter_in<'a, 'buf, S>(&self, buf: &'buf Buf, prefix: &'a S) -> IterIn<'a, 'buf, T, E, F>
700    where
701        S: ?Sized + AsRef<[u8]>,
702    {
703        IterIn {
704            iter: Walk::find(buf, self.links, prefix.as_ref()),
705        }
706    }
707
708    /// Construct an iterator over all matching string prefixes in the trie
709    /// which also returns the string of the entries using a fixed max iteration
710    /// depth of `N`.
711    ///
712    /// Note that the iteration order is unspecified and might change in future
713    /// versions.
714    ///
715    /// # Errors
716    ///
717    /// This errors in case the trie being iterated over is structurally
718    /// invalid or if the iteration depth exceeds `N`.
719    ///
720    /// # Examples
721    ///
722    /// ```
723    /// use std::str::from_utf8;
724    ///
725    /// use anyhow::Result;
726    /// use musli_zerocopy::{trie, OwnedBuf};
727    ///
728    /// // Helper to convert output to utf-8.
729    /// fn to_utf8<'buf, E>(result: Result<(&'buf [u8], &'buf i32), E>) -> Result<(&'buf str, i32)>
730    /// where
731    ///     anyhow::Error: From<E>
732    /// {
733    ///     let (k, v) = result?;
734    ///     Ok((from_utf8(k)?, *v))
735    /// }
736    ///
737    /// let mut buf = OwnedBuf::new();
738    ///
739    /// let values = [
740    ///     (buf.store_unsized("work")?, 1),
741    ///     (buf.store_unsized("worker")?, 2),
742    ///     (buf.store_unsized("workers")?, 3),
743    ///     (buf.store_unsized("working")?, 4),
744    ///     (buf.store_unsized("working")?, 5),
745    ///     (buf.store_unsized("working man")?, 6),
746    ///     (buf.store_unsized("run")?, 7),
747    ///     (buf.store_unsized("running")?, 8),
748    /// ];
749    ///
750    /// let trie = trie::store(&mut buf, values)?;
751    ///
752    /// let mut values = trie
753    ///     .iter_in_fixed::<16, _>(&buf, "workin")
754    ///     .map(to_utf8)
755    ///     .collect::<Result<Vec<_>>>()?;
756    /// values.sort();
757    ///
758    /// assert_eq!(values, [("working", 4), ("working", 5), ("working man", 6)]);
759    ///
760    /// let mut values = trie
761    ///     .iter_in_fixed::<16, _>(&buf, "wor")
762    ///     .map(to_utf8)
763    ///     .collect::<Result<Vec<_>>>()?;
764    /// values.sort();
765    ///
766    /// assert_eq! {
767    ///     values,
768    ///     [
769    ///         ("work", 1),
770    ///         ("worker", 2),
771    ///         ("workers", 3),
772    ///         ("working", 4),
773    ///         ("working", 5),
774    ///         ("working man", 6),
775    ///     ]
776    /// };
777    ///
778    /// let mut values = trie
779    ///     .iter_in_fixed::<16, _>(&buf, "runn")
780    ///     .map(to_utf8)
781    ///     .collect::<Result<Vec<_>>>()?;
782    /// values.sort();
783    ///
784    /// assert_eq!(values, [("running", 8)]);
785    /// # Ok::<_, anyhow::Error>(())
786    /// ```
787    pub fn iter_in_fixed<'a, 'buf, const N: usize, S>(
788        &self,
789        buf: &'buf Buf,
790        prefix: &'a S,
791    ) -> IterInFixed<'a, 'buf, N, T, E, F>
792    where
793        S: ?Sized + AsRef<[u8]>,
794    {
795        IterInFixed {
796            iter: Walk::find(buf, self.links, prefix.as_ref()),
797        }
798    }
799}
800
801/// An iterator over values matching a `prefix` in a [`TrieRef`].
802///
803/// See [`TrieRef::values_in()`].
804#[cfg(feature = "alloc")]
805pub struct ValuesIn<'a, 'buf, T, E, F>
806where
807    T: ZeroCopy,
808    E: ByteOrder,
809    F: Flavor,
810{
811    iter: Walk<'a, 'buf, T, E, F, Vec<StackEntry<'buf, T, E, F>>>,
812}
813
814#[cfg(feature = "alloc")]
815impl<'buf, T, E, F> Iterator for ValuesIn<'_, 'buf, T, E, F>
816where
817    T: ZeroCopy,
818    E: ByteOrder,
819    F: Flavor,
820{
821    type Item = Result<&'buf T, Error>;
822
823    #[inline]
824    fn next(&mut self) -> Option<Self::Item> {
825        let (_, value) = match self.iter.poll() {
826            Ok(entry) => entry?,
827            Err(error) => return Some(Err(error)),
828        };
829
830        Some(Ok(value))
831    }
832}
833
834/// An iterator over values matching a `prefix` in a [`TrieRef`] using a fixed
835/// max iteration depth of `N`
836///
837/// See [`TrieRef::values_in_fixed()`].
838pub struct ValuesInFixed<'a, 'buf, const N: usize, T, E, F>
839where
840    T: ZeroCopy,
841    E: ByteOrder,
842    F: Flavor,
843{
844    iter: Walk<'a, 'buf, T, E, F, ArrayStack<StackEntry<'buf, T, E, F>, N>>,
845}
846
847impl<'buf, const N: usize, T, E, F> Iterator for ValuesInFixed<'_, 'buf, N, T, E, F>
848where
849    T: ZeroCopy,
850    E: ByteOrder,
851    F: Flavor,
852{
853    type Item = Result<&'buf T, Error>;
854
855    #[inline]
856    fn next(&mut self) -> Option<Self::Item> {
857        let (_, value) = match self.iter.poll() {
858            Ok(entry) => entry?,
859            Err(error) => return Some(Err(error)),
860        };
861
862        Some(Ok(value))
863    }
864}
865
866/// An iterator over all values in a [`TrieRef`].
867///
868/// See [`TrieRef::values()`].
869#[cfg(feature = "alloc")]
870pub struct Values<'buf, T, E, F>
871where
872    T: ZeroCopy,
873    E: ByteOrder,
874    F: Flavor,
875{
876    iter: Walk<'static, 'buf, T, E, F, Vec<StackEntry<'buf, T, E, F>>>,
877}
878
879#[cfg(feature = "alloc")]
880impl<'buf, T, E, F> Iterator for Values<'buf, T, E, F>
881where
882    T: ZeroCopy,
883    E: ByteOrder,
884    F: Flavor,
885{
886    type Item = Result<&'buf T, Error>;
887
888    #[inline]
889    fn next(&mut self) -> Option<Self::Item> {
890        let (_, value) = match self.iter.poll() {
891            Ok(entry) => entry?,
892            Err(error) => return Some(Err(error)),
893        };
894
895        Some(Ok(value))
896    }
897}
898
899/// An iterator over all values in a [`TrieRef`] using a fixed max iteration
900/// depth of `N`
901///
902/// See [`TrieRef::values_fixed()`].
903pub struct ValuesFixed<'buf, const N: usize, T, E, F>
904where
905    T: ZeroCopy,
906    E: ByteOrder,
907    F: Flavor,
908{
909    iter: Walk<'static, 'buf, T, E, F, ArrayStack<StackEntry<'buf, T, E, F>, N>>,
910}
911
912impl<'buf, const N: usize, T, E, F> Iterator for ValuesFixed<'buf, N, T, E, F>
913where
914    T: ZeroCopy,
915    E: ByteOrder,
916    F: Flavor,
917{
918    type Item = Result<&'buf T, Error>;
919
920    #[inline]
921    fn next(&mut self) -> Option<Self::Item> {
922        let (_, value) = match self.iter.poll() {
923            Ok(entry) => entry?,
924            Err(error) => return Some(Err(error)),
925        };
926
927        Some(Ok(value))
928    }
929}
930
931/// An iterator over all entries in a [`TrieRef`].
932///
933/// See [`TrieRef::iter()`].
934#[cfg(feature = "alloc")]
935pub struct Iter<'buf, T, E, F>
936where
937    T: ZeroCopy,
938    E: ByteOrder,
939    F: Flavor,
940{
941    iter: Walk<'static, 'buf, T, E, F, Vec<StackEntry<'buf, T, E, F>>>,
942}
943
944#[cfg(feature = "alloc")]
945impl<'buf, T, E, F> Iterator for Iter<'buf, T, E, F>
946where
947    T: ZeroCopy,
948    E: ByteOrder,
949    F: Flavor,
950{
951    type Item = Result<(&'buf [u8], &'buf T), Error>;
952
953    #[inline]
954    fn next(&mut self) -> Option<Self::Item> {
955        self.iter.poll().transpose()
956    }
957}
958
959/// An iterator over all entries in a [`TrieRef`] using a fixed max iteration
960/// depth of `N`
961///
962/// See [`TrieRef::iter_fixed()`].
963pub struct IterFixed<'buf, const N: usize, T, E, F>
964where
965    T: ZeroCopy,
966    E: ByteOrder,
967    F: Flavor,
968{
969    iter: Walk<'static, 'buf, T, E, F, ArrayStack<StackEntry<'buf, T, E, F>, N>>,
970}
971
972impl<'buf, const N: usize, T, E, F> Iterator for IterFixed<'buf, N, T, E, F>
973where
974    T: ZeroCopy,
975    E: ByteOrder,
976    F: Flavor,
977{
978    type Item = Result<(&'buf [u8], &'buf T), Error>;
979
980    #[inline]
981    fn next(&mut self) -> Option<Self::Item> {
982        self.iter.poll().transpose()
983    }
984}
985
986/// An iterator over all entries inside of a `prefix` in a [`TrieRef`].
987///
988/// See [`TrieRef::iter_in()`].
989#[cfg(feature = "alloc")]
990pub struct IterIn<'a, 'buf, T, E, F>
991where
992    T: ZeroCopy,
993    E: ByteOrder,
994    F: Flavor,
995{
996    iter: Walk<'a, 'buf, T, E, F, Vec<StackEntry<'buf, T, E, F>>>,
997}
998
999#[cfg(feature = "alloc")]
1000impl<'buf, T, E, F> Iterator for IterIn<'_, 'buf, T, E, F>
1001where
1002    T: ZeroCopy,
1003    E: ByteOrder,
1004    F: Flavor,
1005{
1006    type Item = Result<(&'buf [u8], &'buf T), Error>;
1007
1008    #[inline]
1009    fn next(&mut self) -> Option<Self::Item> {
1010        self.iter.poll().transpose()
1011    }
1012}
1013
1014/// An iterator over all entries inside of a `prefix` in a [`TrieRef`] using a
1015/// fixed max iteration depth of `N`
1016///
1017/// See [`TrieRef::iter_in_fixed()`].
1018pub struct IterInFixed<'a, 'buf, const N: usize, T, E, F>
1019where
1020    T: ZeroCopy,
1021    E: ByteOrder,
1022    F: Flavor,
1023{
1024    iter: Walk<'a, 'buf, T, E, F, ArrayStack<StackEntry<'buf, T, E, F>, N>>,
1025}
1026
1027impl<'buf, const N: usize, T, E, F> Iterator for IterInFixed<'_, 'buf, N, T, E, F>
1028where
1029    T: ZeroCopy,
1030    E: ByteOrder,
1031    F: Flavor,
1032{
1033    type Item = Result<(&'buf [u8], &'buf T), Error>;
1034
1035    #[inline]
1036    fn next(&mut self) -> Option<Self::Item> {
1037        self.iter.poll().transpose()
1038    }
1039}
1040
1041/// Debug printing of a trie.
1042///
1043/// See [`TrieRef::debug()`].
1044#[cfg(feature = "alloc")]
1045pub struct Debug<'a, 'buf, T, E, F>
1046where
1047    T: ZeroCopy,
1048    E: ByteOrder,
1049    F: Flavor,
1050{
1051    trie: &'a TrieRef<T, E, F>,
1052    buf: &'buf Buf,
1053}
1054
1055#[cfg(feature = "alloc")]
1056impl<T, E, F> fmt::Debug for Debug<'_, '_, T, E, F>
1057where
1058    T: fmt::Debug + ZeroCopy,
1059    E: ByteOrder,
1060    F: Flavor,
1061{
1062    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1063        let mut f = f.debug_map();
1064
1065        for result in self.trie.iter(self.buf) {
1066            let (key, value) = result.map_err(|_| fmt::Error)?;
1067            f.entry(&LossyStr::new(key), value);
1068        }
1069
1070        f.finish()
1071    }
1072}
1073
1074/// Debug printing of a trie with a fixed iteration depth of `N`.
1075///
1076/// See [`TrieRef::debug_fixed()`].
1077pub struct DebugFixed<'a, 'buf, const N: usize, T, E, F>
1078where
1079    T: ZeroCopy,
1080    E: ByteOrder,
1081    F: Flavor,
1082{
1083    trie: &'a TrieRef<T, E, F>,
1084    buf: &'buf Buf,
1085}
1086
1087impl<const N: usize, T, E, F> fmt::Debug for DebugFixed<'_, '_, N, T, E, F>
1088where
1089    T: fmt::Debug + ZeroCopy,
1090    E: ByteOrder,
1091    F: Flavor,
1092{
1093    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1094        let mut f = f.debug_map();
1095
1096        for result in self.trie.iter_fixed::<N>(self.buf) {
1097            let (key, value) = result.map_err(|_| fmt::Error)?;
1098            f.entry(&LossyStr::new(key), value);
1099        }
1100
1101        f.finish()
1102    }
1103}
1104
1105impl<T, E, F> Clone for TrieRef<T, E, F>
1106where
1107    T: ZeroCopy,
1108    E: ByteOrder,
1109    F: Flavor,
1110    F::Values<T, E>: Clone,
1111    F::Children<NodeRef<T, E, F>, E>: Clone,
1112{
1113    #[inline]
1114    fn clone(&self) -> Self {
1115        *self
1116    }
1117}
1118
1119impl<T, E, F> Copy for TrieRef<T, E, F>
1120where
1121    T: ZeroCopy,
1122    E: ByteOrder,
1123    F: Flavor,
1124    F::Values<T, E>: Copy,
1125    F::Children<NodeRef<T, E, F>, E>: Copy,
1126{
1127}
1128
1129#[derive(ZeroCopy)]
1130#[zero_copy(crate)]
1131#[repr(C)]
1132struct LinksRef<T, E, F>
1133where
1134    T: ZeroCopy,
1135    E: ByteOrder,
1136    F: Flavor,
1137{
1138    values: F::Values<T, E>,
1139    children: F::Children<NodeRef<T, E, F>, E>,
1140}
1141
1142impl<T, E, F> Clone for LinksRef<T, E, F>
1143where
1144    T: ZeroCopy,
1145    E: ByteOrder,
1146    F: Flavor,
1147    F::Values<T, E>: Copy,
1148    F::Children<NodeRef<T, E, F>, E>: Copy,
1149{
1150    #[inline]
1151    fn clone(&self) -> Self {
1152        *self
1153    }
1154}
1155
1156impl<T, E, F> Copy for LinksRef<T, E, F>
1157where
1158    T: ZeroCopy,
1159    E: ByteOrder,
1160    F: Flavor,
1161    F::Values<T, E>: Copy,
1162    F::Children<NodeRef<T, E, F>, E>: Copy,
1163{
1164}
1165
1166#[derive(ZeroCopy)]
1167#[zero_copy(crate)]
1168#[repr(C)]
1169struct NodeRef<T, E, F>
1170where
1171    T: ZeroCopy,
1172    E: ByteOrder,
1173    F: Flavor,
1174{
1175    string: F::String<E>,
1176    links: LinksRef<T, E, F>,
1177}
1178
1179/// Calculate the common prefix between two strings.
1180fn prefix(a: &[u8], b: &[u8]) -> usize {
1181    a.iter().zip(b.iter()).take_while(|(a, b)| a == b).count()
1182}