use super::history::History;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum StatusCode {
ReadyToAll,
ReadyToCommonPrefixSearch,
ReadyToPredictiveSearch,
EndOfCommonPrefixSearch,
EndOfPredictiveSearch,
}
#[derive(Debug, Clone)]
pub struct State {
key_buf: Vec<u8>,
history: Vec<History>,
node_id: u32,
query_pos: u32,
history_pos: u32,
status_code: StatusCode,
}
impl Default for State {
fn default() -> Self {
Self::new()
}
}
impl State {
pub fn new() -> Self {
State {
key_buf: Vec::new(),
history: Vec::new(),
node_id: 0,
query_pos: 0,
history_pos: 0,
status_code: StatusCode::ReadyToAll,
}
}
#[inline]
pub fn set_node_id(&mut self, node_id: usize) {
debug_assert!(node_id <= u32::MAX as usize, "Node ID exceeds u32::MAX");
self.node_id = node_id as u32;
}
#[inline]
pub fn set_query_pos(&mut self, query_pos: usize) {
debug_assert!(
query_pos <= u32::MAX as usize,
"Query position exceeds u32::MAX"
);
self.query_pos = query_pos as u32;
}
#[inline]
pub fn set_history_pos(&mut self, history_pos: usize) {
debug_assert!(
history_pos <= u32::MAX as usize,
"History position exceeds u32::MAX"
);
self.history_pos = history_pos as u32;
}
#[inline]
pub fn set_status_code(&mut self, status_code: StatusCode) {
self.status_code = status_code;
}
#[inline]
pub fn node_id(&self) -> usize {
self.node_id as usize
}
#[inline]
pub fn query_pos(&self) -> usize {
self.query_pos as usize
}
#[inline]
pub fn history_pos(&self) -> usize {
self.history_pos as usize
}
#[inline]
pub fn status_code(&self) -> StatusCode {
self.status_code
}
#[inline]
pub fn key_buf(&self) -> &[u8] {
&self.key_buf
}
#[inline]
pub fn history(&self) -> &[History] {
&self.history
}
#[inline]
pub fn key_buf_mut(&mut self) -> &mut Vec<u8> {
&mut self.key_buf
}
#[inline]
pub fn history_mut(&mut self) -> &mut Vec<History> {
&mut self.history
}
#[inline]
pub fn history_size(&self) -> usize {
self.history.len()
}
#[inline]
pub fn push_history(&mut self, history: History) {
self.history.push(history);
}
#[inline]
pub fn history_back(&self) -> &History {
self.history.last().expect("History stack is empty")
}
#[inline]
pub fn history_at(&self, index: usize) -> &History {
&self.history[index]
}
#[inline]
pub fn history_at_mut(&mut self, index: usize) -> &mut History {
&mut self.history[index]
}
pub fn reset(&mut self) {
self.status_code = StatusCode::ReadyToAll;
}
pub fn lookup_init(&mut self) {
self.node_id = 0;
self.query_pos = 0;
self.status_code = StatusCode::ReadyToAll;
}
pub fn reverse_lookup_init(&mut self) {
self.key_buf.clear();
self.key_buf.reserve(32);
self.status_code = StatusCode::ReadyToAll;
}
pub fn common_prefix_search_init(&mut self) {
self.node_id = 0;
self.query_pos = 0;
self.status_code = StatusCode::ReadyToCommonPrefixSearch;
}
pub fn predictive_search_init(&mut self) {
self.key_buf.clear();
self.key_buf.reserve(256);
self.history.clear();
self.history.reserve(64);
self.node_id = 0;
self.query_pos = 0;
self.history_pos = 0;
self.status_code = StatusCode::ReadyToPredictiveSearch;
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_state_new() {
let state = State::new();
assert_eq!(state.node_id(), 0);
assert_eq!(state.query_pos(), 0);
assert_eq!(state.history_pos(), 0);
assert_eq!(state.status_code(), StatusCode::ReadyToAll);
assert_eq!(state.key_buf().len(), 0);
assert_eq!(state.history().len(), 0);
}
#[test]
fn test_state_default() {
let state = State::default();
assert_eq!(state.node_id(), 0);
assert_eq!(state.query_pos(), 0);
assert_eq!(state.history_pos(), 0);
assert_eq!(state.status_code(), StatusCode::ReadyToAll);
}
#[test]
fn test_state_set_node_id() {
let mut state = State::new();
state.set_node_id(100);
assert_eq!(state.node_id(), 100);
}
#[test]
fn test_state_set_query_pos() {
let mut state = State::new();
state.set_query_pos(50);
assert_eq!(state.query_pos(), 50);
}
#[test]
fn test_state_set_history_pos() {
let mut state = State::new();
state.set_history_pos(10);
assert_eq!(state.history_pos(), 10);
}
#[test]
fn test_state_set_status_code() {
let mut state = State::new();
state.set_status_code(StatusCode::ReadyToCommonPrefixSearch);
assert_eq!(state.status_code(), StatusCode::ReadyToCommonPrefixSearch);
}
#[test]
fn test_state_key_buf() {
let mut state = State::new();
state.key_buf_mut().push(b'h');
state.key_buf_mut().push(b'i');
assert_eq!(state.key_buf(), b"hi");
}
#[test]
fn test_state_history() {
let mut state = State::new();
let mut hist = History::new();
hist.set_node_id(10);
state.history_mut().push(hist);
assert_eq!(state.history().len(), 1);
assert_eq!(state.history()[0].node_id(), 10);
}
#[test]
fn test_state_reset() {
let mut state = State::new();
state.set_status_code(StatusCode::EndOfCommonPrefixSearch);
state.reset();
assert_eq!(state.status_code(), StatusCode::ReadyToAll);
}
#[test]
fn test_state_lookup_init() {
let mut state = State::new();
state.set_node_id(100);
state.set_query_pos(50);
state.set_status_code(StatusCode::EndOfCommonPrefixSearch);
state.lookup_init();
assert_eq!(state.node_id(), 0);
assert_eq!(state.query_pos(), 0);
assert_eq!(state.status_code(), StatusCode::ReadyToAll);
}
#[test]
fn test_state_reverse_lookup_init() {
let mut state = State::new();
state.key_buf_mut().push(b'x');
state.key_buf_mut().push(b'y');
state.reverse_lookup_init();
assert_eq!(state.key_buf().len(), 0);
assert!(state.key_buf_mut().capacity() >= 32);
assert_eq!(state.status_code(), StatusCode::ReadyToAll);
}
#[test]
fn test_state_common_prefix_search_init() {
let mut state = State::new();
state.set_node_id(100);
state.set_query_pos(50);
state.common_prefix_search_init();
assert_eq!(state.node_id(), 0);
assert_eq!(state.query_pos(), 0);
assert_eq!(state.status_code(), StatusCode::ReadyToCommonPrefixSearch);
}
#[test]
fn test_state_predictive_search_init() {
let mut state = State::new();
state.key_buf_mut().push(b'a');
state.history_mut().push(History::new());
state.set_node_id(100);
state.set_query_pos(50);
state.set_history_pos(10);
state.predictive_search_init();
assert_eq!(state.key_buf().len(), 0);
assert!(state.key_buf_mut().capacity() >= 64);
assert_eq!(state.history().len(), 0);
assert!(state.history_mut().capacity() >= 4);
assert_eq!(state.node_id(), 0);
assert_eq!(state.query_pos(), 0);
assert_eq!(state.history_pos(), 0);
assert_eq!(state.status_code(), StatusCode::ReadyToPredictiveSearch);
}
#[test]
fn test_state_clone() {
let mut state1 = State::new();
state1.set_node_id(42);
state1.key_buf_mut().push(b't');
let state2 = state1.clone();
assert_eq!(state2.node_id(), 42);
assert_eq!(state2.key_buf(), b"t");
}
#[test]
fn test_status_code_equality() {
assert_eq!(StatusCode::ReadyToAll, StatusCode::ReadyToAll);
assert_ne!(
StatusCode::ReadyToAll,
StatusCode::ReadyToCommonPrefixSearch
);
}
#[test]
fn test_state_max_values() {
let mut state = State::new();
state.set_node_id(u32::MAX as usize);
state.set_query_pos(u32::MAX as usize);
state.set_history_pos(u32::MAX as usize);
assert_eq!(state.node_id(), u32::MAX as usize);
assert_eq!(state.query_pos(), u32::MAX as usize);
assert_eq!(state.history_pos(), u32::MAX as usize);
}
}