gammalooprs/graph/
autogen.rs1use 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}