acid/firmware/acid-firmware/src/ui/storage.rs

161 lines
4.3 KiB
Rust
Raw Normal View History

use core::fmt::{Debug, Formatter};
2026-02-13 03:00:46 +01:00
use alloc::rc::Rc;
2026-01-31 15:24:36 +01:00
use chrono::NaiveDateTime;
use password_hash::Key;
use serde::{Deserialize, Serialize};
2026-02-13 03:00:46 +01:00
use slint::{Model, SharedString, VecModel};
2026-01-31 15:24:36 +01:00
use spectre_api_sys::{SpectreAlgorithm, SpectreCounter, SpectreResultType};
#[derive(Deserialize, Serialize, Default)]
2026-01-31 15:24:36 +01:00
pub struct SpectreUsersConfig {
#[serde(with = "vec_model")]
pub users: Rc<VecModel<SpectreUserConfig>>,
}
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()),
}
}
2026-01-31 15:24:36 +01:00
}
#[derive(Deserialize, Serialize, Clone, Debug, PartialEq, Eq)]
pub struct SpectreUserConfig {
2026-02-04 03:14:21 +01:00
pub username: SharedString,
2026-01-31 15:24:36 +01:00
#[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,
2026-02-04 03:14:21 +01:00
pub password: Option<SharedString>,
2026-01-31 15:24:36 +01:00
#[serde(with = "with_repr")]
pub login_type: SpectreResultType,
2026-02-04 03:14:21 +01:00
pub login_name: Option<SharedString>,
2026-01-31 15:24:36 +01:00
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)]
2026-01-31 15:36:36 +01:00
pub struct SpectreSite {
2026-02-04 03:14:21 +01:00
pub username: SharedString,
pub site_name: SharedString,
2026-01-31 15:24:36 +01:00
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<T, S>(value: &Rc<VecModel<T>>, serializer: S) -> Result<S::Ok, S::Error>
where
T: Serialize,
VecModel<T>: Model<Data = T>,
S: Serializer,
{
let vec: Vec<T> = value.iter().collect();
vec.serialize(serializer)
}
#[allow(unused)]
pub fn deserialize<'de, T, D>(deserializer: D) -> Result<Rc<VecModel<T>>, D::Error>
where
T: Deserialize<'de>,
D: Deserializer<'de>,
{
let vec = Vec::<T>::deserialize(deserializer)?;
Ok(Rc::new(VecModel::from(vec)))
}
}
2026-01-31 15:24:36 +01:00
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::<Self::Repr, Self>(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::<Self::Repr, Self>(repr) }
}
fn into_repr(self) -> Self::Repr {
self as Self::Repr
}
}
2026-01-31 15:36:36 +01:00
#[allow(unused)]
2026-01-31 15:24:36 +01:00
pub fn serialize<T, S>(value: &T, serializer: S) -> Result<S::Ok, S::Error>
where
T: ReprConvert<Repr = u32>,
S: Serializer,
{
serializer.serialize_u32(value.into_repr())
}
2026-01-31 15:36:36 +01:00
#[allow(unused)]
2026-01-31 15:24:36 +01:00
pub fn deserialize<'de, T, D>(deserializer: D) -> Result<T, D::Error>
where
T: ReprConvert<Repr = u32>,
D: Deserializer<'de>,
{
<u32 as Deserialize>::deserialize(deserializer).map(T::from_repr)
}
}