Skip to main content

boxology_contract/
presence.rs

1/// The contract side on which a value is being decoded.
2#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
3pub enum DecodeRole {
4    ProviderInput,
5    ConsumerOutput,
6}
7
8/// Presence and nullability for a top-level slot or object field.
9#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
10pub enum Field<T> {
11    Missing,
12    Null,
13    Value(T),
14}
15
16impl<T> Field<T> {
17    pub fn is_missing(&self) -> bool {
18        matches!(self, Self::Missing)
19    }
20
21    pub fn is_null(&self) -> bool {
22        matches!(self, Self::Null)
23    }
24
25    pub fn is_value(&self) -> bool {
26        matches!(self, Self::Value(_))
27    }
28
29    /// Borrows the value, collapsing both `Missing` and `Null` to `None`.
30    pub fn value(&self) -> Option<&T> {
31        match self {
32            Self::Value(value) => Some(value),
33            Self::Missing | Self::Null => None,
34        }
35    }
36
37    /// Takes the value, collapsing both `Missing` and `Null` to `None`.
38    pub fn into_value(self) -> Option<T> {
39        match self {
40            Self::Value(value) => Some(value),
41            Self::Missing | Self::Null => None,
42        }
43    }
44
45    pub fn as_ref(&self) -> Field<&T> {
46        match self {
47            Self::Missing => Field::Missing,
48            Self::Null => Field::Null,
49            Self::Value(value) => Field::Value(value),
50        }
51    }
52}
53
54#[cfg(test)]
55mod tests {
56    use super::Field;
57
58    #[test]
59    fn field_queries_and_projections_preserve_all_states() {
60        let missing = Field::<u8>::Missing;
61        let null = Field::<u8>::Null;
62        let value = Field::Value(7);
63        assert!(missing.is_missing() && null.is_null() && value.is_value());
64        assert_eq!((missing.value(), missing.as_ref()), (None, Field::Missing));
65        assert_eq!((null.as_ref(), null.into_value()), (Field::Null, None));
66        assert_eq!(value.value(), Some(&7));
67        assert_eq!(value.as_ref(), Field::Value(&7));
68        assert_eq!(value.into_value(), Some(7));
69    }
70}