use core::fmt::{Debug, Formatter}; use alloc::rc::Rc; use chrono::NaiveDateTime; use password_hash::Key; use serde::{Deserialize, Serialize}; use slint::{Model, SharedString, VecModel}; use spectre_api_sys::{SpectreAlgorithm, SpectreCounter, SpectreResultType}; #[derive(Deserialize, Serialize, Default)] pub struct SpectreUsersConfig { #[serde(with = "vec_model")] pub users: Rc>, } impl Debug for SpectreUsersConfig { fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result { f.debug_struct("SpectreUsersConfig") .field_with("users", |f| { f.debug_list().entries(self.users.iter()).finish() }) .finish() } } impl Clone for SpectreUsersConfig { fn clone(&self) -> Self { Self { users: Rc::new(self.users.iter().collect()), } } } #[derive(Deserialize, Serialize, Clone, Debug, PartialEq, Eq)] pub struct SpectreUserConfig { pub username: SharedString, #[serde(with = "serde_bytes")] pub encrypted_key: Key, #[serde(with = "serde_bytes")] pub key_id: [u8; 32], } #[derive(Deserialize, Serialize, Clone, Debug, PartialEq, Eq)] pub struct SpectreSiteConfig { #[serde(with = "with_repr")] pub algorithm: SpectreAlgorithm, pub counter: SpectreCounter::Type, #[serde(rename = "type")] #[serde(with = "with_repr")] pub result_type: SpectreResultType, pub password: Option, #[serde(with = "with_repr")] pub login_type: SpectreResultType, pub login_name: Option, pub uses: u32, pub last_used: NaiveDateTime, } impl Default for SpectreSiteConfig { fn default() -> Self { Self { algorithm: SpectreAlgorithm::Current, counter: SpectreCounter::Default, result_type: SpectreResultType::SpectreResultDefaultResult, password: None, login_type: SpectreResultType::SpectreResultDefaultLogin, login_name: None, uses: 0, last_used: Default::default(), } } } #[derive(Clone, Debug, PartialEq, Eq)] pub struct SpectreSite { pub username: SharedString, pub site_name: SharedString, pub config: SpectreSiteConfig, } mod vec_model { use alloc::{rc::Rc, vec::Vec}; use serde::{Deserialize, Deserializer, Serialize, Serializer}; use slint::{Model, VecModel}; #[allow(unused)] pub fn serialize(value: &Rc>, serializer: S) -> Result where T: Serialize, VecModel: Model, S: Serializer, { let vec: Vec = value.iter().collect(); vec.serialize(serializer) } #[allow(unused)] pub fn deserialize<'de, T, D>(deserializer: D) -> Result>, D::Error> where T: Deserialize<'de>, D: Deserializer<'de>, { let vec = Vec::::deserialize(deserializer)?; Ok(Rc::new(VecModel::from(vec))) } } mod with_repr { use serde::{Deserialize, Deserializer, Serializer}; use spectre_api_sys::{SpectreAlgorithm, SpectreResultType}; pub trait ReprConvert: Copy { type Repr: Copy; fn into_repr(self) -> Self::Repr; fn from_repr(repr: Self::Repr) -> Self; } impl ReprConvert for SpectreAlgorithm { type Repr = u32; fn from_repr(repr: Self::Repr) -> Self { unsafe { core::mem::transmute::(repr) } } fn into_repr(self) -> Self::Repr { self as Self::Repr } } impl ReprConvert for SpectreResultType { type Repr = u32; fn from_repr(repr: Self::Repr) -> Self { unsafe { core::mem::transmute::(repr) } } fn into_repr(self) -> Self::Repr { self as Self::Repr } } #[allow(unused)] pub fn serialize(value: &T, serializer: S) -> Result where T: ReprConvert, S: Serializer, { serializer.serialize_u32(value.into_repr()) } #[allow(unused)] pub fn deserialize<'de, T, D>(deserializer: D) -> Result where T: ReprConvert, D: Deserializer<'de>, { ::deserialize(deserializer).map(T::from_repr) } }