concinnity_cook/build_only/
provenance.rs1use super::LoadedWorld;
7
8#[derive(Debug, Clone, PartialEq, Eq)]
10pub enum Provenance {
11 Authored,
13 AuthoredShadowing {
16 generated_by: String,
18 },
19 Injected {
21 by: String,
23 },
24 Generated {
26 by: String,
28 },
29 Expanded,
32}
33
34impl Provenance {
35 pub fn source(&self) -> Option<&str> {
38 match self {
39 Provenance::AuthoredShadowing { generated_by } => Some(generated_by),
40 Provenance::Injected { by } => Some(by),
41 Provenance::Generated { by } => Some(by),
42 Provenance::Authored | Provenance::Expanded => None,
43 }
44 }
45
46 pub fn is_authored(&self) -> bool {
48 matches!(
49 self,
50 Provenance::Authored | Provenance::AuthoredShadowing { .. }
51 )
52 }
53
54 pub fn is_overridable(&self) -> bool {
60 matches!(
61 self,
62 Provenance::Injected { .. } | Provenance::Generated { .. }
63 )
64 }
65}
66
67impl std::fmt::Display for Provenance {
68 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
69 match self {
70 Provenance::Authored => write!(f, "authored"),
71 Provenance::AuthoredShadowing { generated_by } => {
72 write!(f, "authored (shadows {})", generated_by)
73 }
74 Provenance::Injected { by } => write!(f, "injected:{}", by),
75 Provenance::Generated { by } => write!(f, "generated:{}", by),
76 Provenance::Expanded => write!(f, "expanded"),
77 }
78 }
79}
80
81impl LoadedWorld {
82 pub fn provenance(&self, name: &str) -> Provenance {
84 if self.authored.iter().any(|n| n == name) {
85 return match self.shadowed.iter().find(|s| s.name == name) {
86 Some(s) => Provenance::AuthoredShadowing {
87 generated_by: s.generated_by.clone(),
88 },
89 None => Provenance::Authored,
90 };
91 }
92 if let Some(i) = self.injected.iter().find(|i| i.name == name) {
93 return Provenance::Injected {
94 by: i.injected_by.to_string(),
95 };
96 }
97 if let Some(g) = self.generated.iter().find(|g| g.name == name) {
98 return Provenance::Generated {
99 by: g.generated_by.clone(),
100 };
101 }
102 Provenance::Expanded
103 }
104}
105
106#[cfg(test)]
107mod tests {
108 use super::*;
109 use crate::build_only::{GeneratedAsset, InjectedAsset, ShadowedAsset};
110
111 fn world() -> LoadedWorld {
112 LoadedWorld {
113 assets: Vec::new(),
114 injected: vec![InjectedAsset {
115 name: "hud_font".to_string(),
116 asset_type: "Font".to_string(),
117 args: serde_json::json!({}),
118 injected_by: "debug_hud",
119 }],
120 generated: vec![GeneratedAsset {
121 name: "bistro_mat_wood".to_string(),
122 asset_type: "Material".to_string(),
123 generated_by: "bistro".to_string(),
124 }],
125 shadowed: vec![ShadowedAsset {
126 name: "bistro_mat_glass".to_string(),
127 asset_type: "Material".to_string(),
128 generated_by: "bistro".to_string(),
129 args: serde_json::json!({}),
130 }],
131 authored: vec!["cam".to_string(), "bistro_mat_glass".to_string()],
132 }
133 }
134
135 #[test]
136 fn each_record_classifies_its_names() {
137 let w = world();
138 assert_eq!(w.provenance("cam"), Provenance::Authored);
139 assert_eq!(
140 w.provenance("hud_font"),
141 Provenance::Injected {
142 by: "debug_hud".to_string()
143 }
144 );
145 assert_eq!(
146 w.provenance("bistro_mat_wood"),
147 Provenance::Generated {
148 by: "bistro".to_string()
149 }
150 );
151 assert_eq!(
152 w.provenance("bistro_mat_glass"),
153 Provenance::AuthoredShadowing {
154 generated_by: "bistro".to_string()
155 }
156 );
157 assert_eq!(w.provenance("main_menu_tab_0"), Provenance::Expanded);
159 }
160
161 #[test]
163 fn display_matches_the_listing_vocabulary() {
164 let w = world();
165 assert_eq!(w.provenance("cam").to_string(), "authored");
166 assert_eq!(w.provenance("hud_font").to_string(), "injected:debug_hud");
167 assert_eq!(
168 w.provenance("bistro_mat_wood").to_string(),
169 "generated:bistro"
170 );
171 assert_eq!(
172 w.provenance("bistro_mat_glass").to_string(),
173 "authored (shadows bistro)"
174 );
175 assert_eq!(w.provenance("nothing").to_string(), "expanded");
176 }
177
178 #[test]
179 fn source_names_the_producing_asset_or_pass() {
180 let w = world();
181 assert_eq!(w.provenance("bistro_mat_wood").source(), Some("bistro"));
182 assert_eq!(w.provenance("hud_font").source(), Some("debug_hud"));
183 assert_eq!(w.provenance("bistro_mat_glass").source(), Some("bistro"));
184 assert_eq!(w.provenance("cam").source(), None);
185 assert_eq!(w.provenance("nothing").source(), None);
186 }
187
188 #[test]
191 fn only_skipping_passes_are_overridable() {
192 let w = world();
193 assert!(w.provenance("bistro_mat_wood").is_overridable());
194 assert!(w.provenance("hud_font").is_overridable());
195 assert!(!w.provenance("nothing").is_overridable());
196 assert!(!w.provenance("cam").is_overridable());
197 assert!(!w.provenance("bistro_mat_glass").is_overridable());
199 }
200
201 #[test]
202 fn is_authored_covers_a_plain_line_and_an_overriding_copy() {
203 let w = world();
204 assert!(w.provenance("cam").is_authored());
205 assert!(w.provenance("bistro_mat_glass").is_authored());
206 assert!(!w.provenance("bistro_mat_wood").is_authored());
207 assert!(!w.provenance("nothing").is_authored());
208 }
209}