Skip to main content

luct_scanner/
utils.rs

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