mod causal_perf;
#[doc(hidden)]
pub mod concurrent_slots;
#[doc(hidden)]
pub use causal_perf::{
causal_construction_stats, reset_causal_construction_stats, CausalConstructionStats,
};
pub mod bijective;
#[cfg(feature = "bindings-core")]
pub mod bindings;
pub mod bloom_filter;
pub mod char_unit;
pub mod collection;
pub mod factory;
#[cfg(feature = "ffi")]
pub mod ffi;
pub mod iterator;
pub mod node_signature;
mod nonblocking;
pub mod substring;
pub mod sync_compat;
pub mod value;
pub mod zipper;
pub mod difference_zipper;
pub mod excluding_prefix_zipper;
pub mod intersection_zipper;
pub mod prefix_zipper;
pub mod symmetric_difference_zipper;
pub mod union_zipper;
pub mod value_diff_zipper;
pub mod double_array_trie;
pub mod dynamic_dawg;
#[cfg(feature = "pathmap-backend")]
pub mod pathmap;
pub mod scdawg;
pub mod suffix_automaton;
#[cfg(feature = "persistent-artrie")]
pub mod artrie_trait;
#[cfg(feature = "persistent-artrie")]
pub mod persistent_artrie;
#[cfg(feature = "serialization")]
pub mod serialization;
pub use bijective::{BijectiveDictionary, BijectiveMap, InsertError};
pub use bloom_filter::BloomFilter;
pub use char_unit::CharUnit;
pub use collection::{
DictionaryEntries, DictionaryEntriesIter, DictionaryEntry, DictionaryKeys,
DictionaryLanguageEntries, DictionaryLanguageTerms, DictionaryTerms, DictionaryValues,
ExactSnapshotEntryIterator, SnapshotEntryIterator, SnapshotTermIterator,
ValuedZipperCollection, ZipperCollection, ZipperEntryIterator, ZipperTermIterator,
};
pub use dynamic_dawg::core::{DawgCore, DawgNode};
pub use iterator::{DictionaryIterator, DictionaryTermIterator};
pub use node_signature::NodeSignature;
pub use substring::{
BidirectionalDictionaryNode, ExtensionResult, SubstringDictionary, SubstringMatch,
};
pub use value::DictionaryValue;
pub use zipper::{DictZipper, ValuedDictZipper};
#[cfg(feature = "persistent-artrie")]
pub use artrie_trait::{ARTrie, EvictableARTrie};
#[cfg(feature = "persistent-artrie")]
#[allow(deprecated)]
pub use artrie_trait::ARTrieAtomicOps;
#[cfg(feature = "persistent-artrie")]
pub use persistent_artrie::char::{
PersistentARTrieChar, PersistentARTrieCharNode, PersistentARTrieCharZipper,
};
#[cfg(feature = "persistent-artrie")]
pub use persistent_artrie::vocab::{IndexedVocabularyPersistent, PersistentVocabARTrie};
#[cfg(feature = "persistent-artrie")]
pub use persistent_artrie::wal::Lsn;
#[cfg(feature = "persistent-artrie")]
pub use persistent_artrie::{
PersistentARTrie, PersistentARTrieU64, PersistentARTrieU64Node, PersistentARTrieZipper,
PersistentScdawg, PersistentScdawgChar, PersistentScdawgCharNode, PersistentScdawgNode,
PersistentSuffixAutomaton, PersistentSuffixAutomatonChar, PersistentSuffixAutomatonCharNode,
PersistentSuffixAutomatonNode, PersistentSuffixTree, PersistentSuffixTreeChar,
PersistentSuffixTreeCharNode, PersistentSuffixTreeNode, RecoveryMode, RecoveryReport,
WalConfig,
};
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum SyncStrategy {
ExternalSync,
InternalSync,
Persistent,
}
#[derive(Clone, Copy, Debug)]
pub struct SnapshotTraversalEdge<U: CharUnit> {
label: U,
target: u32,
}
impl<U: CharUnit> SnapshotTraversalEdge<U> {
pub fn new(label: U, target: u32) -> Self {
Self { label, target }
}
pub fn label(self) -> U {
self.label
}
pub fn target_cursor(self) -> SnapshotTraversalCursor {
SnapshotTraversalCursor::from_index(self.target as usize)
.expect("snapshot traversal targets are one-based")
}
}
pub struct SnapshotTraversalEdges<'a, U: CharUnit> {
edges: &'a [SnapshotTraversalEdge<U>],
is_final: bool,
}
impl<'a, U: CharUnit> SnapshotTraversalEdges<'a, U> {
pub fn new(edges: &'a [SnapshotTraversalEdge<U>], is_final: bool) -> Self {
Self { edges, is_final }
}
pub fn edges(&self) -> &'a [SnapshotTraversalEdge<U>] {
self.edges
}
pub fn is_final(&self) -> bool {
self.is_final
}
}
#[derive(Clone, Copy, Debug)]
pub struct SnapshotTraversalNode<H = SnapshotTraversalCursor> {
pub(crate) edge_start: u32,
pub(crate) edge_len: u32,
pub(crate) is_final: bool,
pub(crate) value_handle: H,
}
#[derive(Clone, Copy, Debug)]
#[repr(transparent)]
struct SnapshotTraversalRange(u64);
const _: () = assert!(std::mem::size_of::<SnapshotTraversalRange>() == 8);
const SNAPSHOT_RANGE_FINAL_BIT: u64 = 1u64 << 63;
const SNAPSHOT_RANGE_LENGTH_MASK: u64 = u32::MAX as u64 >> 1;
impl SnapshotTraversalRange {
#[inline]
fn new(edge_start: u32, edge_len: u32, is_final: bool) -> Option<Self> {
if u64::from(edge_len) > SNAPSHOT_RANGE_LENGTH_MASK {
return None;
}
let finality = if is_final {
SNAPSHOT_RANGE_FINAL_BIT
} else {
0
};
Some(Self(
u64::from(edge_start) | (u64::from(edge_len) << u32::BITS) | finality,
))
}
#[inline]
fn edge_start(self) -> usize {
self.0 as u32 as usize
}
#[inline]
fn edge_len(self) -> usize {
((self.0 >> u32::BITS) & SNAPSHOT_RANGE_LENGTH_MASK) as usize
}
#[inline]
fn is_final(self) -> bool {
self.0 & SNAPSHOT_RANGE_FINAL_BIT != 0
}
}
impl<H: Copy> SnapshotTraversalNode<H> {
pub fn new(edge_start: u32, edge_len: u32, is_final: bool, value_handle: H) -> Self {
Self {
edge_start,
edge_len,
is_final,
value_handle,
}
}
pub fn edge_start(self) -> u32 {
self.edge_start
}
pub fn edge_len(self) -> u32 {
self.edge_len
}
pub fn is_final(self) -> bool {
self.is_final
}
pub fn value_handle(self) -> H {
self.value_handle
}
}
#[derive(Debug)]
pub struct SnapshotTraversalGraph<U: CharUnit, H = SnapshotTraversalCursor> {
nodes: Box<[SnapshotTraversalRange]>,
value_handles: Box<[H]>,
pub(crate) edges: Box<[SnapshotTraversalEdge<U>]>,
pub(crate) root: u32,
}
impl<U: CharUnit, H: Copy> SnapshotTraversalGraph<U, H> {
pub fn new(
nodes: Vec<SnapshotTraversalNode<H>>,
edges: Vec<SnapshotTraversalEdge<U>>,
root: u32,
) -> Option<Self> {
if nodes.is_empty() || root as usize >= nodes.len() {
return None;
}
for node in &nodes {
let start = node.edge_start as usize;
let end = start.checked_add(node.edge_len as usize)?;
let range = edges.get(start..end)?;
let mut previous = None;
for edge in range {
if edge.target as usize >= nodes.len()
|| previous.is_some_and(|label| label >= edge.label)
{
return None;
}
previous = Some(edge.label);
}
}
let mut ranges = Vec::with_capacity(nodes.len());
let mut value_handles = Vec::with_capacity(nodes.len());
for node in nodes {
ranges.push(SnapshotTraversalRange::new(
node.edge_start,
node.edge_len,
node.is_final,
)?);
value_handles.push(node.value_handle);
}
Some(Self {
nodes: ranges.into_boxed_slice(),
value_handles: value_handles.into_boxed_slice(),
edges: edges.into_boxed_slice(),
root,
})
}
pub fn node_count(&self) -> usize {
self.nodes.len()
}
pub fn node(&self, index: usize) -> Option<SnapshotTraversalNode<H>> {
let range = *self.nodes.get(index)?;
let value_handle = *self.value_handles.get(index)?;
Some(SnapshotTraversalNode::new(
range.edge_start() as u32,
range.edge_len() as u32,
range.is_final(),
value_handle,
))
}
pub fn edges(&self) -> &[SnapshotTraversalEdge<U>] {
&self.edges
}
pub fn root_index(&self) -> u32 {
self.root
}
#[inline]
pub fn root_cursor(&self) -> SnapshotTraversalCursor {
SnapshotTraversalCursor::from_index(self.root as usize)
.expect("snapshot traversal roots are one-based")
}
#[inline]
pub fn edges_and_finality(
&self,
cursor: SnapshotTraversalCursor,
) -> SnapshotTraversalEdges<'_, U> {
let index = cursor.index();
let node = self.nodes[index];
let start = node.edge_start();
let end = start + node.edge_len();
SnapshotTraversalEdges::new(&self.edges[start..end], node.is_final())
}
#[inline]
pub unsafe fn edges_and_finality_unchecked(
&self,
cursor: SnapshotTraversalCursor,
) -> SnapshotTraversalEdges<'_, U> {
let index = cursor.index();
let node = unsafe { *self.nodes.get_unchecked(index) };
let start = node.edge_start();
let len = node.edge_len();
let edges = unsafe { std::slice::from_raw_parts(self.edges.as_ptr().add(start), len) };
SnapshotTraversalEdges::new(edges, node.is_final())
}
#[inline]
pub fn value_handle(&self, cursor: SnapshotTraversalCursor) -> H {
self.value_handles[cursor.index()]
}
}
pub type SnapshotTraversalProjection<N> = std::sync::Arc<
SnapshotTraversalGraph<
<N as DictionaryNode>::Unit,
<N as DictionaryNode>::SnapshotGraphValueHandle,
>,
>;
pub struct DictionaryTraversalParts<N: DictionaryNode> {
projection: Option<SnapshotTraversalProjection<N>>,
root: N,
}
impl<N: DictionaryNode> DictionaryTraversalParts<N> {
pub fn projection(&self) -> Option<&SnapshotTraversalProjection<N>> {
self.projection.as_ref()
}
pub fn root(&self) -> &N {
&self.root
}
pub fn into_projection_and_root(self) -> (Option<SnapshotTraversalProjection<N>>, N) {
(self.projection, self.root)
}
}
pub struct DictionaryTraversalRoot<N: DictionaryNode> {
snapshot: Option<SnapshotTraversalProjection<N>>,
node: N,
}
impl<N: DictionaryNode> DictionaryTraversalRoot<N> {
pub fn owned(node: N) -> Self {
Self {
node,
snapshot: None,
}
}
pub fn captured(node: N, snapshot: SnapshotTraversalProjection<N>) -> Self {
Self {
node,
snapshot: Some(snapshot),
}
}
pub fn into_parts(self) -> DictionaryTraversalParts<N> {
DictionaryTraversalParts {
projection: self.snapshot,
root: self.node,
}
}
}
pub trait Dictionary {
type Node: DictionaryNode;
fn root(&self) -> Self::Node;
fn traversal_root(&self) -> DictionaryTraversalRoot<Self::Node> {
DictionaryTraversalRoot::owned(self.root())
}
fn contains(&self, term: &str) -> bool {
let mut node = self.root();
for unit in <Self::Node as DictionaryNode>::Unit::iter_str(term) {
match node.transition(unit) {
Some(next) => node = next,
None => return false,
}
}
node.is_final()
}
fn len(&self) -> Option<usize>;
fn is_empty(&self) -> bool {
self.len().map(|n| n == 0).unwrap_or(false)
}
fn sync_strategy(&self) -> SyncStrategy {
SyncStrategy::ExternalSync
}
fn is_suffix_based(&self) -> bool {
false
}
}
pub trait DictionaryNode: Clone + Send + Sync {
type Unit: CharUnit;
type SnapshotCursor: Copy + Send + Sync + 'static;
type SnapshotGraphValueHandle: Copy + Send + Sync + 'static;
#[inline]
fn requires_final_units(&self) -> bool {
false
}
#[inline]
fn accepts_final_units(&self, units: &[Self::Unit]) -> bool {
let _ = units;
true
}
#[inline]
fn snapshot_node_identity(&self) -> Option<SnapshotNodeIdentity> {
None
}
#[inline]
fn snapshot_root_cursor(&self) -> Option<Self::SnapshotCursor> {
None
}
#[inline]
fn snapshot_cursor_requires_full_projection(&self) -> bool {
false
}
#[inline]
fn contains_snapshot_cursor(&self, cursor: Self::SnapshotCursor) -> bool {
let _ = cursor;
false
}
#[inline]
fn supports_snapshot_cursor_nodes(&self) -> bool {
false
}
#[inline]
fn supports_snapshot_cursor_key_units(&self) -> bool {
false
}
#[inline]
unsafe fn snapshot_cursor_key_units(
&self,
cursor: Self::SnapshotCursor,
) -> Option<Vec<Self::Unit>> {
let _ = cursor;
None
}
#[inline]
unsafe fn snapshot_cursor_node(&self, cursor: Self::SnapshotCursor) -> Option<Self>
where
Self: Sized,
{
let _ = cursor;
None
}
#[inline]
unsafe fn filter_map_snapshot_cursor_edges_and_finality<T, P, F>(
&self,
cursor: Self::SnapshotCursor,
_project: P,
_visitor: F,
) -> Option<bool>
where
Self: Sized,
P: FnMut(Self::Unit) -> Option<T>,
F: FnMut(Self::Unit, Self::SnapshotCursor, T),
{
let _ = cursor;
None
}
#[inline]
unsafe fn snapshot_cursor_is_final(&self, cursor: Self::SnapshotCursor) -> Option<bool>
where
Self: Sized,
{
unsafe {
self.filter_map_snapshot_cursor_edges_and_finality(
cursor,
|_| None::<()>,
|_, _, _| unreachable!("a rejected projection cannot be visited"),
)
}
}
#[inline]
unsafe fn snapshot_cursor_transition(
&self,
cursor: Self::SnapshotCursor,
wanted: Self::Unit,
) -> Option<Option<Self::SnapshotCursor>>
where
Self: Sized,
{
let mut child = None;
unsafe {
self.filter_map_snapshot_cursor_edges_and_finality(
cursor,
|label| (label == wanted).then_some(()),
|_, cursor, ()| child = Some(cursor),
)?
};
Some(child)
}
#[inline]
fn supports_efficient_snapshot_cursor_edge_paging(&self) -> bool {
false
}
#[inline]
unsafe fn visit_snapshot_cursor_edge_page<F>(
&self,
cursor: Self::SnapshotCursor,
start: usize,
capacity: usize,
mut visitor: F,
) -> Option<(bool, usize)>
where
Self: Sized,
F: FnMut(Self::Unit, Self::SnapshotCursor),
{
let end = start.saturating_add(capacity);
let mut total = 0usize;
let is_final = unsafe {
self.filter_map_snapshot_cursor_edges_and_finality(
cursor,
|_| Some(()),
|label, child, ()| {
if total >= start && total < end {
visitor(label, child);
}
total += 1;
},
)?
};
Some((is_final, total))
}
fn is_final(&self) -> bool;
fn transition(&self, label: Self::Unit) -> Option<Self>;
fn edges(&self) -> Box<dyn Iterator<Item = (Self::Unit, Self)> + '_>;
#[inline]
fn for_each_edge<F>(&self, mut visitor: F)
where
Self: Sized,
F: FnMut(Self::Unit, Self),
{
for (label, child) in self.edges() {
visitor(label, child);
}
}
#[inline]
fn visit_edges_and_finality<F>(&self, visitor: F) -> bool
where
Self: Sized,
F: FnMut(Self::Unit, Self),
{
let is_final = self.is_final();
self.for_each_edge(visitor);
is_final
}
#[inline]
fn filter_map_edges<T, P, F>(&self, mut project: P, mut visitor: F)
where
Self: Sized,
P: FnMut(Self::Unit) -> Option<T>,
F: FnMut(Self::Unit, Self, T),
{
self.for_each_edge(|label, child| {
if let Some(projected) = project(label) {
visitor(label, child, projected);
}
});
}
#[inline]
fn filter_map_edges_and_finality<T, P, F>(&self, project: P, visitor: F) -> bool
where
Self: Sized,
P: FnMut(Self::Unit) -> Option<T>,
F: FnMut(Self::Unit, Self, T),
{
let is_final = self.is_final();
self.filter_map_edges(project, visitor);
is_final
}
#[inline]
fn supports_efficient_edge_paging(&self) -> bool {
false
}
#[inline]
fn visit_edge_page_and_finality<F>(
&self,
start: usize,
capacity: usize,
mut visitor: F,
) -> (bool, usize)
where
Self: Sized,
F: FnMut(Self::Unit, Self),
{
let end = start.saturating_add(capacity);
let mut total = 0usize;
let is_final = self.visit_edges_and_finality(|label, child| {
if total >= start && total < end {
visitor(label, child);
}
total = total
.checked_add(1)
.expect("a dictionary node's out-degree fits in usize");
});
(is_final, total)
}
#[inline]
fn visit_edge_page<F>(&self, start: usize, capacity: usize, visitor: F) -> usize
where
Self: Sized,
F: FnMut(Self::Unit, Self),
{
self.visit_edge_page_and_finality(start, capacity, visitor)
.1
}
fn has_edge(&self, label: Self::Unit) -> bool {
self.transition(label).is_some()
}
fn edge_count(&self) -> Option<usize> {
None
}
}
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub struct SnapshotNodeIdentity(std::num::NonZeroU64);
impl SnapshotNodeIdentity {
pub const fn new(value: u64) -> Option<Self> {
match std::num::NonZeroU64::new(value) {
Some(value) => Some(Self(value)),
None => None,
}
}
pub fn from_index(index: usize) -> Option<Self> {
let value = u64::try_from(index).ok()?.checked_add(1)?;
Self::new(value)
}
pub const fn get(self) -> u64 {
self.0.get()
}
}
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
#[repr(transparent)]
pub struct DenseSnapshotCursor(std::num::NonZeroUsize);
impl DenseSnapshotCursor {
#[inline]
pub const fn try_from_one_based(value: usize) -> Option<Self> {
match std::num::NonZeroUsize::new(value) {
Some(value) => Some(Self(value)),
None => None,
}
}
#[inline]
pub fn from_index(index: usize) -> Option<Self> {
Self::try_from_one_based(index.checked_add(1)?)
}
#[inline]
pub const fn index(self) -> usize {
self.0.get() - 1
}
#[inline]
pub const fn one_based(self) -> usize {
self.0.get()
}
#[inline]
pub const fn new(value: usize) -> Option<Self> {
Self::try_from_one_based(value)
}
#[inline]
pub const fn get(self) -> usize {
self.one_based()
}
}
pub type SnapshotTraversalCursor = DenseSnapshotCursor;
#[cfg(test)]
mod snapshot_traversal_cursor_tests {
use super::{DenseSnapshotCursor, SnapshotTraversalCursor};
fn assert_send_sync<T: Send + Sync>() {}
#[test]
fn dense_cursor_is_one_word_and_round_trips_both_index_forms() {
assert_eq!(
std::mem::size_of::<SnapshotTraversalCursor>(),
std::mem::size_of::<usize>()
);
assert_send_sync::<SnapshotTraversalCursor>();
let dense = SnapshotTraversalCursor::new(17).expect("small dense cursor");
assert_eq!(dense.get(), 17);
assert_eq!(dense.index(), 16);
assert_eq!(DenseSnapshotCursor::from_index(16), Some(dense));
assert!(SnapshotTraversalCursor::new(0).is_none());
assert!(DenseSnapshotCursor::from_index(usize::MAX).is_none());
}
}
#[inline]
#[cfg(any(
feature = "bindings-core",
feature = "serialization",
feature = "persistent-artrie"
))]
pub(crate) fn collect_node_edges<N: DictionaryNode>(node: &N) -> Vec<(N::Unit, N)> {
let mut edges = Vec::with_capacity(node.edge_count().unwrap_or(0));
node.for_each_edge(|label, child| edges.push((label, child)));
edges
}
pub trait MappedDictionary: Dictionary {
type Value: DictionaryValue;
fn get_value(&self, term: &str) -> Option<Self::Value>;
fn contains_with_value<F>(&self, term: &str, predicate: F) -> bool
where
F: Fn(&Self::Value) -> bool,
{
self.get_value(term).is_some_and(|v| predicate(&v))
}
}
pub trait MappedDictionaryNode: DictionaryNode {
type Value: DictionaryValue;
fn value(&self) -> Option<Self::Value>;
fn value_at_final(&self) -> Option<Self::Value> {
self.value()
}
#[inline]
fn value_at_final_with_units(&self, units: &[Self::Unit]) -> Option<Self::Value> {
let _ = units;
self.value_at_final()
}
#[inline]
fn supports_snapshot_cursor_values(&self) -> bool {
false
}
#[inline]
fn supports_snapshot_graph_values(&self) -> bool {
false
}
#[inline]
fn snapshot_traversal_graph(
&self,
) -> Option<std::sync::Arc<SnapshotTraversalGraph<Self::Unit, Self::SnapshotGraphValueHandle>>>
{
None
}
#[inline]
unsafe fn snapshot_cursor_value(
&self,
cursor: Self::SnapshotCursor,
) -> Option<Option<Self::Value>> {
let _ = cursor;
None
}
#[inline]
unsafe fn snapshot_cursor_value_with_units(
&self,
cursor: Self::SnapshotCursor,
units: &[Self::Unit],
) -> Option<Option<Self::Value>> {
let _ = units;
unsafe { self.snapshot_cursor_value(cursor) }
}
#[inline]
unsafe fn snapshot_graph_cursor_value(
&self,
graph: &SnapshotTraversalGraph<Self::Unit, Self::SnapshotGraphValueHandle>,
cursor: SnapshotTraversalCursor,
) -> Option<Option<Self::Value>> {
let _ = (graph, cursor);
None
}
#[inline]
unsafe fn snapshot_graph_cursor_value_with_units(
&self,
graph: &SnapshotTraversalGraph<Self::Unit, Self::SnapshotGraphValueHandle>,
cursor: SnapshotTraversalCursor,
units: &[Self::Unit],
) -> Option<Option<Self::Value>> {
let _ = units;
unsafe { self.snapshot_graph_cursor_value(graph, cursor) }
}
}
pub trait MutableDictionary: Dictionary {
fn insert(&self, term: &str) -> bool;
fn remove(&self, term: &str) -> bool;
fn extend<I, S>(&self, terms: I) -> usize
where
I: IntoIterator<Item = S>,
S: AsRef<str>,
{
terms
.into_iter()
.filter(|term| self.insert(term.as_ref()))
.count()
}
fn remove_many<I, S>(&self, terms: I) -> usize
where
I: IntoIterator<Item = S>,
S: AsRef<str>,
{
terms
.into_iter()
.filter(|term| self.remove(term.as_ref()))
.count()
}
}
pub trait CompactableDictionary: MutableDictionary {
fn needs_compaction(&self) -> bool;
fn compact(&self) -> usize;
fn minimize(&self) -> usize {
self.compact()
}
}
pub trait MutableMappedDictionary: MappedDictionary {
fn insert_with_value(&self, term: &str, value: Self::Value) -> bool;
fn union_with<F>(&self, other: &Self, merge_fn: F) -> usize
where
F: Fn(&Self::Value, &Self::Value) -> Self::Value,
Self::Value: Clone;
fn union_replace(&self, other: &Self) -> usize
where
Self::Value: Clone,
{
self.union_with(other, |_, right| right.clone())
}
fn update_or_insert<F>(&self, term: &str, default_value: Self::Value, update_fn: F) -> bool
where
F: Fn(&mut Self::Value);
}
pub mod prelude {
pub use crate::{
BijectiveDictionary, BijectiveMap, CharUnit, CompactableDictionary, DictZipper, Dictionary,
DictionaryEntries, DictionaryEntriesIter, DictionaryEntry, DictionaryKeys,
DictionaryLanguageEntries, DictionaryLanguageTerms, DictionaryNode, DictionaryTerms,
DictionaryValue, DictionaryValues, ExactSnapshotEntryIterator, InsertError,
MappedDictionary, MappedDictionaryNode, MutableDictionary, MutableMappedDictionary,
SnapshotEntryIterator, SnapshotTermIterator, SyncStrategy, ValuedDictZipper,
ValuedZipperCollection, ZipperCollection, ZipperEntryIterator, ZipperTermIterator,
};
pub use crate::double_array_trie::{DoubleArrayTrie, DoubleArrayTrieChar};
pub use crate::dynamic_dawg::{DynamicDawg, DynamicDawgChar, DynamicDawgU64};
pub use crate::scdawg::{Scdawg, ScdawgChar};
pub use crate::suffix_automaton::{SuffixAutomaton, SuffixAutomatonChar};
#[cfg(feature = "persistent-artrie")]
pub use crate::persistent_artrie::{
PersistentARTrieU64, PersistentScdawg, PersistentScdawgChar, PersistentSuffixAutomaton,
PersistentSuffixAutomatonChar, PersistentSuffixTree, PersistentSuffixTreeChar,
};
}