Skip to main content

luct_scanner/
utils.rs

1use luct_store::StringStoreValue;
2use serde::{Deserialize, Serialize, de::DeserializeOwned};
3use std::ops::Deref;
4use web_time::{Duration, SystemTime};
5
6/// Wrapper around a type to indicate, that the contained value has been validated
7///
8/// When wrapping a `T` into [`Validated`], it means that the value has been validated and will be
9/// trusted from now on.
10#[derive(Debug, Clone, Eq, PartialOrd, Ord, Serialize, Deserialize)]
11pub struct Validated<T> {
12    inner: T,
13    validated_at: SystemTime,
14}
15
16impl<T: PartialEq> PartialEq for Validated<T> {
17    fn eq(&self, other: &Self) -> bool {
18        // NOTE: The validated_at should not influence equality
19        self.inner == other.inner
20    }
21}
22
23impl<T> Validated<T> {
24    pub(crate) fn new(inner: T) -> Self {
25        Self {
26            inner,
27            validated_at: SystemTime::now(),
28        }
29    }
30
31    pub(crate) fn validated_at(&self) -> SystemTime {
32        self.validated_at
33    }
34}
35
36impl<T> Deref for Validated<T> {
37    type Target = T;
38
39    fn deref(&self) -> &Self::Target {
40        &self.inner
41    }
42}
43
44impl<T: StringStoreValue + Serialize + DeserializeOwned> StringStoreValue for Validated<T> {
45    fn serialize_value(&self) -> String {
46        serde_json::to_string(self).unwrap()
47    }
48
49    fn deserialize_value(value: &str) -> Option<Self> {
50        serde_json::from_str(value)
51            .ok()
52            .or_else(|| Self::deserialize_value_legacy(value))
53    }
54}
55
56impl<T: StringStoreValue> Validated<T> {
57    // NOTE: Version 0.1 parses STHs this way. We can drop this, once we have implemented log sth removal
58    fn deserialize_value_legacy(value: &str) -> Option<Self> {
59        let (validated_at, inner): (u64, String) = serde_json::from_str(value).ok()?;
60
61        let validated_at =
62            SystemTime::UNIX_EPOCH.checked_add(Duration::from_millis(validated_at))?;
63        let inner = T::deserialize_value(&inner)?;
64
65        Some(Self {
66            inner,
67            validated_at,
68        })
69    }
70}
71
72// TODO: Round trip test