use crate::grimoire::trie::state::{State, StatusCode};
use crate::key::Key;
use crate::query::Query;
use std::io;
pub struct Agent {
query: Query,
key: Key,
state: Option<Box<State>>,
}
impl Default for Agent {
fn default() -> Self {
Self::new()
}
}
impl Clone for Agent {
fn clone(&self) -> Self {
let mut cloned = Agent {
query: self.query.clone(),
key: self.key.clone(),
state: self.state.as_ref().map(|s| Box::new((**s).clone())),
};
let should_update = cloned.state.is_some();
if should_update {
if let Some(ref state) = cloned.state {
let status = state.status_code();
match status {
StatusCode::ReadyToPredictiveSearch | StatusCode::EndOfPredictiveSearch => {
let key_buf = state.key_buf();
cloned.key.set_bytes(key_buf);
}
_ => {
}
}
}
}
cloned
}
}
impl Agent {
pub fn new() -> Self {
Agent {
query: Query::new(),
key: Key::new(),
state: None,
}
}
pub fn query(&self) -> &Query {
&self.query
}
pub fn query_mut(&mut self) -> &mut Query {
&mut self.query
}
pub fn key(&self) -> &Key {
&self.key
}
pub fn key_mut(&mut self) -> &mut Key {
&mut self.key
}
pub fn set_query_str(&mut self, s: &str) {
if let Some(ref mut state) = self.state {
state.reset();
}
self.query.set_str(s);
}
pub fn set_query_bytes(&mut self, bytes: &[u8]) {
if let Some(ref mut state) = self.state {
state.reset();
}
self.query.set_bytes(bytes);
}
pub fn set_query_id(&mut self, key_id: usize) {
if let Some(ref mut state) = self.state {
state.reset();
}
self.query.set_id(key_id);
}
pub fn state(&self) -> Option<&State> {
self.state.as_deref()
}
pub fn state_mut(&mut self) -> Option<&mut State> {
self.state.as_deref_mut()
}
pub fn set_key_str(&mut self, s: &str) {
self.key.set_str(s);
}
pub fn set_key_bytes(&mut self, bytes: &[u8]) {
self.key.set_bytes(bytes);
}
pub fn set_key_id(&mut self, id: usize) {
self.key.set_id(id);
}
pub fn set_key_from_state_buf(&mut self) {
if let Some(ref state) = self.state {
let buf = state.key_buf();
self.key.set_bytes(buf);
} else {
panic!("Agent must have state to set key from state buffer");
}
}
pub fn set_key_from_query(&mut self) {
let bytes = self.query.as_bytes();
self.key.set_bytes(bytes);
}
pub fn set_key_from_query_prefix(&mut self, length: usize) {
let bytes = self.query.as_bytes();
assert!(length <= bytes.len(), "Prefix length out of bounds");
self.key.set_bytes(&bytes[..length]);
}
pub fn has_state(&self) -> bool {
self.state.is_some()
}
pub fn init_state(&mut self) -> io::Result<()> {
if self.state.is_some() {
return Err(io::Error::new(
io::ErrorKind::AlreadyExists,
"State already initialized",
));
}
self.state = Some(Box::new(State::new()));
Ok(())
}
pub fn clear(&mut self) {
*self = Agent::new();
}
pub fn swap(&mut self, other: &mut Agent) {
std::mem::swap(self, other);
}
}
#[allow(dead_code)]
fn update_agent_after_copying_state(state: &State, agent: &mut Agent) {
match state.status_code() {
StatusCode::ReadyToPredictiveSearch | StatusCode::EndOfPredictiveSearch => {
let key_buf = state.key_buf();
agent.key.set_bytes(key_buf);
}
_ => {
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_agent_new() {
let agent = Agent::new();
assert_eq!(agent.query().length(), 0);
assert_eq!(agent.key().length(), 0);
assert!(!agent.has_state());
}
#[test]
fn test_agent_default() {
let agent = Agent::default();
assert_eq!(agent.query().length(), 0);
}
#[test]
fn test_agent_set_query_str() {
let mut agent = Agent::new();
agent.set_query_str("hello");
assert_eq!(agent.query().as_str(), "hello");
assert_eq!(agent.query().length(), 5);
}
#[test]
fn test_agent_set_query_bytes() {
let mut agent = Agent::new();
agent.set_query_bytes(b"world");
assert_eq!(agent.query().as_bytes(), b"world");
assert_eq!(agent.query().length(), 5);
}
#[test]
fn test_agent_set_query_id() {
let mut agent = Agent::new();
agent.set_query_id(42);
assert_eq!(agent.query().id(), 42);
}
#[test]
fn test_agent_set_key_str() {
let mut agent = Agent::new();
agent.set_key_str("test");
assert_eq!(agent.key().as_str(), "test");
}
#[test]
fn test_agent_set_key_id() {
let mut agent = Agent::new();
agent.set_key_id(100);
assert_eq!(agent.key().id(), 100);
}
#[test]
fn test_agent_init_state() {
let mut agent = Agent::new();
assert!(!agent.has_state());
agent.init_state().unwrap();
assert!(agent.has_state());
}
#[test]
fn test_agent_init_state_already_exists() {
let mut agent = Agent::new();
agent.init_state().unwrap();
let result = agent.init_state();
assert!(result.is_err());
}
#[test]
fn test_agent_state_reset_on_set_query() {
let mut agent = Agent::new();
agent.init_state().unwrap();
{
let state = agent.state_mut().unwrap();
state.set_status_code(StatusCode::EndOfPredictiveSearch);
}
agent.set_query_str("new query");
let state = agent.state().unwrap();
assert_eq!(state.status_code(), StatusCode::ReadyToAll);
}
#[test]
fn test_agent_clear() {
let mut agent = Agent::new();
agent.set_query_str("test");
agent.set_key_id(10);
agent.init_state().unwrap();
agent.clear();
assert_eq!(agent.query().length(), 0);
assert_eq!(agent.key().length(), 0);
assert!(!agent.has_state());
}
#[test]
fn test_agent_swap() {
let s1 = "query1";
let s2 = "query2";
let mut a1 = Agent::new();
a1.set_query_str(s1);
a1.set_key_id(1);
let mut a2 = Agent::new();
a2.set_query_str(s2);
a2.set_key_id(2);
a2.init_state().unwrap();
a1.swap(&mut a2);
assert_eq!(a1.query().as_str(), "query2");
assert_eq!(a1.key().id(), 2);
assert!(a1.has_state());
assert_eq!(a2.query().as_str(), "query1");
assert_eq!(a2.key().id(), 1);
assert!(!a2.has_state());
}
#[test]
fn test_agent_clone() {
let mut agent = Agent::new();
agent.set_query_str("original");
agent.set_key_id(42);
agent.init_state().unwrap();
let cloned = agent.clone();
assert_eq!(cloned.query().as_str(), "original");
assert_eq!(cloned.key().id(), 42);
assert!(cloned.has_state());
}
#[test]
fn test_agent_query_mut() {
let mut agent = Agent::new();
agent.query_mut().set_str("mutable");
assert_eq!(agent.query().as_str(), "mutable");
}
#[test]
fn test_agent_key_mut() {
let mut agent = Agent::new();
agent.key_mut().set_id(99);
assert_eq!(agent.key().id(), 99);
}
}