use crate::value::DictionaryValue;
use crate::CharUnit;
#[derive(Debug, Clone)]
#[cfg_attr(
feature = "serialization",
derive(serde::Serialize, serde::Deserialize)
)]
#[cfg_attr(
all(feature = "serialization", not(feature = "persistent-artrie")),
serde(bound(
serialize = "U: serde::Serialize, V: serde::Serialize",
deserialize = "U: serde::Deserialize<'de>, V: serde::Deserialize<'de>",
))
)]
#[cfg_attr(
all(feature = "serialization", feature = "persistent-artrie"),
serde(bound(
serialize = "U: serde::Serialize, V: serde::Serialize",
deserialize = "U: serde::de::DeserializeOwned, V: serde::de::DeserializeOwned",
))
)]
pub struct SuffixNode<U: CharUnit, V: DictionaryValue = ()> {
pub edges: Vec<(U, usize)>,
pub suffix_link: Option<usize>,
pub max_length: usize,
pub is_final: bool,
pub value: Option<V>,
}
impl<U: CharUnit, V: DictionaryValue> SuffixNode<U, V> {
pub fn root() -> Self {
Self {
edges: Vec::new(),
suffix_link: None,
max_length: 0,
is_final: false,
value: None,
}
}
pub fn new(max_length: usize) -> Self {
Self {
edges: Vec::new(),
suffix_link: None,
max_length,
is_final: false,
value: None,
}
}
pub fn find_edge(&self, label: U) -> Option<usize> {
if self.edges.len() < 16 {
self.edges
.iter()
.find(|(u, _)| *u == label)
.map(|(_, t)| *t)
} else {
self.edges
.binary_search_by_key(&label, |(u, _)| *u)
.ok()
.map(|idx| self.edges[idx].1)
}
}
pub fn add_edge(&mut self, label: U, target: usize) {
match self.edges.binary_search_by_key(&label, |(u, _)| *u) {
Ok(idx) => {
self.edges[idx].1 = target;
}
Err(idx) => {
self.edges.insert(idx, (label, target));
}
}
}
pub fn update_edge(&mut self, label: U, new_target: usize) -> bool {
if let Some(idx) = self.edges.iter().position(|(u, _)| *u == label) {
self.edges[idx].1 = new_target;
true
} else {
false
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn suffix_node_byte_smoke() {
let mut node: SuffixNode<u8, ()> = SuffixNode::root();
node.add_edge(b'a', 1);
node.add_edge(b'b', 2);
assert_eq!(node.find_edge(b'a'), Some(1));
assert_eq!(node.find_edge(b'b'), Some(2));
assert_eq!(node.find_edge(b'c'), None);
assert!(node.update_edge(b'a', 10));
assert_eq!(node.find_edge(b'a'), Some(10));
assert!(!node.update_edge(b'z', 99));
}
#[test]
fn suffix_node_char_smoke() {
let mut node: SuffixNode<char, u32> = SuffixNode::new(5);
node.add_edge('é', 7);
node.add_edge('中', 12);
assert_eq!(node.find_edge('é'), Some(7));
assert_eq!(node.find_edge('中'), Some(12));
assert_eq!(node.find_edge('z'), None);
assert_eq!(node.max_length, 5);
}
}