1use crate::FeagiNetworkError;
2use base64::{engine::general_purpose::STANDARD as BASE64_STANDARD, Engine as _};
3use feagi_serialization::{AgentIdentifier, FeagiByteContainer};
4use serde::{Deserialize, Deserializer, Serialize, Serializer};
5
6#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
9pub struct AgentID {
10 bytes: [u8; AgentID::NUMBER_BYTES],
11}
12
13impl Serialize for AgentID {
14 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
15 where
16 S: Serializer,
17 {
18 serializer.serialize_str(&self.to_base64())
19 }
20}
21
22impl<'de> Deserialize<'de> for AgentID {
23 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
24 where
25 D: Deserializer<'de>,
26 {
27 let s = String::deserialize(deserializer)?;
28 Self::try_from_base64(&s).map_err(serde::de::Error::custom)
29 }
30}
31
32impl AgentID {
33 pub const NUMBER_BYTES: usize = FeagiByteContainer::AGENT_ID_BYTE_COUNT;
34
35 pub fn new(bytes: [u8; AgentID::NUMBER_BYTES]) -> Self {
36 Self { bytes }
37 }
38
39 pub const fn new_blank() -> Self {
40 Self {
41 bytes: [0; AgentID::NUMBER_BYTES],
42 }
43 }
44
45 pub fn new_random() -> Self {
46 let mut bytes = [0u8; AgentID::NUMBER_BYTES];
47 getrandom::getrandom(&mut bytes).expect("Failed to generate random bytes");
48 Self { bytes }
49 }
50
51 pub fn try_from_base64(base64_str: &str) -> Result<Self, FeagiNetworkError> {
63 let decoded = BASE64_STANDARD
64 .decode(base64_str)
65 .map_err(|e| FeagiNetworkError::GeneralFailure(format!("Invalid base64: {}", e)))?;
66
67 if decoded.len() != Self::NUMBER_BYTES {
68 return Err(FeagiNetworkError::GeneralFailure(format!(
69 "Invalid AgentID length: expected {} bytes, got {}",
70 Self::NUMBER_BYTES,
71 decoded.len()
72 )));
73 }
74
75 let mut bytes = [0u8; Self::NUMBER_BYTES];
76 bytes.copy_from_slice(&decoded);
77 Ok(Self { bytes })
78 }
79
80 pub fn is_blank(&self) -> bool {
81 self.bytes == [0; AgentID::NUMBER_BYTES]
82 }
83
84 pub fn bytes(&self) -> &[u8; AgentID::NUMBER_BYTES] {
85 &self.bytes
86 }
87
88 pub fn to_base64(&self) -> String {
90 BASE64_STANDARD.encode(self.bytes)
91 }
92}
93
94impl AgentIdentifier for AgentID {
95 fn get_identifier_bytes(&self) -> &[u8; FeagiByteContainer::AGENT_ID_BYTE_COUNT] {
96 &self.bytes
97 }
98}