extend_store_nested/
extend_store_nested.rs1use panopticon_core::extend::{Store, Value};
9
10fn write_query_results(store: &mut Store) -> Result<(), Box<dyn std::error::Error>> {
11 store.with_array("rows", |rows| {
12 let mut row = rows.push_map()?;
14 row.insert("user", "alice@contoso.com")?
15 .insert("ip", "10.0.0.1")?
16 .insert("status", "Success")?
17 .insert("attempts", 1i64)?;
18
19 let mut row = rows.push_map()?;
21 row.insert("user", "bob@contoso.com")?
22 .insert("ip", "192.168.1.50")?
23 .insert("status", "Failure")?
24 .insert("attempts", 3i64)?;
25
26 Ok(())
27 })?;
28
29 Ok(())
30}
31
32fn write_grouped_data(store: &mut Store) -> Result<(), Box<dyn std::error::Error>> {
33 store.with_map("by_severity", |groups| {
34 groups.with_array("high", |arr| {
35 arr.push("INC-001")?.push("INC-004")?;
36 Ok(())
37 })?;
38
39 groups.with_array("medium", |arr| {
40 arr.push("INC-002")?;
41 Ok(())
42 })?;
43
44 groups.with_array("low", |arr| {
45 arr.push("INC-003")?.push("INC-005")?.push("INC-006")?;
46 Ok(())
47 })?;
48
49 Ok(())
50 })?;
51
52 Ok(())
53}
54
55fn write_nested_config(store: &mut Store) -> Result<(), Box<dyn std::error::Error>> {
56 store.with_map("pipeline_config", |cfg| {
57 cfg.insert("name", "signin_analysis")?;
58
59 cfg.with_map("source", |src| {
60 src.insert("type", "kql")?
61 .insert("workspace", "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx")?;
62
63 src.with_map("options", |opts| {
64 opts.insert("timeout_secs", 30i64)?
65 .insert("max_rows", 10_000i64)?;
66 Ok(())
67 })?;
68
69 Ok(())
70 })?;
71
72 cfg.with_array("outputs", |outputs| {
73 let mut o = outputs.push_map()?;
74 o.insert("format", "json")?
75 .insert("path", "/tmp/results.json")?;
76
77 let mut o = outputs.push_map()?;
78 o.insert("format", "csv")?
79 .insert("path", "/tmp/results.csv")?;
80
81 Ok(())
82 })?;
83
84 Ok(())
85 })?;
86
87 Ok(())
88}
89
90fn main() -> Result<(), Box<dyn std::error::Error>> {
91 let mut store = Store::new();
92
93 write_query_results(&mut store)?;
95 write_grouped_data(&mut store)?;
96 write_nested_config(&mut store)?;
97
98 let bob_status = store
102 .get("rows")?
103 .get_index(1)?
104 .get_key("status")?
105 .get_value()?;
106 println!("rows[1].status = {bob_status:?}");
107 assert_eq!(bob_status, &Value::Text("Failure".into()));
108
109 let alice_attempts = store
110 .get("rows")?
111 .get_index(0)?
112 .get_key("attempts")?
113 .get_value()?;
114 println!("rows[0].attempts = {alice_attempts:?}");
115 assert_eq!(alice_attempts, &Value::Integer(1));
116
117 let high_count = store.get("by_severity")?.get_key("high")?.as_array()?.len();
119 println!("by_severity.high: {high_count} incidents");
120 assert_eq!(high_count, 2);
121
122 let first_low = store
123 .get("by_severity")?
124 .get_key("low")?
125 .get_index(0)?
126 .get_value()?;
127 println!("by_severity.low[0] = {first_low:?}");
128
129 let timeout = store
131 .get("pipeline_config")?
132 .get_key("source")?
133 .get_key("options")?
134 .get_key("timeout_secs")?
135 .get_value()?;
136 println!("pipeline_config.source.options.timeout_secs = {timeout:?}");
137 assert_eq!(timeout, &Value::Integer(30));
138
139 let second_format = store
141 .get("pipeline_config")?
142 .get_key("outputs")?
143 .get_index(1)?
144 .get_key("format")?
145 .get_value()?;
146 println!("pipeline_config.outputs[1].format = {second_format:?}");
147 assert_eq!(second_format, &Value::Text("csv".into()));
148
149 println!("store_nested: ok");
150 Ok(())
151}