vitaminc_protected/usage/
mod.rs

1use serde::{Serialize, Serializer};
2
3use crate::{exportable::SafeSerialize, private::ControlledPrivate, Controlled, Protected};
4use std::marker::PhantomData;
5
6// TODO: Docs, explain compile time
7pub struct Usage<T, Scope = DefaultScope>(pub(crate) T, pub(crate) PhantomData<Scope>);
8
9impl<T, S> Usage<T, S> {
10    pub fn new(x: <Usage<T, S> as Controlled>::Inner) -> Self
11    where
12        Self: Controlled,
13        S: Scope,
14    {
15        Self::init_from_inner(x)
16    }
17}
18
19impl<T: ControlledPrivate, Scope> ControlledPrivate for Usage<T, Scope> {}
20
21impl<T, Scope> Controlled for Usage<T, Scope>
22where
23    T: Controlled,
24{
25    fn risky_unwrap(self) -> Self::Inner {
26        self.0.risky_unwrap()
27    }
28
29    type Inner = T::Inner;
30
31    fn init_from_inner(x: Self::Inner) -> Self {
32        Self(T::init_from_inner(x), PhantomData)
33    }
34
35    fn risky_ref(&self) -> &Self::Inner {
36        self.0.risky_ref()
37    }
38
39    fn inner_mut(&mut self) -> &mut Self::Inner {
40        self.0.inner_mut()
41    }
42}
43
44/// Marker trait for a type that defines a usage scope
45pub trait Scope {}
46
47/// Marker trait for types that are acceptable in a certain scope.
48pub trait Acceptable<S>
49where
50    S: Scope,
51{
52}
53
54impl<T, S> Acceptable<S> for Usage<T, S> where S: Scope {}
55
56// TODO: Move this to all of the other modules
57pub struct DefaultScope;
58impl Scope for DefaultScope {}
59impl<T> Acceptable<DefaultScope> for Protected<T> {}
60
61/// Serialize implementation for Usage if it is controlled and the inner type is safe serializable.
62///
63/// For example, this allows us to serialize a `Usage<Exportable<Protected<[u8; 32]>>>` type.
64impl<T, A> Serialize for Usage<T, A>
65where
66    T: Controlled,
67    T::Inner: SafeSerialize,
68{
69    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
70    where
71        S: Serializer,
72    {
73        self.risky_ref().safe_serialize(serializer)
74    }
75}
76
77#[cfg(test)]
78mod tests {
79    use super::*;
80
81    struct MyScope;
82    impl Scope for MyScope {}
83
84    // TODO: Create some compilation tests
85    fn example1<T: Acceptable<DefaultScope>>(_: T) -> bool {
86        true
87    }
88    fn example2<T: Acceptable<MyScope>>(_: T) -> bool {
89        true
90    }
91
92    #[test]
93    fn test_usage_for_default_scope() {
94        let x: Usage<Protected<[u8; 32]>, DefaultScope> = Usage::new([0u8; 32]);
95
96        assert!(example1(x));
97    }
98
99    #[test]
100    fn test_usage_for_specific_scope() {
101        let x: Usage<Protected<[u8; 32]>, MyScope> = Usage::new([0; 32]);
102
103        assert!(example2(x));
104    }
105}