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}