feagi_agent/sdk/common/
auth_token.rs1use serde::{Deserialize, Serialize};
4use std::fmt;
5
6pub const AUTH_TOKEN_LENGTH: usize = 32;
8
9#[derive(Clone, Serialize, Deserialize, PartialEq, Eq)]
13pub struct AuthToken {
14 value: [u8; AUTH_TOKEN_LENGTH],
15}
16
17impl AuthToken {
18 pub fn new(value: [u8; AUTH_TOKEN_LENGTH]) -> Self {
20 Self { value }
21 }
22
23 pub fn from_hex(hex: &str) -> Option<Self> {
28 if hex.len() != AUTH_TOKEN_LENGTH * 2 {
29 return None;
30 }
31
32 let mut value = [0u8; AUTH_TOKEN_LENGTH];
33 for (i, chunk) in hex.as_bytes().chunks(2).enumerate() {
34 let hex_byte = std::str::from_utf8(chunk).ok()?;
35 value[i] = u8::from_str_radix(hex_byte, 16).ok()?;
36 }
37 Some(Self { value })
38 }
39
40 pub fn from_base64(b64: &str) -> Option<Self> {
45 use base64::Engine;
46 let decoded = base64::engine::general_purpose::STANDARD.decode(b64).ok()?;
47 if decoded.len() != AUTH_TOKEN_LENGTH {
48 return None;
49 }
50 let mut value = [0u8; AUTH_TOKEN_LENGTH];
51 value.copy_from_slice(&decoded);
52 Some(Self { value })
53 }
54
55 pub fn as_bytes(&self) -> &[u8; AUTH_TOKEN_LENGTH] {
59 &self.value
60 }
61
62 pub fn to_hex(&self) -> String {
64 self.value.iter().map(|b| format!("{:02x}", b)).collect()
65 }
66
67 pub fn to_base64(&self) -> String {
69 use base64::Engine;
70 base64::engine::general_purpose::STANDARD.encode(self.value)
71 }
72}
73
74impl fmt::Debug for AuthToken {
76 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
77 f.debug_struct("AuthToken")
78 .field("value", &"[REDACTED]")
79 .finish()
80 }
81}
82
83impl fmt::Display for AuthToken {
85 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
86 let hex = self.to_hex();
87 write!(f, "{}...{}", &hex[..4], &hex[hex.len() - 4..])
88 }
89}