Coverage Report

Created: 2026-01-10 06:44

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/zerotrie-0.1.3/src/zerotrie.rs
Line
Count
Source
1
// This file is part of ICU4X. For terms of use, please see the file
2
// called LICENSE at the top level of the ICU4X source tree
3
// (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ).
4
5
use crate::reader;
6
7
use core::borrow::Borrow;
8
9
#[cfg(feature = "alloc")]
10
use crate::{builder::bytestr::ByteStr, builder::nonconst::ZeroTrieBuilder, error::Error};
11
#[cfg(feature = "alloc")]
12
use alloc::{boxed::Box, collections::BTreeMap, collections::VecDeque, string::String, vec::Vec};
13
#[cfg(feature = "litemap")]
14
use litemap::LiteMap;
15
16
/// A data structure that compactly maps from byte sequences to integers.
17
///
18
/// There are several variants of `ZeroTrie` which are very similar but are optimized
19
/// for different use cases:
20
///
21
/// - [`ZeroTrieSimpleAscii`] is the most compact structure. Very fast for small data.
22
///   Only stores ASCII-encoded strings. Can be const-constructed!
23
/// - [`ZeroTriePerfectHash`] is also compact, but it also supports arbitrary binary
24
///   strings. It also scales better to large data. Cannot be const-constructed.
25
/// - [`ZeroTrieExtendedCapacity`] can be used if more than 2^32 bytes are required.
26
///
27
/// You can create a `ZeroTrie` directly, in which case the most appropriate
28
/// backing implementation will be chosen.
29
///
30
/// # Backing Store
31
///
32
/// The data structure has a flexible backing data store. The only requirement for most
33
/// functionality is that it implement `AsRef<[u8]>`. All of the following are valid
34
/// ZeroTrie types:
35
///
36
/// - `ZeroTrie<[u8]>` (dynamically sized type: must be stored in a reference or Box)
37
/// - `ZeroTrie<&[u8]>` (borrows its data from a u8 buffer)
38
/// - `ZeroTrie<Vec<u8>>` (fully owned data)
39
/// - `ZeroTrie<ZeroVec<u8>>` (the recommended borrowed-or-owned signature)
40
/// - `Cow<ZeroTrie<[u8]>>` (another borrowed-or-owned signature)
41
/// - `ZeroTrie<Cow<[u8]>>` (another borrowed-or-owned signature)
42
///
43
/// # Examples
44
///
45
/// ```
46
/// use litemap::LiteMap;
47
/// use zerotrie::ZeroTrie;
48
///
49
/// let mut map = LiteMap::<&[u8], usize>::new_vec();
50
/// map.insert("foo".as_bytes(), 1);
51
/// map.insert("bar".as_bytes(), 2);
52
/// map.insert("bazzoo".as_bytes(), 3);
53
///
54
/// let trie = ZeroTrie::try_from(&map)?;
55
///
56
/// assert_eq!(trie.get("foo"), Some(1));
57
/// assert_eq!(trie.get("bar"), Some(2));
58
/// assert_eq!(trie.get("bazzoo"), Some(3));
59
/// assert_eq!(trie.get("unknown"), None);
60
///
61
/// # Ok::<_, zerotrie::ZeroTrieError>(())
62
/// ```
63
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
64
// Note: The absence of the following derive does not cause any test failures in this crate
65
#[cfg_attr(feature = "yoke", derive(yoke::Yokeable))]
66
pub struct ZeroTrie<Store>(pub(crate) ZeroTrieFlavor<Store>);
67
68
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
69
pub(crate) enum ZeroTrieFlavor<Store> {
70
    SimpleAscii(ZeroTrieSimpleAscii<Store>),
71
    PerfectHash(ZeroTriePerfectHash<Store>),
72
    ExtendedCapacity(ZeroTrieExtendedCapacity<Store>),
73
}
74
75
/// A data structure that compactly maps from ASCII strings to integers.
76
///
77
/// For more information, see [`ZeroTrie`].
78
///
79
/// # Examples
80
///
81
/// ```
82
/// use litemap::LiteMap;
83
/// use zerotrie::ZeroTrieSimpleAscii;
84
///
85
/// let mut map = LiteMap::new_vec();
86
/// map.insert(&b"foo"[..], 1);
87
/// map.insert(b"bar", 2);
88
/// map.insert(b"bazzoo", 3);
89
///
90
/// let trie = ZeroTrieSimpleAscii::try_from(&map)?;
91
///
92
/// assert_eq!(trie.get(b"foo"), Some(1));
93
/// assert_eq!(trie.get(b"bar"), Some(2));
94
/// assert_eq!(trie.get(b"bazzoo"), Some(3));
95
/// assert_eq!(trie.get(b"unknown"), None);
96
///
97
/// # Ok::<_, zerotrie::ZeroTrieError>(())
98
/// ```
99
///
100
/// The trie can only store ASCII bytes; a string with non-ASCII always returns None:
101
///
102
/// ```
103
/// use zerotrie::ZeroTrieSimpleAscii;
104
///
105
/// // A trie with two values: "abc" and "abcdef"
106
/// let trie = ZeroTrieSimpleAscii::from_bytes(b"abc\x80def\x81");
107
///
108
/// assert!(matches!(trie.get(b"ab\xFF"), None));
109
/// ```
110
#[repr(transparent)]
111
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
112
#[cfg_attr(feature = "databake", derive(databake::Bake), databake(path = zerotrie))]
113
#[allow(clippy::exhaustive_structs)] // databake hidden fields
114
pub struct ZeroTrieSimpleAscii<Store: ?Sized> {
115
    #[doc(hidden)] // for databake, but there are no invariants
116
    pub store: Store,
117
}
118
119
impl<Store> ZeroTrieSimpleAscii<Store> {
120
    /// Wrap this specific ZeroTrie variant into a ZeroTrie.
121
    #[inline]
122
0
    pub const fn into_zerotrie(self) -> ZeroTrie<Store> {
123
0
        ZeroTrie(ZeroTrieFlavor::SimpleAscii(self))
124
0
    }
125
}
126
127
/// A data structure that compactly maps from ASCII strings to integers
128
/// in a case-insensitive way.
129
///
130
/// # Examples
131
///
132
/// ```
133
/// use litemap::LiteMap;
134
/// use zerotrie::ZeroAsciiIgnoreCaseTrie;
135
///
136
/// let mut map = LiteMap::new_vec();
137
/// map.insert(&b"foo"[..], 1);
138
/// map.insert(b"Bar", 2);
139
/// map.insert(b"Bazzoo", 3);
140
///
141
/// let trie = ZeroAsciiIgnoreCaseTrie::try_from(&map)?;
142
///
143
/// assert_eq!(trie.get(b"foo"), Some(1));
144
/// assert_eq!(trie.get(b"bar"), Some(2));
145
/// assert_eq!(trie.get(b"BAR"), Some(2));
146
/// assert_eq!(trie.get(b"bazzoo"), Some(3));
147
/// assert_eq!(trie.get(b"unknown"), None);
148
///
149
/// # Ok::<_, zerotrie::ZeroTrieError>(())
150
/// ```
151
///
152
/// Strings with different cases of the same character at the same offset are not allowed:
153
///
154
/// ```
155
/// use litemap::LiteMap;
156
/// use zerotrie::ZeroAsciiIgnoreCaseTrie;
157
///
158
/// let mut map = LiteMap::new_vec();
159
/// map.insert(&b"bar"[..], 1);
160
/// // OK: 'r' and 'Z' are different letters
161
/// map.insert(b"baZ", 2);
162
/// // Bad: we already inserted 'r' so we cannot also insert 'R' at the same position
163
/// map.insert(b"baR", 2);
164
///
165
/// ZeroAsciiIgnoreCaseTrie::try_from(&map).expect_err("mixed-case strings!");
166
/// ```
167
#[repr(transparent)]
168
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
169
#[cfg_attr(feature = "databake", derive(databake::Bake), databake(path = zerotrie))]
170
#[allow(clippy::exhaustive_structs)] // databake hidden fields
171
pub struct ZeroAsciiIgnoreCaseTrie<Store: ?Sized> {
172
    #[doc(hidden)] // for databake, but there are no invariants
173
    pub store: Store,
174
}
175
176
// Note: ZeroAsciiIgnoreCaseTrie is not a variant of ZeroTrie so there is no `into_zerotrie`
177
178
/// A data structure that compactly maps from byte strings to integers.
179
///
180
/// For more information, see [`ZeroTrie`].
181
///
182
/// # Examples
183
///
184
/// ```
185
/// use litemap::LiteMap;
186
/// use zerotrie::ZeroTriePerfectHash;
187
///
188
/// let mut map = LiteMap::<&[u8], usize>::new_vec();
189
/// map.insert("foo".as_bytes(), 1);
190
/// map.insert("bår".as_bytes(), 2);
191
/// map.insert("båzzøø".as_bytes(), 3);
192
///
193
/// let trie = ZeroTriePerfectHash::try_from(&map)?;
194
///
195
/// assert_eq!(trie.get("foo".as_bytes()), Some(1));
196
/// assert_eq!(trie.get("bår".as_bytes()), Some(2));
197
/// assert_eq!(trie.get("båzzøø".as_bytes()), Some(3));
198
/// assert_eq!(trie.get("bazzoo".as_bytes()), None);
199
///
200
/// # Ok::<_, zerotrie::ZeroTrieError>(())
201
/// ```
202
#[repr(transparent)]
203
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
204
#[cfg_attr(feature = "databake", derive(databake::Bake), databake(path = zerotrie))]
205
#[allow(clippy::exhaustive_structs)] // databake hidden fields
206
pub struct ZeroTriePerfectHash<Store: ?Sized> {
207
    #[doc(hidden)] // for databake, but there are no invariants
208
    pub store: Store,
209
}
210
211
impl<Store> ZeroTriePerfectHash<Store> {
212
    /// Wrap this specific ZeroTrie variant into a ZeroTrie.
213
    #[inline]
214
0
    pub const fn into_zerotrie(self) -> ZeroTrie<Store> {
215
0
        ZeroTrie(ZeroTrieFlavor::PerfectHash(self))
216
0
    }
217
}
218
219
/// A data structure that maps from a large number of byte strings to integers.
220
///
221
/// For more information, see [`ZeroTrie`].
222
#[repr(transparent)]
223
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
224
#[cfg_attr(feature = "databake", derive(databake::Bake), databake(path = zerotrie))]
225
#[allow(clippy::exhaustive_structs)] // databake hidden fields
226
pub struct ZeroTrieExtendedCapacity<Store: ?Sized> {
227
    #[doc(hidden)] // for databake, but there are no invariants
228
    pub store: Store,
229
}
230
231
impl<Store> ZeroTrieExtendedCapacity<Store> {
232
    /// Wrap this specific ZeroTrie variant into a ZeroTrie.
233
    #[inline]
234
0
    pub const fn into_zerotrie(self) -> ZeroTrie<Store> {
235
0
        ZeroTrie(ZeroTrieFlavor::ExtendedCapacity(self))
236
0
    }
237
}
238
239
macro_rules! impl_zerotrie_subtype {
240
    ($name:ident, $iter_ty:ty, $iter_fn:path, $cnv_fn:path) => {
241
        impl<Store> $name<Store> {
242
            /// Create a trie directly from a store.
243
            ///
244
            /// If the store does not contain valid bytes, unexpected behavior may occur.
245
            #[inline]
246
0
            pub const fn from_store(store: Store) -> Self {
247
0
                Self { store }
248
0
            }
Unexecuted instantiation: <zerotrie::zerotrie::ZeroAsciiIgnoreCaseTrie<zerovec::zerovec::ZeroVec<u8>>>::from_store
Unexecuted instantiation: <zerotrie::zerotrie::ZeroAsciiIgnoreCaseTrie<&[u8]>>::from_store
Unexecuted instantiation: <zerotrie::zerotrie::ZeroTriePerfectHash<zerovec::zerovec::ZeroVec<u8>>>::from_store
Unexecuted instantiation: <zerotrie::zerotrie::ZeroTrieExtendedCapacity<zerovec::zerovec::ZeroVec<u8>>>::from_store
Unexecuted instantiation: <zerotrie::zerotrie::ZeroTrieSimpleAscii<zerovec::zerovec::ZeroVec<u8>>>::from_store
Unexecuted instantiation: <zerotrie::zerotrie::ZeroAsciiIgnoreCaseTrie<alloc::boxed::Box<[u8]>>>::from_store
Unexecuted instantiation: <zerotrie::zerotrie::ZeroTriePerfectHash<alloc::boxed::Box<[u8]>>>::from_store
Unexecuted instantiation: <zerotrie::zerotrie::ZeroTrieExtendedCapacity<alloc::boxed::Box<[u8]>>>::from_store
Unexecuted instantiation: <zerotrie::zerotrie::ZeroTrieSimpleAscii<alloc::boxed::Box<[u8]>>>::from_store
249
            /// Takes the byte store from this trie.
250
            #[inline]
251
0
            pub fn take_store(self) -> Store {
252
0
                self.store
253
0
            }
Unexecuted instantiation: <zerotrie::zerotrie::ZeroAsciiIgnoreCaseTrie<_>>::take_store
Unexecuted instantiation: <zerotrie::zerotrie::ZeroTriePerfectHash<_>>::take_store
Unexecuted instantiation: <zerotrie::zerotrie::ZeroTrieExtendedCapacity<_>>::take_store
Unexecuted instantiation: <zerotrie::zerotrie::ZeroTrieSimpleAscii<_>>::take_store
254
            /// Converts this trie's store to a different store implementing the `From` trait.
255
            ///
256
            #[doc = concat!("For example, use this to change `", stringify!($name), "<Vec<u8>>` to `", stringify!($name), "<Cow<[u8]>>`.")]
257
            ///
258
            /// # Examples
259
            ///
260
            /// ```
261
            /// use std::borrow::Cow;
262
            #[doc = concat!("use zerotrie::", stringify!($name), ";")]
263
            ///
264
            #[doc = concat!("let trie: ", stringify!($name), "<Vec<u8>> = ", stringify!($name), "::from_bytes(b\"abc\\x85\").to_owned();")]
265
            #[doc = concat!("let cow: ", stringify!($name), "<Cow<[u8]>> = trie.convert_store();")]
266
            ///
267
            /// assert_eq!(cow.get(b"abc"), Some(5));
268
            /// ```
269
0
            pub fn convert_store<X: From<Store>>(self) -> $name<X> {
270
0
                $name::<X>::from_store(X::from(self.store))
271
0
            }
Unexecuted instantiation: <zerotrie::zerotrie::ZeroAsciiIgnoreCaseTrie<_>>::convert_store::<_>
Unexecuted instantiation: <zerotrie::zerotrie::ZeroTriePerfectHash<_>>::convert_store::<_>
Unexecuted instantiation: <zerotrie::zerotrie::ZeroTrieExtendedCapacity<_>>::convert_store::<_>
Unexecuted instantiation: <zerotrie::zerotrie::ZeroTrieSimpleAscii<_>>::convert_store::<_>
272
        }
273
        impl<Store> $name<Store>
274
        where
275
        Store: AsRef<[u8]> + ?Sized,
276
        {
277
            /// Queries the trie for a string.
278
0
            pub fn get<K>(&self, key: K) -> Option<usize> where K: AsRef<[u8]> {
279
                // TODO: Should this be AsRef or Borrow?
280
0
                reader::get_parameterized::<Self>(self.store.as_ref(), key.as_ref())
281
0
            }
Unexecuted instantiation: <zerotrie::zerotrie::ZeroAsciiIgnoreCaseTrie<zerovec::zerovec::ZeroVec<u8>>>::get::<&[u8]>
Unexecuted instantiation: <zerotrie::zerotrie::ZeroAsciiIgnoreCaseTrie<zerovec::zerovec::ZeroVec<u8>>>::get::<&str>
Unexecuted instantiation: <zerotrie::zerotrie::ZeroTriePerfectHash<zerovec::zerovec::ZeroVec<u8>>>::get::<&[u8]>
Unexecuted instantiation: <zerotrie::zerotrie::ZeroTrieExtendedCapacity<zerovec::zerovec::ZeroVec<u8>>>::get::<&[u8]>
Unexecuted instantiation: <zerotrie::zerotrie::ZeroTrieSimpleAscii<zerovec::zerovec::ZeroVec<u8>>>::get::<&[u8]>
Unexecuted instantiation: <zerotrie::zerotrie::ZeroAsciiIgnoreCaseTrie<_>>::get::<_>
Unexecuted instantiation: <zerotrie::zerotrie::ZeroTriePerfectHash<_>>::get::<_>
Unexecuted instantiation: <zerotrie::zerotrie::ZeroTrieExtendedCapacity<_>>::get::<_>
Unexecuted instantiation: <zerotrie::zerotrie::ZeroTrieSimpleAscii<_>>::get::<_>
282
            /// Returns `true` if the trie is empty.
283
            #[inline]
284
0
            pub fn is_empty(&self) -> bool {
285
0
                self.store.as_ref().is_empty()
286
0
            }
Unexecuted instantiation: <zerotrie::zerotrie::ZeroAsciiIgnoreCaseTrie<_>>::is_empty
Unexecuted instantiation: <zerotrie::zerotrie::ZeroTriePerfectHash<_>>::is_empty
Unexecuted instantiation: <zerotrie::zerotrie::ZeroTrieExtendedCapacity<_>>::is_empty
Unexecuted instantiation: <zerotrie::zerotrie::ZeroTrieSimpleAscii<_>>::is_empty
287
            /// Returns the size of the trie in number of bytes.
288
            ///
289
            /// To get the number of keys in the trie, use `.iter().count()`:
290
            ///
291
            /// ```
292
            #[doc = concat!("use zerotrie::", stringify!($name), ";")]
293
            ///
294
            /// // A trie with two values: "abc" and "abcdef"
295
            #[doc = concat!("let trie: &", stringify!($name), "<[u8]> = ", stringify!($name), "::from_bytes(b\"abc\\x80def\\x81\");")]
296
            ///
297
            /// assert_eq!(8, trie.byte_len());
298
            /// assert_eq!(2, trie.iter().count());
299
            /// ```
300
            #[inline]
301
0
            pub fn byte_len(&self) -> usize {
302
0
                self.store.as_ref().len()
303
0
            }
Unexecuted instantiation: <zerotrie::zerotrie::ZeroAsciiIgnoreCaseTrie<_>>::byte_len
Unexecuted instantiation: <zerotrie::zerotrie::ZeroTriePerfectHash<_>>::byte_len
Unexecuted instantiation: <zerotrie::zerotrie::ZeroTrieExtendedCapacity<_>>::byte_len
Unexecuted instantiation: <zerotrie::zerotrie::ZeroTrieSimpleAscii<_>>::byte_len
304
            /// Returns the bytes contained in the underlying store.
305
            #[inline]
306
0
            pub fn as_bytes(&self) -> &[u8] {
307
0
                self.store.as_ref()
308
0
            }
Unexecuted instantiation: <zerotrie::zerotrie::ZeroAsciiIgnoreCaseTrie<_>>::as_bytes
Unexecuted instantiation: <zerotrie::zerotrie::ZeroTriePerfectHash<_>>::as_bytes
Unexecuted instantiation: <zerotrie::zerotrie::ZeroTrieExtendedCapacity<_>>::as_bytes
Unexecuted instantiation: <zerotrie::zerotrie::ZeroTrieSimpleAscii<_>>::as_bytes
309
            /// Returns this trie as a reference transparent over a byte slice.
310
            #[inline]
311
0
            pub fn as_borrowed(&self) -> &$name<[u8]> {
312
0
                $name::from_bytes(self.store.as_ref())
313
0
            }
Unexecuted instantiation: <zerotrie::zerotrie::ZeroAsciiIgnoreCaseTrie<_>>::as_borrowed
Unexecuted instantiation: <zerotrie::zerotrie::ZeroTriePerfectHash<_>>::as_borrowed
Unexecuted instantiation: <zerotrie::zerotrie::ZeroTrieExtendedCapacity<_>>::as_borrowed
Unexecuted instantiation: <zerotrie::zerotrie::ZeroTrieSimpleAscii<_>>::as_borrowed
314
            /// Returns a trie with a store borrowing from this trie.
315
            #[inline]
316
0
            pub fn as_borrowed_slice(&self) -> $name<&[u8]> {
317
0
                $name::from_store(self.store.as_ref())
318
0
            }
Unexecuted instantiation: <zerotrie::zerotrie::ZeroAsciiIgnoreCaseTrie<zerovec::zerovec::ZeroVec<u8>>>::as_borrowed_slice
Unexecuted instantiation: <zerotrie::zerotrie::ZeroAsciiIgnoreCaseTrie<_>>::as_borrowed_slice
Unexecuted instantiation: <zerotrie::zerotrie::ZeroTriePerfectHash<_>>::as_borrowed_slice
Unexecuted instantiation: <zerotrie::zerotrie::ZeroTrieExtendedCapacity<_>>::as_borrowed_slice
Unexecuted instantiation: <zerotrie::zerotrie::ZeroTrieSimpleAscii<_>>::as_borrowed_slice
319
        }
320
        impl<Store> AsRef<$name<[u8]>> for $name<Store>
321
        where
322
        Store: AsRef<[u8]> + ?Sized,
323
        {
324
            #[inline]
325
0
            fn as_ref(&self) -> &$name<[u8]> {
326
0
                self.as_borrowed()
327
0
            }
Unexecuted instantiation: <zerotrie::zerotrie::ZeroAsciiIgnoreCaseTrie<_> as core::convert::AsRef<zerotrie::zerotrie::ZeroAsciiIgnoreCaseTrie<[u8]>>>::as_ref
Unexecuted instantiation: <zerotrie::zerotrie::ZeroTriePerfectHash<_> as core::convert::AsRef<zerotrie::zerotrie::ZeroTriePerfectHash<[u8]>>>::as_ref
Unexecuted instantiation: <zerotrie::zerotrie::ZeroTrieExtendedCapacity<_> as core::convert::AsRef<zerotrie::zerotrie::ZeroTrieExtendedCapacity<[u8]>>>::as_ref
Unexecuted instantiation: <zerotrie::zerotrie::ZeroTrieSimpleAscii<_> as core::convert::AsRef<zerotrie::zerotrie::ZeroTrieSimpleAscii<[u8]>>>::as_ref
328
        }
329
        #[cfg(feature = "alloc")]
330
        impl<Store> $name<Store>
331
        where
332
        Store: AsRef<[u8]> + ?Sized,
333
        {
334
            /// Converts a possibly-borrowed $name to an owned one.
335
            ///
336
            /// ✨ *Enabled with the `alloc` Cargo feature.*
337
            ///
338
            /// # Examples
339
            ///
340
            /// ```
341
            #[doc = concat!("use zerotrie::", stringify!($name), ";")]
342
            ///
343
            #[doc = concat!("let trie: &", stringify!($name), "<[u8]> = ", stringify!($name), "::from_bytes(b\"abc\\x85\");")]
344
            #[doc = concat!("let owned: ", stringify!($name), "<Vec<u8>> = trie.to_owned();")]
345
            ///
346
            /// assert_eq!(trie.get(b"abc"), Some(5));
347
            /// assert_eq!(owned.get(b"abc"), Some(5));
348
            /// ```
349
            #[inline]
350
0
            pub fn to_owned(&self) -> $name<Vec<u8>> {
351
0
                $name::from_store(
352
0
                    Vec::from(self.store.as_ref()),
353
                )
354
0
            }
Unexecuted instantiation: <zerotrie::zerotrie::ZeroAsciiIgnoreCaseTrie<_>>::to_owned
Unexecuted instantiation: <zerotrie::zerotrie::ZeroTriePerfectHash<_>>::to_owned
Unexecuted instantiation: <zerotrie::zerotrie::ZeroTrieExtendedCapacity<_>>::to_owned
Unexecuted instantiation: <zerotrie::zerotrie::ZeroTrieSimpleAscii<_>>::to_owned
355
            /// Returns an iterator over the key/value pairs in this trie.
356
            ///
357
            /// ✨ *Enabled with the `alloc` Cargo feature.*
358
            ///
359
            /// # Examples
360
            ///
361
            /// ```
362
            #[doc = concat!("use zerotrie::", stringify!($name), ";")]
363
            ///
364
            /// // A trie with two values: "abc" and "abcdef"
365
            #[doc = concat!("let trie: &", stringify!($name), "<[u8]> = ", stringify!($name), "::from_bytes(b\"abc\\x80def\\x81\");")]
366
            ///
367
            /// let mut it = trie.iter();
368
            /// assert_eq!(it.next(), Some(("abc".into(), 0)));
369
            /// assert_eq!(it.next(), Some(("abcdef".into(), 1)));
370
            /// assert_eq!(it.next(), None);
371
            /// ```
372
            #[inline]
373
0
            pub fn iter(&self) -> impl Iterator<Item = ($iter_ty, usize)> + '_ {
374
0
                 $iter_fn(self.as_bytes())
375
0
            }
Unexecuted instantiation: <zerotrie::zerotrie::ZeroAsciiIgnoreCaseTrie<_>>::iter
Unexecuted instantiation: <zerotrie::zerotrie::ZeroTriePerfectHash<_>>::iter
Unexecuted instantiation: <zerotrie::zerotrie::ZeroTrieExtendedCapacity<_>>::iter
Unexecuted instantiation: <zerotrie::zerotrie::ZeroTrieSimpleAscii<_>>::iter
376
        }
377
        impl $name<[u8]> {
378
            /// Casts from a byte slice to a reference to a trie with the same lifetime.
379
            ///
380
            /// If the bytes are not a valid trie, unexpected behavior may occur.
381
            #[inline]
382
0
            pub fn from_bytes(trie: &[u8]) -> &Self {
383
                // Safety: Self is repr(transparent) over [u8]
384
0
                unsafe { core::mem::transmute(trie) }
385
0
            }
Unexecuted instantiation: <zerotrie::zerotrie::ZeroAsciiIgnoreCaseTrie<[u8]>>::from_bytes
Unexecuted instantiation: <zerotrie::zerotrie::ZeroTriePerfectHash<[u8]>>::from_bytes
Unexecuted instantiation: <zerotrie::zerotrie::ZeroTrieExtendedCapacity<[u8]>>::from_bytes
Unexecuted instantiation: <zerotrie::zerotrie::ZeroTrieSimpleAscii<[u8]>>::from_bytes
386
        }
387
        #[cfg(feature = "alloc")]
388
        impl $name<Vec<u8>> {
389
0
            pub(crate) fn try_from_tuple_slice(items: &[(&ByteStr, usize)]) -> Result<Self, Error> {
390
                use crate::options::ZeroTrieWithOptions;
391
0
                ZeroTrieBuilder::<VecDeque<u8>>::from_sorted_tuple_slice(
392
0
                    items,
393
                    Self::OPTIONS,
394
                )
395
0
                .map(|s| Self {
396
0
                    store: s.to_bytes(),
397
0
                })
Unexecuted instantiation: <zerotrie::zerotrie::ZeroAsciiIgnoreCaseTrie<alloc::vec::Vec<u8>>>::try_from_tuple_slice::{closure#0}
Unexecuted instantiation: <zerotrie::zerotrie::ZeroTrieExtendedCapacity<alloc::vec::Vec<u8>>>::try_from_tuple_slice::{closure#0}
Unexecuted instantiation: <zerotrie::zerotrie::ZeroTriePerfectHash<alloc::vec::Vec<u8>>>::try_from_tuple_slice::{closure#0}
Unexecuted instantiation: <zerotrie::zerotrie::ZeroTrieSimpleAscii<alloc::vec::Vec<u8>>>::try_from_tuple_slice::{closure#0}
398
0
            }
Unexecuted instantiation: <zerotrie::zerotrie::ZeroAsciiIgnoreCaseTrie<alloc::vec::Vec<u8>>>::try_from_tuple_slice
Unexecuted instantiation: <zerotrie::zerotrie::ZeroTrieExtendedCapacity<alloc::vec::Vec<u8>>>::try_from_tuple_slice
Unexecuted instantiation: <zerotrie::zerotrie::ZeroTriePerfectHash<alloc::vec::Vec<u8>>>::try_from_tuple_slice
Unexecuted instantiation: <zerotrie::zerotrie::ZeroTrieSimpleAscii<alloc::vec::Vec<u8>>>::try_from_tuple_slice
399
        }
400
        #[cfg(feature = "alloc")]
401
        impl<'a, K> FromIterator<(K, usize)> for $name<Vec<u8>>
402
        where
403
            K: AsRef<[u8]>
404
        {
405
0
            fn from_iter<T: IntoIterator<Item = (K, usize)>>(iter: T) -> Self {
406
                use crate::options::ZeroTrieWithOptions;
407
                use crate::builder::nonconst::ZeroTrieBuilder;
408
0
                ZeroTrieBuilder::<VecDeque<u8>>::from_bytes_iter(
409
0
                    iter,
410
                    Self::OPTIONS
411
                )
412
0
                .map(|s| Self {
413
0
                    store: s.to_bytes(),
414
0
                })
Unexecuted instantiation: <zerotrie::zerotrie::ZeroAsciiIgnoreCaseTrie<alloc::vec::Vec<u8>> as core::iter::traits::collect::FromIterator<(_, usize)>>::from_iter::<_>::{closure#0}
Unexecuted instantiation: <zerotrie::zerotrie::ZeroTrieExtendedCapacity<alloc::vec::Vec<u8>> as core::iter::traits::collect::FromIterator<(_, usize)>>::from_iter::<_>::{closure#0}
Unexecuted instantiation: <zerotrie::zerotrie::ZeroTriePerfectHash<alloc::vec::Vec<u8>> as core::iter::traits::collect::FromIterator<(_, usize)>>::from_iter::<_>::{closure#0}
Unexecuted instantiation: <zerotrie::zerotrie::ZeroTrieSimpleAscii<alloc::vec::Vec<u8>> as core::iter::traits::collect::FromIterator<(_, usize)>>::from_iter::<_>::{closure#0}
415
0
                .unwrap()
416
0
            }
Unexecuted instantiation: <zerotrie::zerotrie::ZeroAsciiIgnoreCaseTrie<alloc::vec::Vec<u8>> as core::iter::traits::collect::FromIterator<(_, usize)>>::from_iter::<_>
Unexecuted instantiation: <zerotrie::zerotrie::ZeroTrieExtendedCapacity<alloc::vec::Vec<u8>> as core::iter::traits::collect::FromIterator<(_, usize)>>::from_iter::<_>
Unexecuted instantiation: <zerotrie::zerotrie::ZeroTriePerfectHash<alloc::vec::Vec<u8>> as core::iter::traits::collect::FromIterator<(_, usize)>>::from_iter::<_>
Unexecuted instantiation: <zerotrie::zerotrie::ZeroTrieSimpleAscii<alloc::vec::Vec<u8>> as core::iter::traits::collect::FromIterator<(_, usize)>>::from_iter::<_>
417
        }
418
        #[cfg(feature = "alloc")]
419
        impl<'a, K> TryFrom<&'a BTreeMap<K, usize>> for $name<Vec<u8>>
420
        where
421
            K: Borrow<[u8]>
422
        {
423
            type Error = crate::error::Error;
424
0
            fn try_from(map: &'a BTreeMap<K, usize>) -> Result<Self, Self::Error> {
425
0
                let tuples: Vec<(&[u8], usize)> = map
426
0
                    .iter()
427
0
                    .map(|(k, v)| (k.borrow(), *v))
Unexecuted instantiation: <zerotrie::zerotrie::ZeroAsciiIgnoreCaseTrie<alloc::vec::Vec<u8>> as core::convert::TryFrom<&alloc::collections::btree::map::BTreeMap<_, usize>>>::try_from::{closure#0}
Unexecuted instantiation: <zerotrie::zerotrie::ZeroTrieExtendedCapacity<alloc::vec::Vec<u8>> as core::convert::TryFrom<&alloc::collections::btree::map::BTreeMap<_, usize>>>::try_from::{closure#0}
Unexecuted instantiation: <zerotrie::zerotrie::ZeroTriePerfectHash<alloc::vec::Vec<u8>> as core::convert::TryFrom<&alloc::collections::btree::map::BTreeMap<_, usize>>>::try_from::{closure#0}
Unexecuted instantiation: <zerotrie::zerotrie::ZeroTrieSimpleAscii<alloc::vec::Vec<u8>> as core::convert::TryFrom<&alloc::collections::btree::map::BTreeMap<_, usize>>>::try_from::{closure#0}
428
0
                    .collect();
429
0
                let byte_str_slice = ByteStr::from_byte_slice_with_value(&tuples);
430
0
                Self::try_from_tuple_slice(byte_str_slice)
431
0
            }
Unexecuted instantiation: <zerotrie::zerotrie::ZeroAsciiIgnoreCaseTrie<alloc::vec::Vec<u8>> as core::convert::TryFrom<&alloc::collections::btree::map::BTreeMap<_, usize>>>::try_from
Unexecuted instantiation: <zerotrie::zerotrie::ZeroTrieExtendedCapacity<alloc::vec::Vec<u8>> as core::convert::TryFrom<&alloc::collections::btree::map::BTreeMap<_, usize>>>::try_from
Unexecuted instantiation: <zerotrie::zerotrie::ZeroTriePerfectHash<alloc::vec::Vec<u8>> as core::convert::TryFrom<&alloc::collections::btree::map::BTreeMap<_, usize>>>::try_from
Unexecuted instantiation: <zerotrie::zerotrie::ZeroTrieSimpleAscii<alloc::vec::Vec<u8>> as core::convert::TryFrom<&alloc::collections::btree::map::BTreeMap<_, usize>>>::try_from
432
        }
433
        #[cfg(feature = "alloc")]
434
        impl<Store> $name<Store>
435
        where
436
            Store: AsRef<[u8]> + ?Sized
437
        {
438
            /// Exports the data from this ZeroTrie type into a BTreeMap.
439
            ///
440
            /// ✨ *Enabled with the `alloc` Cargo feature.*
441
            ///
442
            /// # Examples
443
            ///
444
            /// ```
445
            #[doc = concat!("use zerotrie::", stringify!($name), ";")]
446
            /// use std::collections::BTreeMap;
447
            ///
448
            #[doc = concat!("let trie = ", stringify!($name), "::from_bytes(b\"abc\\x81def\\x82\");")]
449
            /// let items = trie.to_btreemap();
450
            ///
451
            /// assert_eq!(items.len(), 2);
452
            ///
453
            #[doc = concat!("let recovered_trie: ", stringify!($name), "<Vec<u8>> = items")]
454
            ///     .into_iter()
455
            ///     .collect();
456
            /// assert_eq!(trie.as_bytes(), recovered_trie.as_bytes());
457
            /// ```
458
0
            pub fn to_btreemap(&self) -> BTreeMap<$iter_ty, usize> {
459
0
                self.iter().collect()
460
0
            }
Unexecuted instantiation: <zerotrie::zerotrie::ZeroAsciiIgnoreCaseTrie<_>>::to_btreemap
Unexecuted instantiation: <zerotrie::zerotrie::ZeroTrieExtendedCapacity<_>>::to_btreemap
Unexecuted instantiation: <zerotrie::zerotrie::ZeroTriePerfectHash<_>>::to_btreemap
Unexecuted instantiation: <zerotrie::zerotrie::ZeroTrieSimpleAscii<_>>::to_btreemap
461
            #[allow(dead_code)] // not needed for ZeroAsciiIgnoreCaseTrie
462
0
            pub(crate) fn to_btreemap_bytes(&self) -> BTreeMap<Box<[u8]>, usize> {
463
0
                self.iter().map(|(k, v)| ($cnv_fn(k), v)).collect()
Unexecuted instantiation: <zerotrie::zerotrie::ZeroAsciiIgnoreCaseTrie<_>>::to_btreemap_bytes::{closure#0}
Unexecuted instantiation: <zerotrie::zerotrie::ZeroTrieExtendedCapacity<_>>::to_btreemap_bytes::{closure#0}
Unexecuted instantiation: <zerotrie::zerotrie::ZeroTriePerfectHash<_>>::to_btreemap_bytes::{closure#0}
Unexecuted instantiation: <zerotrie::zerotrie::ZeroTrieSimpleAscii<_>>::to_btreemap_bytes::{closure#0}
464
0
            }
Unexecuted instantiation: <zerotrie::zerotrie::ZeroAsciiIgnoreCaseTrie<_>>::to_btreemap_bytes
Unexecuted instantiation: <zerotrie::zerotrie::ZeroTrieExtendedCapacity<_>>::to_btreemap_bytes
Unexecuted instantiation: <zerotrie::zerotrie::ZeroTriePerfectHash<_>>::to_btreemap_bytes
Unexecuted instantiation: <zerotrie::zerotrie::ZeroTrieSimpleAscii<_>>::to_btreemap_bytes
465
        }
466
        #[cfg(feature = "alloc")]
467
        impl<Store> From<&$name<Store>> for BTreeMap<$iter_ty, usize>
468
        where
469
            Store: AsRef<[u8]> + ?Sized,
470
        {
471
            #[inline]
472
0
            fn from(other: &$name<Store>) -> Self {
473
0
                other.to_btreemap()
474
0
            }
Unexecuted instantiation: <alloc::collections::btree::map::BTreeMap<alloc::vec::Vec<u8>, usize> as core::convert::From<&zerotrie::zerotrie::ZeroTrieExtendedCapacity<_>>>::from
Unexecuted instantiation: <alloc::collections::btree::map::BTreeMap<alloc::string::String, usize> as core::convert::From<&zerotrie::zerotrie::ZeroAsciiIgnoreCaseTrie<_>>>::from
Unexecuted instantiation: <alloc::collections::btree::map::BTreeMap<alloc::vec::Vec<u8>, usize> as core::convert::From<&zerotrie::zerotrie::ZeroTriePerfectHash<_>>>::from
Unexecuted instantiation: <alloc::collections::btree::map::BTreeMap<alloc::string::String, usize> as core::convert::From<&zerotrie::zerotrie::ZeroTrieSimpleAscii<_>>>::from
475
        }
476
        #[cfg(feature = "litemap")]
477
        impl<'a, K, S> TryFrom<&'a LiteMap<K, usize, S>> for $name<Vec<u8>>
478
        where
479
            K: Borrow<[u8]>,
480
            S: litemap::store::StoreIterable<'a, K, usize>,
481
        {
482
            type Error = crate::error::Error;
483
            fn try_from(map: &'a LiteMap<K, usize, S>) -> Result<Self, Self::Error> {
484
                let tuples: Vec<(&[u8], usize)> = map
485
                    .iter()
486
                    .map(|(k, v)| (k.borrow(), *v))
487
                    .collect();
488
                let byte_str_slice = ByteStr::from_byte_slice_with_value(&tuples);
489
                Self::try_from_tuple_slice(byte_str_slice)
490
            }
491
        }
492
        #[cfg(feature = "litemap")]
493
        impl<Store> $name<Store>
494
        where
495
            Store: AsRef<[u8]> + ?Sized,
496
        {
497
            /// Exports the data from this ZeroTrie type into a LiteMap.
498
            ///
499
            /// ✨ *Enabled with the `litemap` Cargo feature.*
500
            ///
501
            /// # Examples
502
            ///
503
            /// ```
504
            #[doc = concat!("use zerotrie::", stringify!($name), ";")]
505
            /// use litemap::LiteMap;
506
            ///
507
            #[doc = concat!("let trie = ", stringify!($name), "::from_bytes(b\"abc\\x81def\\x82\");")]
508
            ///
509
            /// let items = trie.to_litemap();
510
            /// assert_eq!(items.len(), 2);
511
            ///
512
            #[doc = concat!("let recovered_trie: ", stringify!($name), "<Vec<u8>> = items")]
513
            ///     .iter()
514
            ///     .map(|(k, v)| (k, *v))
515
            ///     .collect();
516
            /// assert_eq!(trie.as_bytes(), recovered_trie.as_bytes());
517
            /// ```
518
            pub fn to_litemap(&self) -> LiteMap<$iter_ty, usize> {
519
                self.iter().collect()
520
            }
521
            #[allow(dead_code)] // not needed for ZeroAsciiIgnoreCaseTrie
522
            pub(crate) fn to_litemap_bytes(&self) -> LiteMap<Box<[u8]>, usize> {
523
                self.iter().map(|(k, v)| ($cnv_fn(k), v)).collect()
524
            }
525
        }
526
        #[cfg(feature = "litemap")]
527
        impl<Store> From<&$name<Store>> for LiteMap<$iter_ty, usize>
528
        where
529
            Store: AsRef<[u8]> + ?Sized,
530
        {
531
            #[inline]
532
            fn from(other: &$name<Store>) -> Self {
533
                other.to_litemap()
534
            }
535
        }
536
        #[cfg(feature = "litemap")]
537
        impl $name<Vec<u8>>
538
        {
539
            #[cfg(feature = "serde")]
540
            pub(crate) fn try_from_serde_litemap(items: &LiteMap<Box<ByteStr>, usize>) -> Result<Self, Error> {
541
                let lm_borrowed: LiteMap<&ByteStr, usize> = items.to_borrowed_keys();
542
                Self::try_from_tuple_slice(lm_borrowed.as_slice())
543
            }
544
        }
545
        // Note: Can't generalize this impl due to the `core::borrow::Borrow` blanket impl.
546
        impl Borrow<$name<[u8]>> for $name<&[u8]> {
547
            #[inline]
548
0
            fn borrow(&self) -> &$name<[u8]> {
549
0
                self.as_borrowed()
550
0
            }
Unexecuted instantiation: <zerotrie::zerotrie::ZeroTrieExtendedCapacity<&[u8]> as core::borrow::Borrow<zerotrie::zerotrie::ZeroTrieExtendedCapacity<[u8]>>>::borrow
Unexecuted instantiation: <zerotrie::zerotrie::ZeroAsciiIgnoreCaseTrie<&[u8]> as core::borrow::Borrow<zerotrie::zerotrie::ZeroAsciiIgnoreCaseTrie<[u8]>>>::borrow
Unexecuted instantiation: <zerotrie::zerotrie::ZeroTriePerfectHash<&[u8]> as core::borrow::Borrow<zerotrie::zerotrie::ZeroTriePerfectHash<[u8]>>>::borrow
Unexecuted instantiation: <zerotrie::zerotrie::ZeroTrieSimpleAscii<&[u8]> as core::borrow::Borrow<zerotrie::zerotrie::ZeroTrieSimpleAscii<[u8]>>>::borrow
551
        }
552
        // Note: Can't generalize this impl due to the `core::borrow::Borrow` blanket impl.
553
        #[cfg(feature = "alloc")]
554
        impl Borrow<$name<[u8]>> for $name<Box<[u8]>> {
555
            #[inline]
556
0
            fn borrow(&self) -> &$name<[u8]> {
557
0
                self.as_borrowed()
558
0
            }
Unexecuted instantiation: <zerotrie::zerotrie::ZeroTrieExtendedCapacity<alloc::boxed::Box<[u8]>> as core::borrow::Borrow<zerotrie::zerotrie::ZeroTrieExtendedCapacity<[u8]>>>::borrow
Unexecuted instantiation: <zerotrie::zerotrie::ZeroAsciiIgnoreCaseTrie<alloc::boxed::Box<[u8]>> as core::borrow::Borrow<zerotrie::zerotrie::ZeroAsciiIgnoreCaseTrie<[u8]>>>::borrow
Unexecuted instantiation: <zerotrie::zerotrie::ZeroTriePerfectHash<alloc::boxed::Box<[u8]>> as core::borrow::Borrow<zerotrie::zerotrie::ZeroTriePerfectHash<[u8]>>>::borrow
Unexecuted instantiation: <zerotrie::zerotrie::ZeroTrieSimpleAscii<alloc::boxed::Box<[u8]>> as core::borrow::Borrow<zerotrie::zerotrie::ZeroTrieSimpleAscii<[u8]>>>::borrow
559
        }
560
        // Note: Can't generalize this impl due to the `core::borrow::Borrow` blanket impl.
561
        #[cfg(feature = "alloc")]
562
        impl Borrow<$name<[u8]>> for $name<Vec<u8>> {
563
            #[inline]
564
0
            fn borrow(&self) -> &$name<[u8]> {
565
0
                self.as_borrowed()
566
0
            }
Unexecuted instantiation: <zerotrie::zerotrie::ZeroTrieExtendedCapacity<alloc::vec::Vec<u8>> as core::borrow::Borrow<zerotrie::zerotrie::ZeroTrieExtendedCapacity<[u8]>>>::borrow
Unexecuted instantiation: <zerotrie::zerotrie::ZeroAsciiIgnoreCaseTrie<alloc::vec::Vec<u8>> as core::borrow::Borrow<zerotrie::zerotrie::ZeroAsciiIgnoreCaseTrie<[u8]>>>::borrow
Unexecuted instantiation: <zerotrie::zerotrie::ZeroTriePerfectHash<alloc::vec::Vec<u8>> as core::borrow::Borrow<zerotrie::zerotrie::ZeroTriePerfectHash<[u8]>>>::borrow
Unexecuted instantiation: <zerotrie::zerotrie::ZeroTrieSimpleAscii<alloc::vec::Vec<u8>> as core::borrow::Borrow<zerotrie::zerotrie::ZeroTrieSimpleAscii<[u8]>>>::borrow
567
        }
568
        #[cfg(feature = "alloc")]
569
        impl alloc::borrow::ToOwned for $name<[u8]> {
570
            type Owned = $name<Box<[u8]>>;
571
            #[doc = concat!("This impl allows [`", stringify!($name), "`] to be used inside of a [`Cow`](alloc::borrow::Cow).")]
572
            ///
573
            #[doc = concat!("Note that it is also possible to use `", stringify!($name), "<ZeroVec<u8>>` for a similar result.")]
574
            ///
575
            /// ✨ *Enabled with the `alloc` Cargo feature.*
576
            ///
577
            /// # Examples
578
            ///
579
            /// ```
580
            /// use std::borrow::Cow;
581
            #[doc = concat!("use zerotrie::", stringify!($name), ";")]
582
            ///
583
            #[doc = concat!("let trie: Cow<", stringify!($name), "<[u8]>> = Cow::Borrowed(", stringify!($name), "::from_bytes(b\"abc\\x85\"));")]
584
            /// assert_eq!(trie.get(b"abc"), Some(5));
585
            /// ```
586
0
            fn to_owned(&self) -> Self::Owned {
587
0
                let bytes: &[u8] = self.store.as_ref();
588
0
                $name::from_store(
589
0
                    Vec::from(bytes).into_boxed_slice(),
590
                )
591
0
            }
Unexecuted instantiation: <zerotrie::zerotrie::ZeroTrieExtendedCapacity<[u8]> as alloc::borrow::ToOwned>::to_owned
Unexecuted instantiation: <zerotrie::zerotrie::ZeroAsciiIgnoreCaseTrie<[u8]> as alloc::borrow::ToOwned>::to_owned
Unexecuted instantiation: <zerotrie::zerotrie::ZeroTriePerfectHash<[u8]> as alloc::borrow::ToOwned>::to_owned
Unexecuted instantiation: <zerotrie::zerotrie::ZeroTrieSimpleAscii<[u8]> as alloc::borrow::ToOwned>::to_owned
592
        }
593
        // TODO(#2778): Auto-derive these impls based on the repr(transparent).
594
        // Safety: $name is repr(transparent) over S, a VarULE
595
        #[cfg(feature = "zerovec")]
596
        unsafe impl<Store> zerovec::ule::VarULE for $name<Store>
597
        where
598
            Store: zerovec::ule::VarULE,
599
        {
600
            #[inline]
601
            fn validate_byte_slice(bytes: &[u8]) -> Result<(), zerovec::ZeroVecError> {
602
                Store::validate_byte_slice(bytes)
603
            }
604
            #[inline]
605
            unsafe fn from_byte_slice_unchecked(bytes: &[u8]) -> &Self {
606
                core::mem::transmute(Store::from_byte_slice_unchecked(bytes))
607
            }
608
        }
609
        #[cfg(feature = "zerofrom")]
610
        impl<'zf, Store1, Store2> zerofrom::ZeroFrom<'zf, $name<Store1>> for $name<Store2>
611
        where
612
            Store2: zerofrom::ZeroFrom<'zf, Store1>,
613
        {
614
            #[inline]
615
0
            fn zero_from(other: &'zf $name<Store1>) -> Self {
616
0
                $name::from_store(zerofrom::ZeroFrom::zero_from(&other.store))
617
0
            }
Unexecuted instantiation: <zerotrie::zerotrie::ZeroTrieSimpleAscii<zerovec::zerovec::ZeroVec<u8>> as zerofrom::zero_from::ZeroFrom<zerotrie::zerotrie::ZeroTrieSimpleAscii<zerovec::zerovec::ZeroVec<u8>>>>::zero_from
Unexecuted instantiation: <zerotrie::zerotrie::ZeroTrieExtendedCapacity<zerovec::zerovec::ZeroVec<u8>> as zerofrom::zero_from::ZeroFrom<zerotrie::zerotrie::ZeroTrieExtendedCapacity<zerovec::zerovec::ZeroVec<u8>>>>::zero_from
Unexecuted instantiation: <zerotrie::zerotrie::ZeroAsciiIgnoreCaseTrie<zerovec::zerovec::ZeroVec<u8>> as zerofrom::zero_from::ZeroFrom<zerotrie::zerotrie::ZeroAsciiIgnoreCaseTrie<zerovec::zerovec::ZeroVec<u8>>>>::zero_from
Unexecuted instantiation: <zerotrie::zerotrie::ZeroTriePerfectHash<zerovec::zerovec::ZeroVec<u8>> as zerofrom::zero_from::ZeroFrom<zerotrie::zerotrie::ZeroTriePerfectHash<zerovec::zerovec::ZeroVec<u8>>>>::zero_from
Unexecuted instantiation: <zerotrie::zerotrie::ZeroTrieSimpleAscii<_> as zerofrom::zero_from::ZeroFrom<zerotrie::zerotrie::ZeroTrieSimpleAscii<_>>>::zero_from
Unexecuted instantiation: <zerotrie::zerotrie::ZeroTrieExtendedCapacity<_> as zerofrom::zero_from::ZeroFrom<zerotrie::zerotrie::ZeroTrieExtendedCapacity<_>>>::zero_from
Unexecuted instantiation: <zerotrie::zerotrie::ZeroAsciiIgnoreCaseTrie<_> as zerofrom::zero_from::ZeroFrom<zerotrie::zerotrie::ZeroAsciiIgnoreCaseTrie<_>>>::zero_from
Unexecuted instantiation: <zerotrie::zerotrie::ZeroTriePerfectHash<_> as zerofrom::zero_from::ZeroFrom<zerotrie::zerotrie::ZeroTriePerfectHash<_>>>::zero_from
618
        }
619
    };
620
}
621
622
#[cfg(feature = "alloc")]
623
0
fn string_to_box_u8(input: String) -> Box<[u8]> {
624
0
    input.into_boxed_str().into_boxed_bytes()
625
0
}
626
627
impl_zerotrie_subtype!(
628
    ZeroTrieSimpleAscii,
629
    String,
630
    reader::get_iter_ascii_or_panic,
631
    string_to_box_u8
632
);
633
impl_zerotrie_subtype!(
634
    ZeroAsciiIgnoreCaseTrie,
635
    String,
636
    reader::get_iter_ascii_or_panic,
637
    string_to_box_u8
638
);
639
impl_zerotrie_subtype!(
640
    ZeroTriePerfectHash,
641
    Vec<u8>,
642
    reader::get_iter_phf,
643
    Vec::into_boxed_slice
644
);
645
impl_zerotrie_subtype!(
646
    ZeroTrieExtendedCapacity,
647
    Vec<u8>,
648
    reader::get_iter_phf,
649
    Vec::into_boxed_slice
650
);
651
652
macro_rules! impl_dispatch {
653
    ($self:ident, $inner_fn:ident()) => {
654
        match $self.0 {
655
            ZeroTrieFlavor::SimpleAscii(subtype) => subtype.$inner_fn(),
656
            ZeroTrieFlavor::PerfectHash(subtype) => subtype.$inner_fn(),
657
            ZeroTrieFlavor::ExtendedCapacity(subtype) => subtype.$inner_fn(),
658
        }
659
    };
660
    ($self:ident, $inner_fn:ident().into_zerotrie()) => {
661
        match $self.0 {
662
            ZeroTrieFlavor::SimpleAscii(subtype) => subtype.$inner_fn().into_zerotrie(),
663
            ZeroTrieFlavor::PerfectHash(subtype) => subtype.$inner_fn().into_zerotrie(),
664
            ZeroTrieFlavor::ExtendedCapacity(subtype) => subtype.$inner_fn().into_zerotrie(),
665
        }
666
    };
667
    (&$self:ident, $inner_fn:ident()) => {
668
        match &$self.0 {
669
            ZeroTrieFlavor::SimpleAscii(subtype) => subtype.$inner_fn(),
670
            ZeroTrieFlavor::PerfectHash(subtype) => subtype.$inner_fn(),
671
            ZeroTrieFlavor::ExtendedCapacity(subtype) => subtype.$inner_fn(),
672
        }
673
    };
674
    ($self:ident, $inner_fn:ident($arg:ident)) => {
675
        match $self.0 {
676
            ZeroTrieFlavor::SimpleAscii(subtype) => subtype.$inner_fn($arg),
677
            ZeroTrieFlavor::PerfectHash(subtype) => subtype.$inner_fn($arg),
678
            ZeroTrieFlavor::ExtendedCapacity(subtype) => subtype.$inner_fn($arg),
679
        }
680
    };
681
    (&$self:ident, $inner_fn:ident($arg:ident)) => {
682
        match &$self.0 {
683
            ZeroTrieFlavor::SimpleAscii(subtype) => subtype.$inner_fn($arg),
684
            ZeroTrieFlavor::PerfectHash(subtype) => subtype.$inner_fn($arg),
685
            ZeroTrieFlavor::ExtendedCapacity(subtype) => subtype.$inner_fn($arg),
686
        }
687
    };
688
    (&$self:ident, $trait:ident::$inner_fn:ident()) => {
689
        match &$self.0 {
690
            ZeroTrieFlavor::SimpleAscii(subtype) => {
691
                ZeroTrie(ZeroTrieFlavor::SimpleAscii($trait::$inner_fn(subtype)))
692
            }
693
            ZeroTrieFlavor::PerfectHash(subtype) => {
694
                ZeroTrie(ZeroTrieFlavor::PerfectHash($trait::$inner_fn(subtype)))
695
            }
696
            ZeroTrieFlavor::ExtendedCapacity(subtype) => {
697
                ZeroTrie(ZeroTrieFlavor::ExtendedCapacity($trait::$inner_fn(subtype)))
698
            }
699
        }
700
    };
701
}
702
703
impl<Store> ZeroTrie<Store> {
704
    /// Takes the byte store from this trie.
705
0
    pub fn take_store(self) -> Store {
706
0
        impl_dispatch!(self, take_store())
707
0
    }
708
    /// Converts this trie's store to a different store implementing the `From` trait.
709
    ///
710
    /// For example, use this to change `ZeroTrie<Vec<u8>>` to `ZeroTrie<Cow<[u8]>>`.
711
0
    pub fn convert_store<NewStore>(self) -> ZeroTrie<NewStore>
712
0
    where
713
0
        NewStore: From<Store>,
714
    {
715
0
        impl_dispatch!(self, convert_store().into_zerotrie())
716
0
    }
717
}
718
719
impl<Store> ZeroTrie<Store>
720
where
721
    Store: AsRef<[u8]>,
722
{
723
    /// Queries the trie for a string.
724
0
    pub fn get<K>(&self, key: K) -> Option<usize>
725
0
    where
726
0
        K: AsRef<[u8]>,
727
    {
728
0
        impl_dispatch!(&self, get(key))
729
0
    }
Unexecuted instantiation: <zerotrie::zerotrie::ZeroTrie<zerovec::zerovec::ZeroVec<u8>>>::get::<&[u8]>
Unexecuted instantiation: <zerotrie::zerotrie::ZeroTrie<_>>::get::<_>
730
    /// Returns `true` if the trie is empty.
731
0
    pub fn is_empty(&self) -> bool {
732
0
        impl_dispatch!(&self, is_empty())
733
0
    }
734
    /// Returns the size of the trie in number of bytes.
735
    ///
736
    /// To get the number of keys in the trie, use `.iter().count()`.
737
0
    pub fn byte_len(&self) -> usize {
738
0
        impl_dispatch!(&self, byte_len())
739
0
    }
740
}
741
742
#[cfg(feature = "alloc")]
743
impl<Store> ZeroTrie<Store>
744
where
745
    Store: AsRef<[u8]>,
746
{
747
    /// Exports the data from this ZeroTrie into a BTreeMap.
748
0
    pub fn to_btreemap(&self) -> BTreeMap<Box<[u8]>, usize> {
749
0
        impl_dispatch!(&self, to_btreemap_bytes())
750
0
    }
751
}
752
753
#[cfg(feature = "litemap")]
754
impl<Store> ZeroTrie<Store>
755
where
756
    Store: AsRef<[u8]>,
757
{
758
    /// Exports the data from this ZeroTrie into a LiteMap.
759
    pub fn to_litemap(&self) -> LiteMap<Box<[u8]>, usize> {
760
        impl_dispatch!(&self, to_litemap_bytes())
761
    }
762
}
763
764
#[cfg(feature = "alloc")]
765
impl ZeroTrie<Vec<u8>> {
766
0
    pub(crate) fn try_from_tuple_slice(items: &[(&ByteStr, usize)]) -> Result<Self, Error> {
767
0
        let is_all_ascii = items.iter().all(|(s, _)| s.is_all_ascii());
768
0
        if is_all_ascii && items.len() < 512 {
769
0
            ZeroTrieSimpleAscii::try_from_tuple_slice(items).map(|x| x.into_zerotrie())
770
        } else {
771
0
            ZeroTriePerfectHash::try_from_tuple_slice(items).map(|x| x.into_zerotrie())
772
        }
773
0
    }
774
}
775
776
#[cfg(feature = "alloc")]
777
impl<K> FromIterator<(K, usize)> for ZeroTrie<Vec<u8>>
778
where
779
    K: AsRef<[u8]>,
780
{
781
0
    fn from_iter<T: IntoIterator<Item = (K, usize)>>(iter: T) -> Self {
782
        // We need two Vecs because the first one anchors the `K`s that the second one borrows.
783
0
        let items = Vec::from_iter(iter);
784
0
        let mut items: Vec<(&[u8], usize)> = items.iter().map(|(k, v)| (k.as_ref(), *v)).collect();
785
0
        items.sort();
786
0
        let byte_str_slice = ByteStr::from_byte_slice_with_value(&items);
787
        #[allow(clippy::unwrap_used)] // FromIterator is panicky
788
0
        Self::try_from_tuple_slice(byte_str_slice).unwrap()
789
0
    }
790
}
791
792
#[cfg(feature = "databake")]
793
impl<Store> databake::Bake for ZeroTrie<Store>
794
where
795
    Store: databake::Bake,
796
{
797
    fn bake(&self, env: &databake::CrateEnv) -> databake::TokenStream {
798
        use databake::*;
799
        let inner = impl_dispatch!(&self, bake(env));
800
        quote! { #inner.into_zerotrie() }
801
    }
802
}
803
804
#[cfg(feature = "zerofrom")]
805
impl<'zf, Store1, Store2> zerofrom::ZeroFrom<'zf, ZeroTrie<Store1>> for ZeroTrie<Store2>
806
where
807
    Store2: zerofrom::ZeroFrom<'zf, Store1>,
808
{
809
0
    fn zero_from(other: &'zf ZeroTrie<Store1>) -> Self {
810
        use zerofrom::ZeroFrom;
811
0
        impl_dispatch!(&other, ZeroFrom::zero_from())
812
0
    }
Unexecuted instantiation: <zerotrie::zerotrie::ZeroTrie<zerovec::zerovec::ZeroVec<u8>> as zerofrom::zero_from::ZeroFrom<zerotrie::zerotrie::ZeroTrie<zerovec::zerovec::ZeroVec<u8>>>>::zero_from
Unexecuted instantiation: <zerotrie::zerotrie::ZeroTrie<_> as zerofrom::zero_from::ZeroFrom<zerotrie::zerotrie::ZeroTrie<_>>>::zero_from
813
}