use std::sync::Arc;
use crate::value::DictionaryValue;
use crate::CharUnit;
#[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",
))
)]
#[derive(Clone, Debug)]
pub struct DATCoreShared<U: CharUnit, V: DictionaryValue = ()> {
#[cfg_attr(
feature = "serialization",
serde(
serialize_with = "crate::serialization::serde_helpers::serialize_arc_vec",
deserialize_with = "crate::serialization::serde_helpers::deserialize_arc_vec"
)
)]
pub base: Arc<Vec<i32>>,
#[cfg_attr(
feature = "serialization",
serde(
serialize_with = "crate::serialization::serde_helpers::serialize_arc_vec",
deserialize_with = "crate::serialization::serde_helpers::deserialize_arc_vec"
)
)]
pub check: Arc<Vec<i32>>,
#[cfg_attr(
feature = "serialization",
serde(
serialize_with = "crate::serialization::serde_helpers::serialize_arc_vec",
deserialize_with = "crate::serialization::serde_helpers::deserialize_arc_vec"
)
)]
pub is_final: Arc<Vec<bool>>,
#[cfg_attr(
feature = "serialization",
serde(
serialize_with = "crate::serialization::serde_helpers::serialize_arc_vec_vec",
deserialize_with = "crate::serialization::serde_helpers::deserialize_arc_vec_vec"
)
)]
pub edges: Arc<Vec<Vec<U>>>,
#[cfg_attr(
feature = "serialization",
serde(
serialize_with = "crate::serialization::serde_helpers::serialize_arc_vec",
deserialize_with = "crate::serialization::serde_helpers::deserialize_arc_vec"
)
)]
pub values: Arc<Vec<Option<V>>>,
}
impl<U: CharUnit, V: DictionaryValue> DATCoreShared<U, V> {
pub fn contains_term_from(&self, term: &str, root_state: usize) -> bool {
let mut state: usize = root_state;
for unit in U::iter_str(term) {
if state >= self.base.len() {
return false;
}
let base = self.base[state];
if base < 0 {
return false;
}
let next = (base as usize).wrapping_add(unit.to_dat_offset());
if next >= self.check.len() || self.check[next] != state as i32 {
return false;
}
state = next;
}
state < self.is_final.len() && self.is_final[state]
}
pub fn term_value_from(&self, term: &str, root_state: usize) -> Option<V>
where
V: Clone,
{
let mut state: usize = root_state;
for unit in U::iter_str(term) {
if state >= self.base.len() {
return None;
}
let base = self.base[state];
if base < 0 {
return None;
}
let next = (base as usize).wrapping_add(unit.to_dat_offset());
if next >= self.check.len() || self.check[next] != state as i32 {
return None;
}
state = next;
}
if state < self.is_final.len() && self.is_final[state] {
self.values.get(state).and_then(|v| v.clone())
} else {
None
}
}
#[inline]
pub fn contains_term(&self, term: &str) -> bool {
self.contains_term_from(term, 1)
}
#[inline]
pub fn term_value(&self, term: &str) -> Option<V>
where
V: Clone,
{
self.term_value_from(term, 1)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn dat_core_shared_default_byte() {
let shared: DATCoreShared<u8, ()> = DATCoreShared {
base: Arc::new(vec![0]),
check: Arc::new(vec![0]),
is_final: Arc::new(vec![false]),
edges: Arc::new(vec![vec![]]),
values: Arc::new(vec![None]),
};
assert_eq!(shared.base.len(), 1);
assert_eq!(shared.edges.len(), 1);
}
#[test]
fn dat_core_shared_default_char() {
let shared: DATCoreShared<char, u32> = DATCoreShared {
base: Arc::new(vec![0]),
check: Arc::new(vec![0]),
is_final: Arc::new(vec![false]),
edges: Arc::new(vec![vec![]]),
values: Arc::new(vec![None]),
};
assert_eq!(shared.edges[0].len(), 0);
assert!(shared.values[0].is_none());
}
}