1use sim_kernel::Symbol;
4
5use crate::{ConfigSource, EffectiveConfig};
6
7#[derive(Clone, Debug, Default, PartialEq, Eq)]
9pub struct ConfigReport {
10 pub entries: Vec<ConfigReportEntry>,
12}
13
14impl ConfigReport {
15 pub fn from_effective(effective: &EffectiveConfig) -> Self {
17 Self {
18 entries: effective
19 .trace
20 .iter()
21 .map(|trace| ConfigReportEntry {
22 lib: trace.lib.clone(),
23 key: trace.key.clone(),
24 source: source_label(&trace.source),
25 })
26 .collect(),
27 }
28 }
29}
30
31#[derive(Clone, Debug, PartialEq, Eq)]
33pub struct ConfigReportEntry {
34 pub lib: Symbol,
36 pub key: String,
38 pub source: String,
40}
41
42fn source_label(source: &ConfigSource) -> String {
43 match source {
44 ConfigSource::BuiltIn { lib } => format!("built-in:{}", lib.as_qualified_str()),
45 ConfigSource::Probe { probe, mode } => {
46 format!("probe:{}:{mode:?}", probe.as_qualified_str())
47 }
48 ConfigSource::HomeFile { path } => format!("home-file:{}", path.display()),
49 ConfigSource::WorkFile { path } => format!("work-file:{}", path.display()),
50 ConfigSource::SingleFile { path } => format!("single-file:{}", path.display()),
51 ConfigSource::Site { site } => format!("site:{}", site.as_qualified_str()),
52 ConfigSource::Explicit { label } => format!("explicit:{label}"),
53 }
54}
55
56#[cfg(test)]
57mod tests {
58 use sim_kernel::Symbol;
59 use sim_value::build::{map, text};
60
61 use crate::{ConfigDir, ConfigLayer, merge_layers};
62
63 use super::*;
64
65 #[test]
66 fn report_projects_trace_entries() {
67 let lib = Symbol::qualified("sim", "cookbook");
68 let dir = ConfigDir::one(lib.clone(), map(vec![("mode", text("built-in"))])).unwrap();
69 let effective = merge_layers(&[ConfigLayer::new(
70 ConfigSource::BuiltIn { lib: lib.clone() },
71 dir,
72 )]);
73
74 let report = ConfigReport::from_effective(&effective);
75
76 assert_eq!(
77 report.entries,
78 vec![ConfigReportEntry {
79 lib,
80 key: "mode".to_owned(),
81 source: "built-in:sim/cookbook".to_owned()
82 }]
83 );
84 }
85}