Skip to main content

gammalooprs/graph/
autogen.rs

1use std::{
2    fmt::{Display, Formatter},
3    ops::{Deref, DerefMut},
4};
5
6#[derive(
7    Debug,
8    Clone,
9    Copy,
10    PartialEq,
11    Eq,
12    PartialOrd,
13    Ord,
14    bincode_trait_derive::Encode,
15    bincode_trait_derive::Decode,
16)]
17pub struct Autogen<T> {
18    pub value: T,
19    pub autogenerated: bool,
20}
21
22impl<T> Autogen<T> {
23    pub fn explicit(value: T) -> Self {
24        Self {
25            value,
26            autogenerated: false,
27        }
28    }
29
30    pub fn generated(value: T) -> Self {
31        Self {
32            value,
33            autogenerated: true,
34        }
35    }
36
37    pub fn option(self) -> Option<T> {
38        if self.autogenerated {
39            None
40        } else {
41            Some(self.value)
42        }
43    }
44
45    pub fn option_with_generated(self, include_autogenerated: bool) -> Option<T> {
46        if include_autogenerated || !self.autogenerated {
47            Some(self.value)
48        } else {
49            None
50        }
51    }
52
53    pub fn from_option_or_generate(value: Option<T>, generate: impl FnOnce() -> T) -> Self {
54        match value {
55            Some(value) => Self::explicit(value),
56            None => Self::generated(generate()),
57        }
58    }
59}
60
61impl<T> Deref for Autogen<T> {
62    type Target = T;
63
64    fn deref(&self) -> &Self::Target {
65        &self.value
66    }
67}
68
69impl<T> DerefMut for Autogen<T> {
70    fn deref_mut(&mut self) -> &mut Self::Target {
71        &mut self.value
72    }
73}
74
75impl<T: Display> Display for Autogen<T> {
76    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
77        Display::fmt(&self.value, f)
78    }
79}
80
81#[cfg(test)]
82mod tests {
83    use super::Autogen;
84
85    #[test]
86    fn explicit_marks_value_as_non_autogenerated() {
87        let value = Autogen::explicit(3);
88        assert_eq!(value.value, 3);
89        assert!(!value.autogenerated);
90        assert_eq!(*value, 3);
91    }
92
93    #[test]
94    fn generated_marks_value_as_autogenerated() {
95        let value = Autogen::from_option_or_generate(None, || 7);
96        assert_eq!(value.value, 7);
97        assert!(value.autogenerated);
98    }
99}