use bitflags::bitflags;
use serde::{Deserialize, Serialize};
use super::OpCode;
bitflags! {
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub struct QueryFlags: u8 {
const NONE = 0x00;
const BYPASS_FILTERS = 0x01;
const INCLUDE_REPRESSED = 0x02;
const NO_SIDE_EFFECTS = 0x04;
const FORENSIC = 0x07;
}
}
bitflags! {
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub struct StimulateFlags: u8 {
const NONE = 0x00;
const NO_PROPAGATE = 0x01;
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[repr(u8)]
pub enum LineageStatus {
Found = 0,
NotFound = 1,
Repressed = 2,
Dormant = 3,
}
#[derive(Debug, Clone)]
pub enum Request {
LineageCreate {
id: String,
energy: f32,
threshold: f32,
decay_rate: f32,
},
LineageGet {
id: String,
flags: u8,
},
LineageStimulate {
id: String,
delta: f32,
flags: u8,
},
LineageForget {
id: String,
},
LineageTouch {
id: String,
},
BondConnect {
source: String,
target: String,
strength: f32,
polarity: i8,
},
BondReinforce {
source: String,
target: String,
delta: f32,
},
BondSever {
source: String,
target: String,
},
BondNeighbors {
id: String,
},
QueryConscious {
min_energy: f32,
},
QueryTopK {
k: u32,
},
QueryTrauma {
min_rigidity: f32,
},
QueryPattern {
pattern: String,
},
Ping,
Stats,
Snapshot {
name: String,
},
Restore {
name: String,
},
Freeze {
frozen: bool,
},
PhysicsTune {
param: u8,
value: f32,
},
MoodSet {
mood: f32,
},
Subscribe {
events_mask: u32,
},
Unsubscribe,
}
impl Request {
pub fn opcode(&self) -> OpCode {
match self {
Self::LineageCreate { .. } => OpCode::LineageCreate,
Self::LineageGet { .. } => OpCode::LineageGet,
Self::LineageStimulate { .. } => OpCode::LineageStimulate,
Self::LineageForget { .. } => OpCode::LineageForget,
Self::LineageTouch { .. } => OpCode::LineageTouch,
Self::BondConnect { .. } => OpCode::BondConnect,
Self::BondReinforce { .. } => OpCode::BondReinforce,
Self::BondSever { .. } => OpCode::BondSever,
Self::BondNeighbors { .. } => OpCode::BondNeighbors,
Self::QueryConscious { .. } => OpCode::QueryConscious,
Self::QueryTopK { .. } => OpCode::QueryTopK,
Self::QueryTrauma { .. } => OpCode::QueryTrauma,
Self::QueryPattern { .. } => OpCode::QueryPattern,
Self::Ping => OpCode::SysPing,
Self::Stats => OpCode::SysStats,
Self::Snapshot { .. } => OpCode::SysSnapshot,
Self::Restore { .. } => OpCode::SysRestore,
Self::Freeze { .. } => OpCode::SysFreeze,
Self::PhysicsTune { .. } => OpCode::PhysicsTune,
Self::MoodSet { .. } => OpCode::SysMoodSet,
Self::Subscribe { .. } => OpCode::StreamSubscribe,
Self::Unsubscribe => OpCode::StreamUnsubscribe,
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum Response {
Ok(ResponseData),
Error { code: ErrorCode, message: String },
Event(Event),
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum ResponseData {
Ack,
Pong,
LineageResult(LineageResult),
Lineages(Vec<LineageInfo>),
Neighbors(Vec<NeighborInfo>),
Stats(StatsInfo),
SnapshotCreated { name: String },
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct LineageResult {
pub status: LineageStatus,
pub info: Option<LineageInfo>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct LineageInfo {
pub id: String,
pub energy: f32,
pub threshold: f32,
pub decay_rate: f32,
pub rigidity: f32,
pub is_conscious: bool,
pub last_access_ms: u64,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct NeighborInfo {
pub id: String,
pub bond_strength: f32,
pub is_learned: bool,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct StatsInfo {
pub lineage_count: usize,
pub bond_count: usize,
pub conscious_count: usize,
pub total_energy: f32,
pub is_frozen: bool,
pub uptime_secs: u64,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[repr(u8)]
pub enum ErrorCode {
Unknown = 0x00,
InvalidOpCode = 0x01,
MalformedPayload = 0x02,
WarmingUp = 0x03,
LineageNotFound = 0x10,
LineageExists = 0x11,
BondNotFound = 0x20,
BondExists = 0x21,
SnapshotNotFound = 0x30,
Internal = 0xFF,
}
impl ErrorCode {
pub fn from_byte(byte: u8) -> Self {
match byte {
0x01 => Self::InvalidOpCode,
0x02 => Self::MalformedPayload,
0x03 => Self::WarmingUp,
0x10 => Self::LineageNotFound,
0x11 => Self::LineageExists,
0x20 => Self::BondNotFound,
0x21 => Self::BondExists,
0x30 => Self::SnapshotNotFound,
0xFF => Self::Internal,
_ => Self::Unknown,
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum Event {
LineageCreated {
id: String,
energy: f32,
},
LineageStimulated {
id: String,
new_energy: f32,
delta: f32,
},
LineageForgotten {
id: String,
},
BondCreated {
source: String,
target: String,
strength: f32,
},
BondSevered {
source: String,
target: String,
},
DecayTick {
processed: usize,
dead_count: usize,
},
SnapshotCreated {
name: String,
},
}
impl Event {
pub fn mask_bit(&self) -> u32 {
match self {
Self::LineageCreated { .. } => 1 << 0,
Self::LineageStimulated { .. } => 1 << 1,
Self::LineageForgotten { .. } => 1 << 2,
Self::BondCreated { .. } => 1 << 3,
Self::BondSevered { .. } => 1 << 4,
Self::DecayTick { .. } => 1 << 5,
Self::SnapshotCreated { .. } => 1 << 6,
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_request_opcode() {
let req = Request::Ping;
assert_eq!(req.opcode(), OpCode::SysPing);
let req = Request::LineageCreate {
id: "test".into(),
energy: 1.0,
threshold: 0.5,
decay_rate: 0.001,
};
assert_eq!(req.opcode(), OpCode::LineageCreate);
}
#[test]
fn test_event_mask() {
let event = Event::LineageCreated {
id: "x".into(),
energy: 1.0,
};
assert_eq!(event.mask_bit(), 1);
let event = Event::BondCreated {
source: "a".into(),
target: "b".into(),
strength: 0.5,
};
assert_eq!(event.mask_bit(), 1 << 3);
}
}