pub struct Store<T = StoreEntry> { /* private fields */ }Expand description
A keyed collection of entries shared across the pipeline lifecycle.
The store is the single source of truth for pipeline state. It holds
draft-time variables, resolved step parameters, per-step global
outputs, and the values produced by return blocks. The generic
parameter T is the entry type — most stores hold StoreEntry
values, but Store<Parameters> is used in draft/ready phases to hold
the unresolved parameter bindings for each step.
Keys are flat dotted strings; nesting is modelled by the
StoreEntry::Array and StoreEntry::Map variants, not by the
store itself. Insertion is append-only through insert
(errors on duplicate) or replacement-allowed through
insert_or_replace.
Implementations§
Source§impl<T> Store<T>
impl<T> Store<T>
Sourcepub fn new() -> Self
pub fn new() -> Self
Constructs an empty store.
Examples found in repository?
10fn main() -> Result<(), Box<dyn std::error::Error>> {
11 let mut store = Store::new();
12
13 // define_var accepts any V: Into<Value>.
14 // From impls exist for &str, String, bool, i64, f64, so you can pass
15 // these directly without calling .into().
16 store.define_var("name", "Alice")?;
17 store.define_var("age", 30i64)?;
18 store.define_var("active", true)?;
19 store.define_var("score", 9.5f64)?;
20 store.define_var("empty", Value::Null)?;
21
22 // Reading back: Store::get returns &StoreEntry.
23 // get_value() extracts the &Value from a Var entry.
24 let name = store.get("name")?.get_value()?;
25 println!("name = {name:?}");
26
27 // as_var() returns (&Value, &Type) — useful when you need to inspect both.
28 let (val, ty) = store.get("age")?.as_var()?;
29 println!("age = {val:?} (type: {ty:?})");
30
31 // Type is inferred from the value at define time.
32 assert_eq!(store.get("active")?.as_var()?.1, &Type::Boolean);
33 assert_eq!(store.get("score")?.as_var()?.1, &Type::Float);
34 assert_eq!(store.get("empty")?.as_var()?.1, &Type::Null);
35
36 // Duplicate names are rejected with StoreError::EntryAlreadyExists.
37 let err = store.define_var("name", "Bob");
38 println!("duplicate define_var: {err:?}");
39 assert!(err.is_err());
40
41 println!("store_scalars: ok");
42 Ok(())
43}More examples
90fn main() -> Result<(), Box<dyn std::error::Error>> {
91 let mut store = Store::new();
92
93 // An Operation would call these to populate its output Store.
94 write_query_results(&mut store)?;
95 write_grouped_data(&mut store)?;
96 write_nested_config(&mut store)?;
97
98 // --- Reading results back via chained accessors ---
99
100 // Query rows: array -> index -> key -> value
101 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 // Grouped data: map -> key -> index -> value
118 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 // Nested config: map -> key -> key -> key -> value
130 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 // Config outputs array: map -> key -> index -> key -> value
140 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}9fn main() -> Result<(), Box<dyn std::error::Error>> {
10 let mut store = Store::new();
11
12 // --- Chainable push ---
13 // push() accepts V: Into<StoreEntry>. The blanket impl
14 // `From<T: Into<Value>> for StoreEntry` means primitives work directly.
15 let mut arr = store.define_array("numbers")?.push(1)?.push(2)?.push(3)?;
16
17 let items = store.get("numbers")?.as_array()?;
18 println!("numbers: len={}", items.len());
19 assert_eq!(items.len(), 3);
20
21 // --- Chainable insert ---
22 // insert() accepts K: Into<String> and V: Into<StoreEntry>.
23 let mut map = store.define_map("config")?;
24 map.insert("host", "localhost")?
25 .insert("port", 8080i64)?
26 .insert("debug", true)?;
27
28 let host = store.get("config")?.get_key("host")?.get_value()?;
29 println!("config.host = {host:?}");
30
31 // --- Closure API on Store ---
32 // with_array scopes the handle so you don't need an explicit drop.
33 store.with_array("tags", |arr| {
34 arr.push("rust")?.push("pipeline")?.push("store")?;
35 Ok(())
36 })?;
37
38 let tags = store.get("tags")?.as_array()?;
39 println!("tags: len={}", tags.len());
40
41 store.with_map("metadata", |map| {
42 map.insert("version", "0.1.0")?.insert("stable", false)?;
43 Ok(())
44 })?;
45
46 let version = store.get("metadata")?.get_key("version")?.get_value()?;
47 println!("metadata.version = {version:?}");
48
49 // --- Nested construction via MapHandle closures ---
50 // with_array and with_map on MapHandle let you build nested structures
51 // without manually managing sub-handles.
52 store.with_map("server", |map| {
53 map.insert("name", "prod-01")?;
54
55 map.with_array("ports", |arr| {
56 arr.push(80)?.push(443)?;
57 Ok(())
58 })?;
59
60 map.with_map("tls", |tls| {
61 tls.insert("enabled", true)?
62 .insert("cert_path", "/etc/ssl/cert.pem")?;
63 Ok(())
64 })?;
65
66 Ok(())
67 })?;
68
69 let tls_enabled = store
70 .get("server")?
71 .get_key("tls")?
72 .get_key("enabled")?
73 .get_value()?;
74 println!("server.tls.enabled = {tls_enabled:?}");
75
76 // --- push_map on ArrayHandle ---
77 // Builds an array of maps — the most common pattern for tabular results.
78 let mut arr = store.define_array("users")?;
79 {
80 let mut user = arr.push_map()?;
81 user.insert("name", "Alice")?.insert("role", "admin")?;
82 }
83 {
84 let mut user = arr.push_map()?;
85 user.insert("name", "Bob")?.insert("role", "viewer")?;
86 }
87
88 let bob_role = store
89 .get("users")?
90 .get_index(1)?
91 .get_key("role")?
92 .get_value()?;
93 println!("users[1].role = {bob_role:?}");
94 assert_eq!(bob_role, &Value::Text("viewer".into()));
95
96 println!("store_collections: ok");
97 Ok(())
98}Sourcepub fn get<N: AsRef<str>>(&self, name: N) -> Result<&T, StoreError>
pub fn get<N: AsRef<str>>(&self, name: N) -> Result<&T, StoreError>
Looks up an entry by name. Returns StoreError::EntryNotFound
if the name is not in the store.
Examples found in repository?
10fn main() -> Result<(), Box<dyn std::error::Error>> {
11 let mut store = Store::new();
12
13 // define_var accepts any V: Into<Value>.
14 // From impls exist for &str, String, bool, i64, f64, so you can pass
15 // these directly without calling .into().
16 store.define_var("name", "Alice")?;
17 store.define_var("age", 30i64)?;
18 store.define_var("active", true)?;
19 store.define_var("score", 9.5f64)?;
20 store.define_var("empty", Value::Null)?;
21
22 // Reading back: Store::get returns &StoreEntry.
23 // get_value() extracts the &Value from a Var entry.
24 let name = store.get("name")?.get_value()?;
25 println!("name = {name:?}");
26
27 // as_var() returns (&Value, &Type) — useful when you need to inspect both.
28 let (val, ty) = store.get("age")?.as_var()?;
29 println!("age = {val:?} (type: {ty:?})");
30
31 // Type is inferred from the value at define time.
32 assert_eq!(store.get("active")?.as_var()?.1, &Type::Boolean);
33 assert_eq!(store.get("score")?.as_var()?.1, &Type::Float);
34 assert_eq!(store.get("empty")?.as_var()?.1, &Type::Null);
35
36 // Duplicate names are rejected with StoreError::EntryAlreadyExists.
37 let err = store.define_var("name", "Bob");
38 println!("duplicate define_var: {err:?}");
39 assert!(err.is_err());
40
41 println!("store_scalars: ok");
42 Ok(())
43}More examples
90fn main() -> Result<(), Box<dyn std::error::Error>> {
91 let mut store = Store::new();
92
93 // An Operation would call these to populate its output Store.
94 write_query_results(&mut store)?;
95 write_grouped_data(&mut store)?;
96 write_nested_config(&mut store)?;
97
98 // --- Reading results back via chained accessors ---
99
100 // Query rows: array -> index -> key -> value
101 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 // Grouped data: map -> key -> index -> value
118 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 // Nested config: map -> key -> key -> key -> value
130 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 // Config outputs array: map -> key -> index -> key -> value
140 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}9fn main() -> Result<(), Box<dyn std::error::Error>> {
10 let mut store = Store::new();
11
12 // --- Chainable push ---
13 // push() accepts V: Into<StoreEntry>. The blanket impl
14 // `From<T: Into<Value>> for StoreEntry` means primitives work directly.
15 let mut arr = store.define_array("numbers")?.push(1)?.push(2)?.push(3)?;
16
17 let items = store.get("numbers")?.as_array()?;
18 println!("numbers: len={}", items.len());
19 assert_eq!(items.len(), 3);
20
21 // --- Chainable insert ---
22 // insert() accepts K: Into<String> and V: Into<StoreEntry>.
23 let mut map = store.define_map("config")?;
24 map.insert("host", "localhost")?
25 .insert("port", 8080i64)?
26 .insert("debug", true)?;
27
28 let host = store.get("config")?.get_key("host")?.get_value()?;
29 println!("config.host = {host:?}");
30
31 // --- Closure API on Store ---
32 // with_array scopes the handle so you don't need an explicit drop.
33 store.with_array("tags", |arr| {
34 arr.push("rust")?.push("pipeline")?.push("store")?;
35 Ok(())
36 })?;
37
38 let tags = store.get("tags")?.as_array()?;
39 println!("tags: len={}", tags.len());
40
41 store.with_map("metadata", |map| {
42 map.insert("version", "0.1.0")?.insert("stable", false)?;
43 Ok(())
44 })?;
45
46 let version = store.get("metadata")?.get_key("version")?.get_value()?;
47 println!("metadata.version = {version:?}");
48
49 // --- Nested construction via MapHandle closures ---
50 // with_array and with_map on MapHandle let you build nested structures
51 // without manually managing sub-handles.
52 store.with_map("server", |map| {
53 map.insert("name", "prod-01")?;
54
55 map.with_array("ports", |arr| {
56 arr.push(80)?.push(443)?;
57 Ok(())
58 })?;
59
60 map.with_map("tls", |tls| {
61 tls.insert("enabled", true)?
62 .insert("cert_path", "/etc/ssl/cert.pem")?;
63 Ok(())
64 })?;
65
66 Ok(())
67 })?;
68
69 let tls_enabled = store
70 .get("server")?
71 .get_key("tls")?
72 .get_key("enabled")?
73 .get_value()?;
74 println!("server.tls.enabled = {tls_enabled:?}");
75
76 // --- push_map on ArrayHandle ---
77 // Builds an array of maps — the most common pattern for tabular results.
78 let mut arr = store.define_array("users")?;
79 {
80 let mut user = arr.push_map()?;
81 user.insert("name", "Alice")?.insert("role", "admin")?;
82 }
83 {
84 let mut user = arr.push_map()?;
85 user.insert("name", "Bob")?.insert("role", "viewer")?;
86 }
87
88 let bob_role = store
89 .get("users")?
90 .get_index(1)?
91 .get_key("role")?
92 .get_value()?;
93 println!("users[1].role = {bob_role:?}");
94 assert_eq!(bob_role, &Value::Text("viewer".into()));
95
96 println!("store_collections: ok");
97 Ok(())
98}Sourcepub fn insert<N: Into<String>>(
&mut self,
name: N,
entry: T,
) -> Result<(), StoreError>
pub fn insert<N: Into<String>>( &mut self, name: N, entry: T, ) -> Result<(), StoreError>
Inserts an entry under name. Returns
StoreError::EntryAlreadyExists if the name is already in use.
Sourcepub fn insert_or_replace<N: Into<String>>(&mut self, name: N, entry: T)
pub fn insert_or_replace<N: Into<String>>(&mut self, name: N, entry: T)
Inserts an entry under name, overwriting any existing entry
with the same name. Used by the runtime when an operation rewrites
its own outputs.
Sourcepub fn merge(
&mut self,
prefix_opt: Option<&str>,
other: Store<T>,
) -> Result<(), StoreError>
pub fn merge( &mut self, prefix_opt: Option<&str>, other: Store<T>, ) -> Result<(), StoreError>
Merges other into this store, optionally prefixing each
incoming key with "{prefix}.". Fails on the first key collision
with StoreError::EntryAlreadyExists.
Source§impl Store<StoreEntry>
impl Store<StoreEntry>
Sourcepub fn define_var<N: Into<String>, V: Into<Value>>(
&mut self,
name: N,
value: V,
) -> Result<(), StoreError>
pub fn define_var<N: Into<String>, V: Into<Value>>( &mut self, name: N, value: V, ) -> Result<(), StoreError>
Defines a new variable entry — a StoreEntry::Var wrapping
the given Value and its derived Type. Fails with
StoreError::EntryAlreadyExists if the name is already in use.
Examples found in repository?
10fn main() -> Result<(), Box<dyn std::error::Error>> {
11 let mut store = Store::new();
12
13 // define_var accepts any V: Into<Value>.
14 // From impls exist for &str, String, bool, i64, f64, so you can pass
15 // these directly without calling .into().
16 store.define_var("name", "Alice")?;
17 store.define_var("age", 30i64)?;
18 store.define_var("active", true)?;
19 store.define_var("score", 9.5f64)?;
20 store.define_var("empty", Value::Null)?;
21
22 // Reading back: Store::get returns &StoreEntry.
23 // get_value() extracts the &Value from a Var entry.
24 let name = store.get("name")?.get_value()?;
25 println!("name = {name:?}");
26
27 // as_var() returns (&Value, &Type) — useful when you need to inspect both.
28 let (val, ty) = store.get("age")?.as_var()?;
29 println!("age = {val:?} (type: {ty:?})");
30
31 // Type is inferred from the value at define time.
32 assert_eq!(store.get("active")?.as_var()?.1, &Type::Boolean);
33 assert_eq!(store.get("score")?.as_var()?.1, &Type::Float);
34 assert_eq!(store.get("empty")?.as_var()?.1, &Type::Null);
35
36 // Duplicate names are rejected with StoreError::EntryAlreadyExists.
37 let err = store.define_var("name", "Bob");
38 println!("duplicate define_var: {err:?}");
39 assert!(err.is_err());
40
41 println!("store_scalars: ok");
42 Ok(())
43}Sourcepub fn define_array<N: Into<String>>(
&mut self,
name: N,
) -> Result<ArrayHandle<'_, StoreEntry>, StoreError>
pub fn define_array<N: Into<String>>( &mut self, name: N, ) -> Result<ArrayHandle<'_, StoreEntry>, StoreError>
Defines a new empty array entry and returns an ArrayHandle
for populating it.
Examples found in repository?
9fn main() -> Result<(), Box<dyn std::error::Error>> {
10 let mut store = Store::new();
11
12 // --- Chainable push ---
13 // push() accepts V: Into<StoreEntry>. The blanket impl
14 // `From<T: Into<Value>> for StoreEntry` means primitives work directly.
15 let mut arr = store.define_array("numbers")?.push(1)?.push(2)?.push(3)?;
16
17 let items = store.get("numbers")?.as_array()?;
18 println!("numbers: len={}", items.len());
19 assert_eq!(items.len(), 3);
20
21 // --- Chainable insert ---
22 // insert() accepts K: Into<String> and V: Into<StoreEntry>.
23 let mut map = store.define_map("config")?;
24 map.insert("host", "localhost")?
25 .insert("port", 8080i64)?
26 .insert("debug", true)?;
27
28 let host = store.get("config")?.get_key("host")?.get_value()?;
29 println!("config.host = {host:?}");
30
31 // --- Closure API on Store ---
32 // with_array scopes the handle so you don't need an explicit drop.
33 store.with_array("tags", |arr| {
34 arr.push("rust")?.push("pipeline")?.push("store")?;
35 Ok(())
36 })?;
37
38 let tags = store.get("tags")?.as_array()?;
39 println!("tags: len={}", tags.len());
40
41 store.with_map("metadata", |map| {
42 map.insert("version", "0.1.0")?.insert("stable", false)?;
43 Ok(())
44 })?;
45
46 let version = store.get("metadata")?.get_key("version")?.get_value()?;
47 println!("metadata.version = {version:?}");
48
49 // --- Nested construction via MapHandle closures ---
50 // with_array and with_map on MapHandle let you build nested structures
51 // without manually managing sub-handles.
52 store.with_map("server", |map| {
53 map.insert("name", "prod-01")?;
54
55 map.with_array("ports", |arr| {
56 arr.push(80)?.push(443)?;
57 Ok(())
58 })?;
59
60 map.with_map("tls", |tls| {
61 tls.insert("enabled", true)?
62 .insert("cert_path", "/etc/ssl/cert.pem")?;
63 Ok(())
64 })?;
65
66 Ok(())
67 })?;
68
69 let tls_enabled = store
70 .get("server")?
71 .get_key("tls")?
72 .get_key("enabled")?
73 .get_value()?;
74 println!("server.tls.enabled = {tls_enabled:?}");
75
76 // --- push_map on ArrayHandle ---
77 // Builds an array of maps — the most common pattern for tabular results.
78 let mut arr = store.define_array("users")?;
79 {
80 let mut user = arr.push_map()?;
81 user.insert("name", "Alice")?.insert("role", "admin")?;
82 }
83 {
84 let mut user = arr.push_map()?;
85 user.insert("name", "Bob")?.insert("role", "viewer")?;
86 }
87
88 let bob_role = store
89 .get("users")?
90 .get_index(1)?
91 .get_key("role")?
92 .get_value()?;
93 println!("users[1].role = {bob_role:?}");
94 assert_eq!(bob_role, &Value::Text("viewer".into()));
95
96 println!("store_collections: ok");
97 Ok(())
98}Sourcepub fn define_map<N: Into<String>>(
&mut self,
name: N,
) -> Result<MapHandle<'_, StoreEntry>, StoreError>
pub fn define_map<N: Into<String>>( &mut self, name: N, ) -> Result<MapHandle<'_, StoreEntry>, StoreError>
Defines a new empty map entry and returns a MapHandle for
populating it.
Examples found in repository?
9fn main() -> Result<(), Box<dyn std::error::Error>> {
10 let mut store = Store::new();
11
12 // --- Chainable push ---
13 // push() accepts V: Into<StoreEntry>. The blanket impl
14 // `From<T: Into<Value>> for StoreEntry` means primitives work directly.
15 let mut arr = store.define_array("numbers")?.push(1)?.push(2)?.push(3)?;
16
17 let items = store.get("numbers")?.as_array()?;
18 println!("numbers: len={}", items.len());
19 assert_eq!(items.len(), 3);
20
21 // --- Chainable insert ---
22 // insert() accepts K: Into<String> and V: Into<StoreEntry>.
23 let mut map = store.define_map("config")?;
24 map.insert("host", "localhost")?
25 .insert("port", 8080i64)?
26 .insert("debug", true)?;
27
28 let host = store.get("config")?.get_key("host")?.get_value()?;
29 println!("config.host = {host:?}");
30
31 // --- Closure API on Store ---
32 // with_array scopes the handle so you don't need an explicit drop.
33 store.with_array("tags", |arr| {
34 arr.push("rust")?.push("pipeline")?.push("store")?;
35 Ok(())
36 })?;
37
38 let tags = store.get("tags")?.as_array()?;
39 println!("tags: len={}", tags.len());
40
41 store.with_map("metadata", |map| {
42 map.insert("version", "0.1.0")?.insert("stable", false)?;
43 Ok(())
44 })?;
45
46 let version = store.get("metadata")?.get_key("version")?.get_value()?;
47 println!("metadata.version = {version:?}");
48
49 // --- Nested construction via MapHandle closures ---
50 // with_array and with_map on MapHandle let you build nested structures
51 // without manually managing sub-handles.
52 store.with_map("server", |map| {
53 map.insert("name", "prod-01")?;
54
55 map.with_array("ports", |arr| {
56 arr.push(80)?.push(443)?;
57 Ok(())
58 })?;
59
60 map.with_map("tls", |tls| {
61 tls.insert("enabled", true)?
62 .insert("cert_path", "/etc/ssl/cert.pem")?;
63 Ok(())
64 })?;
65
66 Ok(())
67 })?;
68
69 let tls_enabled = store
70 .get("server")?
71 .get_key("tls")?
72 .get_key("enabled")?
73 .get_value()?;
74 println!("server.tls.enabled = {tls_enabled:?}");
75
76 // --- push_map on ArrayHandle ---
77 // Builds an array of maps — the most common pattern for tabular results.
78 let mut arr = store.define_array("users")?;
79 {
80 let mut user = arr.push_map()?;
81 user.insert("name", "Alice")?.insert("role", "admin")?;
82 }
83 {
84 let mut user = arr.push_map()?;
85 user.insert("name", "Bob")?.insert("role", "viewer")?;
86 }
87
88 let bob_role = store
89 .get("users")?
90 .get_index(1)?
91 .get_key("role")?
92 .get_value()?;
93 println!("users[1].role = {bob_role:?}");
94 assert_eq!(bob_role, &Value::Text("viewer".into()));
95
96 println!("store_collections: ok");
97 Ok(())
98}Sourcepub fn with_array<N: Into<String>, F>(
&mut self,
name: N,
body: F,
) -> Result<(), StoreError>
pub fn with_array<N: Into<String>, F>( &mut self, name: N, body: F, ) -> Result<(), StoreError>
Defines a new array entry and passes a handle to a closure for
population. Convenience wrapper over define_array
when the nested structure would otherwise force awkward
temporaries.
Examples found in repository?
10fn write_query_results(store: &mut Store) -> Result<(), Box<dyn std::error::Error>> {
11 store.with_array("rows", |rows| {
12 // Row 1 — all fields inserted via chaining, no .into() needed.
13 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 // Row 2
20 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}More examples
9fn main() -> Result<(), Box<dyn std::error::Error>> {
10 let mut store = Store::new();
11
12 // --- Chainable push ---
13 // push() accepts V: Into<StoreEntry>. The blanket impl
14 // `From<T: Into<Value>> for StoreEntry` means primitives work directly.
15 let mut arr = store.define_array("numbers")?.push(1)?.push(2)?.push(3)?;
16
17 let items = store.get("numbers")?.as_array()?;
18 println!("numbers: len={}", items.len());
19 assert_eq!(items.len(), 3);
20
21 // --- Chainable insert ---
22 // insert() accepts K: Into<String> and V: Into<StoreEntry>.
23 let mut map = store.define_map("config")?;
24 map.insert("host", "localhost")?
25 .insert("port", 8080i64)?
26 .insert("debug", true)?;
27
28 let host = store.get("config")?.get_key("host")?.get_value()?;
29 println!("config.host = {host:?}");
30
31 // --- Closure API on Store ---
32 // with_array scopes the handle so you don't need an explicit drop.
33 store.with_array("tags", |arr| {
34 arr.push("rust")?.push("pipeline")?.push("store")?;
35 Ok(())
36 })?;
37
38 let tags = store.get("tags")?.as_array()?;
39 println!("tags: len={}", tags.len());
40
41 store.with_map("metadata", |map| {
42 map.insert("version", "0.1.0")?.insert("stable", false)?;
43 Ok(())
44 })?;
45
46 let version = store.get("metadata")?.get_key("version")?.get_value()?;
47 println!("metadata.version = {version:?}");
48
49 // --- Nested construction via MapHandle closures ---
50 // with_array and with_map on MapHandle let you build nested structures
51 // without manually managing sub-handles.
52 store.with_map("server", |map| {
53 map.insert("name", "prod-01")?;
54
55 map.with_array("ports", |arr| {
56 arr.push(80)?.push(443)?;
57 Ok(())
58 })?;
59
60 map.with_map("tls", |tls| {
61 tls.insert("enabled", true)?
62 .insert("cert_path", "/etc/ssl/cert.pem")?;
63 Ok(())
64 })?;
65
66 Ok(())
67 })?;
68
69 let tls_enabled = store
70 .get("server")?
71 .get_key("tls")?
72 .get_key("enabled")?
73 .get_value()?;
74 println!("server.tls.enabled = {tls_enabled:?}");
75
76 // --- push_map on ArrayHandle ---
77 // Builds an array of maps — the most common pattern for tabular results.
78 let mut arr = store.define_array("users")?;
79 {
80 let mut user = arr.push_map()?;
81 user.insert("name", "Alice")?.insert("role", "admin")?;
82 }
83 {
84 let mut user = arr.push_map()?;
85 user.insert("name", "Bob")?.insert("role", "viewer")?;
86 }
87
88 let bob_role = store
89 .get("users")?
90 .get_index(1)?
91 .get_key("role")?
92 .get_value()?;
93 println!("users[1].role = {bob_role:?}");
94 assert_eq!(bob_role, &Value::Text("viewer".into()));
95
96 println!("store_collections: ok");
97 Ok(())
98}Sourcepub fn with_map<N: Into<String>, F>(
&mut self,
name: N,
body: F,
) -> Result<(), StoreError>
pub fn with_map<N: Into<String>, F>( &mut self, name: N, body: F, ) -> Result<(), StoreError>
Defines a new map entry and passes a handle to a closure for population.
Examples found in repository?
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}More examples
9fn main() -> Result<(), Box<dyn std::error::Error>> {
10 let mut store = Store::new();
11
12 // --- Chainable push ---
13 // push() accepts V: Into<StoreEntry>. The blanket impl
14 // `From<T: Into<Value>> for StoreEntry` means primitives work directly.
15 let mut arr = store.define_array("numbers")?.push(1)?.push(2)?.push(3)?;
16
17 let items = store.get("numbers")?.as_array()?;
18 println!("numbers: len={}", items.len());
19 assert_eq!(items.len(), 3);
20
21 // --- Chainable insert ---
22 // insert() accepts K: Into<String> and V: Into<StoreEntry>.
23 let mut map = store.define_map("config")?;
24 map.insert("host", "localhost")?
25 .insert("port", 8080i64)?
26 .insert("debug", true)?;
27
28 let host = store.get("config")?.get_key("host")?.get_value()?;
29 println!("config.host = {host:?}");
30
31 // --- Closure API on Store ---
32 // with_array scopes the handle so you don't need an explicit drop.
33 store.with_array("tags", |arr| {
34 arr.push("rust")?.push("pipeline")?.push("store")?;
35 Ok(())
36 })?;
37
38 let tags = store.get("tags")?.as_array()?;
39 println!("tags: len={}", tags.len());
40
41 store.with_map("metadata", |map| {
42 map.insert("version", "0.1.0")?.insert("stable", false)?;
43 Ok(())
44 })?;
45
46 let version = store.get("metadata")?.get_key("version")?.get_value()?;
47 println!("metadata.version = {version:?}");
48
49 // --- Nested construction via MapHandle closures ---
50 // with_array and with_map on MapHandle let you build nested structures
51 // without manually managing sub-handles.
52 store.with_map("server", |map| {
53 map.insert("name", "prod-01")?;
54
55 map.with_array("ports", |arr| {
56 arr.push(80)?.push(443)?;
57 Ok(())
58 })?;
59
60 map.with_map("tls", |tls| {
61 tls.insert("enabled", true)?
62 .insert("cert_path", "/etc/ssl/cert.pem")?;
63 Ok(())
64 })?;
65
66 Ok(())
67 })?;
68
69 let tls_enabled = store
70 .get("server")?
71 .get_key("tls")?
72 .get_key("enabled")?
73 .get_value()?;
74 println!("server.tls.enabled = {tls_enabled:?}");
75
76 // --- push_map on ArrayHandle ---
77 // Builds an array of maps — the most common pattern for tabular results.
78 let mut arr = store.define_array("users")?;
79 {
80 let mut user = arr.push_map()?;
81 user.insert("name", "Alice")?.insert("role", "admin")?;
82 }
83 {
84 let mut user = arr.push_map()?;
85 user.insert("name", "Bob")?.insert("role", "viewer")?;
86 }
87
88 let bob_role = store
89 .get("users")?
90 .get_index(1)?
91 .get_key("role")?
92 .get_value()?;
93 println!("users[1].role = {bob_role:?}");
94 assert_eq!(bob_role, &Value::Text("viewer".into()));
95
96 println!("store_collections: ok");
97 Ok(())
98}