use crate::value::DictionaryValue;
use crate::CharUnit;
use smallvec::SmallVec;
pub const NIL: usize = usize::MAX;
#[derive(Clone, Debug)]
#[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 ScdawgNode<U: CharUnit, V: DictionaryValue = ()> {
pub forward_edges: SmallVec<[(U, usize); 4]>,
pub suffix_link: usize,
pub left_edges: SmallVec<[(U, usize); 2]>,
pub length: usize,
pub is_final: bool,
pub term_ends: SmallVec<[(usize, usize); 2]>,
pub value: Option<V>,
pub parent: usize,
pub parent_label: U,
pub first_char: U,
pub depth: usize,
}
impl<U: CharUnit, V: DictionaryValue> ScdawgNode<U, V> {
pub fn root() -> Self {
Self {
forward_edges: SmallVec::new(),
suffix_link: NIL,
left_edges: SmallVec::new(),
length: 0,
is_final: false,
term_ends: SmallVec::new(),
value: None,
parent: NIL,
parent_label: U::default(),
first_char: U::default(),
depth: 0,
}
}
pub fn new(length: usize, suffix_link: usize, first_char: U) -> Self {
Self {
forward_edges: SmallVec::new(),
suffix_link,
left_edges: SmallVec::new(),
length,
is_final: false,
term_ends: SmallVec::new(),
value: None,
parent: NIL,
parent_label: U::default(),
first_char,
depth: 0,
}
}
#[inline(always)]
pub fn get_edge(&self, label: U) -> Option<usize> {
match self.forward_edges.binary_search_by_key(&label, |(l, _)| *l) {
Ok(idx) => Some(self.forward_edges[idx].1),
Err(_) => None,
}
}
#[inline(always)]
pub fn set_edge(&mut self, label: U, target: usize) {
match self.forward_edges.binary_search_by_key(&label, |(l, _)| *l) {
Ok(idx) => self.forward_edges[idx].1 = target,
Err(idx) => self.forward_edges.insert(idx, (label, target)),
}
}
#[inline]
pub fn is_root(&self) -> bool {
self.parent == NIL && self.length == 0
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn scdawg_node_byte_smoke() {
let mut node: ScdawgNode<u8, ()> = ScdawgNode::root();
node.set_edge(b'a', 1);
node.set_edge(b'b', 2);
assert_eq!(node.get_edge(b'a'), Some(1));
assert_eq!(node.get_edge(b'b'), Some(2));
assert_eq!(node.get_edge(b'z'), None);
assert!(node.is_root());
}
#[test]
fn scdawg_node_char_smoke() {
let mut node: ScdawgNode<char, u32> = ScdawgNode::new(3, 0, 'a');
node.set_edge('é', 5);
node.set_edge('中', 7);
assert_eq!(node.get_edge('é'), Some(5));
assert_eq!(node.get_edge('中'), Some(7));
assert!(!node.is_root());
assert_eq!(node.first_char, 'a');
assert_eq!(node.length, 3);
}
}