Open
Description
Currently the ZeroTrie variants are generated using a macro, like this:
macro_rules! impl_zerotrie_subtype {
($name:ident, $iter_ty:ty, $iter_fn:path, $cnv_fn:path) => {
impl<Store> $name<Store>
where
Store: AsRef<[u8]> + ?Sized,
{
/// Returns `true` if the trie is empty.
#[inline]
pub fn is_empty(&self) -> bool {
self.store.as_ref().is_empty()
}
}
#[cfg(feature = "alloc")]
impl<Store> $name<Store>
where
Store: AsRef<[u8]> + ?Sized,
{
/// Returns an iterator over the key/value pairs in this trie.
///
/// ✨ *Enabled with the `alloc` Cargo feature.*
///
/// # Examples
///
/// ```
#[doc = concat!("use zerotrie::", stringify!($name), ";")]
///
/// // A trie with two values: "abc" and "abcdef"
#[doc = concat!("let trie: &", stringify!($name), "<[u8]> = ", stringify!($name), "::from_bytes(b\"abc\\x80def\\x81\");")]
///
/// let mut it = trie.iter();
/// assert_eq!(it.next(), Some(("abc".into(), 0)));
/// assert_eq!(it.next(), Some(("abcdef".into(), 1)));
/// assert_eq!(it.next(), None);
/// ```
#[inline]
pub fn iter(&self) -> impl Iterator<Item = ($iter_ty, usize)> + '_ {
$iter_fn(self.as_bytes())
}
}
}
}
It may be cleaner to instead use a sealed trait, like this:
struct Sealed;
pub trait ZeroTrieVariant : Sealed {
#[internal] // #4467
type IterTy;
fn iter(...) -> ...;
}
pub struct AsciiOnly {
_not_constructible: core::convert::Infallible,
}
impl ZeroTrieVariant for AsciiOnly { ... }
// Alias
pub type ZeroAsciiTrie<Store> = ZeroTrie<AsciiOnly, Store>;
pub struct ZeroTrie2<Variant, Store>
where
Store: AsRef<[u8]> + ?Sized,
{
/// Returns `true` if the trie is empty.
#[inline]
pub fn is_empty(&self) -> bool {
self.store.as_ref().is_empty()
}
}
#[cfg(feature = "alloc")]
impl<Variant, Store> ZeroTrie2<Variant, Store>
where
Variant: ZeroTrieVariant,
Store: AsRef<[u8]> + ?Sized,
{
/// Returns an iterator over the key/value pairs in this trie.
///
/// ✨ *Enabled with the `alloc` Cargo feature.*
///
/// # Examples
///
/// ```
/// use zerotrie::ZeroTrie2;
///
/// // A trie with two values: "abc" and "abcdef"
/// let trie: &ZeroTrie2<AsciiOnly, [u8]> = ZeroTrie2::from_bytes(b"abc\x80def\x81");
///
/// let mut it = trie.iter();
/// assert_eq!(it.next(), Some(("abc".into(), 0)));
/// assert_eq!(it.next(), Some(("abcdef".into(), 1)));
/// assert_eq!(it.next(), None);
/// ```
#[inline]
pub fn iter(&self) -> impl Iterator<Item = (Variant::IterTy, usize)> + '_ {
Variant::iter(self.as_bytes())
}
}
Things that need to be bikeshed:
trait ZeroTrieVariant
- Marker types that implement the trait:
pub struct AsciiOnly
pub struct AsciiIgnoreCase
pub struct WithBytes
Without additional feedback I will proceed with these names.
I would like to do this when there aren't big open PRs using ZeroTrie in order to avoid conflicts and churn.
Ok?