use serde::{Deserialize, Serialize};
use std::fmt;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[repr(transparent)]
pub struct Action(pub u16);
impl Action {
pub const NOP: Self = Self(0x0000);
pub const HALT: Self = Self(0x0001);
pub const ERROR: Self = Self(0x0002);
pub const STATUS: Self = Self(0x0003);
pub const GREET: Self = Self(0x0100);
pub const CONFIRM: Self = Self(0x0101);
pub const DENY: Self = Self(0x0102);
pub const EXPLAIN: Self = Self(0x0103);
pub const CLARIFY: Self = Self(0x0104);
pub const APOLOGIZE: Self = Self(0x0105);
pub const THANK: Self = Self(0x0106);
pub const RESPOND: Self = Self(0x0107);
pub const ASK: Self = Self(0x0200);
pub const REQUEST: Self = Self(0x0201);
pub const SEARCH: Self = Self(0x0202);
pub const RETRIEVE: Self = Self(0x0203);
pub const DEFINE: Self = Self(0x0300);
pub const DESCRIBE: Self = Self(0x0301);
pub const COMPARE: Self = Self(0x0302);
pub const SUMMARIZE: Self = Self(0x0303);
pub const EXPLAIN_HOW: Self = Self(0x0304);
pub const EXPLAIN_WHY: Self = Self(0x0305);
pub const CALCULATE: Self = Self(0x0400);
pub const SET_TIMER: Self = Self(0x0401);
pub const KNOWLEDGE_SEARCH: Self = Self(0x0402);
pub const EMPATHY: Self = Self(0x0500);
pub const CONCERN: Self = Self(0x0501);
pub const ENCOURAGEMENT: Self = Self(0x0502);
pub const REASSURE: Self = Self(0x0503);
pub const TEMPLATE_LOAD: Self = Self(0x0600);
pub const TEMPLATE_FILL: Self = Self(0x0601);
pub const CHAIN: Self = Self(0x0700);
pub const FORK: Self = Self(0x0701);
pub const MERGE: Self = Self(0x0702);
#[inline]
pub const fn from_u16(value: u16) -> Self {
Self(value)
}
#[inline]
pub const fn as_u16(&self) -> u16 {
self.0
}
#[inline]
pub const fn category(&self) -> u8 {
(self.0 >> 8) as u8
}
#[inline]
pub const fn subcategory(&self) -> u8 {
self.0 as u8
}
#[inline]
pub const fn is_system(&self) -> bool {
self.0 <= 0x00FF
}
#[inline]
pub const fn is_response(&self) -> bool {
self.0 >= 0x0100 && self.0 <= 0x01FF
}
#[inline]
pub const fn is_query(&self) -> bool {
self.0 >= 0x0200 && self.0 <= 0x02FF
}
#[inline]
pub const fn is_knowledge(&self) -> bool {
self.0 >= 0x0300 && self.0 <= 0x03FF
}
#[inline]
pub const fn is_skill(&self) -> bool {
self.0 >= 0x0400 && self.0 <= 0x04FF
}
#[inline]
pub const fn is_emotion(&self) -> bool {
self.0 >= 0x0500 && self.0 <= 0x05FF
}
#[inline]
pub const fn is_template(&self) -> bool {
self.0 >= 0x0600 && self.0 <= 0x06FF
}
#[inline]
pub const fn is_chain(&self) -> bool {
self.0 >= 0x0700 && self.0 <= 0x07FF
}
pub fn name(&self) -> &'static str {
match *self {
Self::NOP => "NOP",
Self::HALT => "HALT",
Self::ERROR => "ERROR",
Self::STATUS => "STATUS",
Self::GREET => "GREET",
Self::CONFIRM => "CONFIRM",
Self::DENY => "DENY",
Self::EXPLAIN => "EXPLAIN",
Self::CLARIFY => "CLARIFY",
Self::APOLOGIZE => "APOLOGIZE",
Self::THANK => "THANK",
Self::RESPOND => "RESPOND",
Self::ASK => "ASK",
Self::REQUEST => "REQUEST",
Self::SEARCH => "SEARCH",
Self::RETRIEVE => "RETRIEVE",
Self::DEFINE => "DEFINE",
Self::DESCRIBE => "DESCRIBE",
Self::COMPARE => "COMPARE",
Self::SUMMARIZE => "SUMMARIZE",
Self::EXPLAIN_HOW => "EXPLAIN_HOW",
Self::EXPLAIN_WHY => "EXPLAIN_WHY",
Self::CALCULATE => "CALCULATE",
Self::SET_TIMER => "SET_TIMER",
Self::KNOWLEDGE_SEARCH => "KNOWLEDGE_SEARCH",
Self::EMPATHY => "EMPATHY",
Self::CONCERN => "CONCERN",
Self::ENCOURAGEMENT => "ENCOURAGEMENT",
Self::REASSURE => "REASSURE",
Self::TEMPLATE_LOAD => "TEMPLATE_LOAD",
Self::TEMPLATE_FILL => "TEMPLATE_FILL",
Self::CHAIN => "CHAIN",
Self::FORK => "FORK",
Self::MERGE => "MERGE",
_ => "UNKNOWN",
}
}
}
impl fmt::Display for Action {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "ACT(0x{:04X}:{})", self.0, self.name())
}
}
impl From<u16> for Action {
fn from(value: u16) -> Self {
Self(value)
}
}
impl From<Action> for u16 {
fn from(action: Action) -> Self {
action.0
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_action_categories() {
assert!(Action::NOP.is_system());
assert!(Action::GREET.is_response());
assert!(Action::SEARCH.is_query());
assert!(Action::DEFINE.is_knowledge());
assert!(Action::CALCULATE.is_skill());
assert!(Action::EMPATHY.is_emotion());
assert!(Action::TEMPLATE_LOAD.is_template());
assert!(Action::CHAIN.is_chain());
}
#[test]
fn test_action_bytes() {
assert_eq!(Action::GREET.category(), 0x01);
assert_eq!(Action::GREET.subcategory(), 0x00);
assert_eq!(Action::CALCULATE.category(), 0x04);
assert_eq!(Action::CALCULATE.subcategory(), 0x00);
}
#[test]
fn test_action_names() {
assert_eq!(Action::GREET.name(), "GREET");
assert_eq!(Action::CALCULATE.name(), "CALCULATE");
assert_eq!(Action::from_u16(0xFFFF).name(), "UNKNOWN");
}
#[test]
fn test_serialization() {
let action = Action::GREET;
let json = serde_json::to_string(&action).unwrap();
let deserialized: Action = serde_json::from_str(&json).unwrap();
assert_eq!(action, deserialized);
}
}