1use crate::{Error, Result};
3use serde::{Deserialize, Serialize};
4use serde_json::Value;
5use std::{
6 collections::BTreeMap,
7 fmt,
8 hash::{Hash, Hasher},
9 sync::OnceLock,
10};
11use time::OffsetDateTime;
12
13static DEVICE: OnceLock<DeviceMetaData> = OnceLock::new();
18
19pub fn set_default_device_meta(meta: DeviceMetaData) {
21 DEVICE.get_or_init(|| meta);
22}
23
24pub fn get_default_device_meta<'a>() -> Option<&'a DeviceMetaData> {
26 DEVICE.get()
27}
28
29#[derive(Debug, Copy, Clone, Serialize, Deserialize, Hash, Eq, PartialEq)]
31pub struct DevicePublicKey(
32 #[serde(with = "hex::serde")] [u8; DevicePublicKey::SIZE],
33);
34
35impl DevicePublicKey {
36 pub const SIZE: usize = 32;
38}
39
40impl hex::FromHex for DevicePublicKey {
41 type Error = Error;
42 fn from_hex<T: AsRef<[u8]>>(value: T) -> Result<Self> {
43 let buf = hex::decode(value)?;
44 let buf: [u8; 32] = buf.as_slice().try_into()?;
45 Ok(Self(buf))
46 }
47}
48
49impl From<[u8; 32]> for DevicePublicKey {
50 fn from(value: [u8; 32]) -> Self {
51 Self(value)
52 }
53}
54
55impl From<&[u8; 32]> for DevicePublicKey {
56 fn from(value: &[u8; 32]) -> Self {
57 Self(*value)
58 }
59}
60
61impl TryFrom<&[u8]> for DevicePublicKey {
62 type Error = Error;
63
64 fn try_from(value: &[u8]) -> Result<Self> {
65 let value: [u8; 32] = value.try_into()?;
66 Ok(Self(value))
67 }
68}
69
70impl AsRef<[u8]> for DevicePublicKey {
71 fn as_ref(&self) -> &[u8] {
72 &self.0
73 }
74}
75
76impl fmt::Display for DevicePublicKey {
77 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
78 write!(f, "{}", hex::encode(self.0))
79 }
80}
81
82#[derive(Default, Debug, Clone, Serialize, Deserialize, Eq, PartialEq)]
85pub struct DeviceMetaData {
86 #[serde(flatten)]
90 info: BTreeMap<String, Value>,
91}
92
93impl fmt::Display for DeviceMetaData {
94 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
95 for (o, v) in &self.info {
96 if let Value::Object(map) = v {
97 for (k, v) in map {
98 if let Value::String(s) = v {
99 writeln!(f, "[{}] {}: {}", o, k, s)?;
100 }
101 }
102 }
103 }
104 Ok(())
105 }
106}
107
108#[derive(Debug, Clone, Serialize, Deserialize, Eq)]
110#[serde(rename_all = "camelCase")]
111pub struct TrustedDevice {
112 public_key: DevicePublicKey,
114 extra_info: DeviceMetaData,
116 created_date: OffsetDateTime,
118}
119
120impl PartialEq for TrustedDevice {
121 fn eq(&self, other: &Self) -> bool {
122 self.public_key == other.public_key
123 }
124}
125
126impl Hash for TrustedDevice {
127 fn hash<H: Hasher>(&self, state: &mut H) {
128 self.public_key.as_ref().hash(state);
129 }
130}
131
132impl TrustedDevice {
133 pub fn new(
135 public_key: DevicePublicKey,
136 extra_info: Option<DeviceMetaData>,
137 created_date: Option<OffsetDateTime>,
138 ) -> Self {
139 let extra_info = if let Some(extra_info) = extra_info {
140 extra_info
141 } else {
142 if let Some(device) = DEVICE.get() {
143 device.clone()
144 } else {
145 Default::default()
146 }
147 };
148
149 Self {
150 public_key,
151 extra_info,
152 created_date: created_date
153 .unwrap_or_else(|| OffsetDateTime::now_utc()),
154 }
155 }
156
157 pub fn public_key(&self) -> &DevicePublicKey {
159 &self.public_key
160 }
161
162 pub fn public_id(&self) -> Result<String> {
164 let mut encoded = String::new();
165 bs58::encode(&self.public_key).into(&mut encoded)?;
166 Ok(encoded)
167 }
168
169 pub fn extra_info(&self) -> &DeviceMetaData {
171 &self.extra_info
172 }
173
174 pub fn created_date(&self) -> &OffsetDateTime {
176 &self.created_date
177 }
178}
179
180impl From<DevicePublicKey> for TrustedDevice {
181 fn from(value: DevicePublicKey) -> Self {
182 Self {
183 extra_info: Default::default(),
184 public_key: value,
185 created_date: OffsetDateTime::now_utc(),
186 }
187 }
188}
189
190impl TryFrom<&TrustedDevice> for (DevicePublicKey, String) {
191 type Error = Error;
192 fn try_from(value: &TrustedDevice) -> Result<Self> {
193 Ok((
194 value.public_key.clone(),
195 serde_json::to_string(&value.extra_info)?,
196 ))
197 }
198}