bc_envelope/extension/expressions/parameters_store.rs
1use std::collections::HashMap;
2
3use super::Parameter;
4
5/// A store that maps parameters to their assigned names.
6///
7/// `ParametersStore` maintains a registry of parameters and their
8/// human-readable names, which is useful for displaying and debugging
9/// expression parameters. The store allows for consistent name resolution of
10/// parameters used in expressions.
11///
12/// # Examples
13///
14/// ```
15/// use bc_envelope::{
16/// extension::expressions::{ParametersStore, parameters},
17/// prelude::*,
18/// };
19///
20/// // Create a store with common parameters
21/// let store = ParametersStore::new([
22/// parameters::LHS,
23/// parameters::RHS,
24/// parameters::BLANK,
25/// ]);
26///
27/// // Look up the name of a parameter
28/// assert_eq!(store.name(¶meters::LHS), "lhs");
29/// ```
30#[derive(Clone, Debug)]
31pub struct ParametersStore {
32 dict: HashMap<Parameter, String>,
33}
34
35impl ParametersStore {
36 /// Creates a new `ParametersStore` with the given parameters.
37 ///
38 /// # Parameters
39 ///
40 /// * `parameters` - An iterable of `Parameter` instances to store
41 ///
42 /// # Returns
43 ///
44 /// A new `ParametersStore` containing the parameters
45 ///
46 /// # Examples
47 ///
48 /// ```
49 /// use bc_envelope::{
50 /// extension::expressions::{ParametersStore, parameters},
51 /// prelude::*,
52 /// };
53 ///
54 /// // Create a store with standard parameters
55 /// let store = ParametersStore::new([
56 /// parameters::LHS,
57 /// parameters::RHS,
58 /// parameters::BLANK,
59 /// ]);
60 /// ```
61 pub fn new<T>(parameters: T) -> Self
62 where
63 T: IntoIterator<Item = Parameter>,
64 {
65 let mut dict = HashMap::new();
66 for parameter in parameters {
67 Self::_insert(parameter, &mut dict);
68 }
69 Self { dict }
70 }
71
72 /// Inserts a parameter into the store.
73 ///
74 /// # Parameters
75 ///
76 /// * `parameter` - The parameter to insert
77 ///
78 /// # Examples
79 ///
80 /// ```
81 /// use bc_envelope::{
82 /// extension::expressions::{Parameter, ParametersStore, parameters},
83 /// prelude::*,
84 /// };
85 ///
86 /// let mut store = ParametersStore::default();
87 /// store.insert(parameters::LHS);
88 /// store.insert(Parameter::new_with_static_name(100, "myCustomParameter"));
89 /// ```
90 pub fn insert(&mut self, parameter: Parameter) {
91 Self::_insert(parameter, &mut self.dict);
92 }
93
94 /// Returns the assigned name for a parameter, if it exists in the store.
95 ///
96 /// # Parameters
97 ///
98 /// * `parameter` - The parameter to look up
99 ///
100 /// # Returns
101 ///
102 /// Some string slice with the parameter name if found, or None if not found
103 ///
104 /// # Examples
105 ///
106 /// ```
107 /// use bc_envelope::{
108 /// extension::expressions::{ParametersStore, parameters},
109 /// prelude::*,
110 /// };
111 ///
112 /// let store = ParametersStore::new([parameters::LHS]);
113 /// assert_eq!(store.assigned_name(¶meters::LHS), Some("lhs"));
114 /// assert_eq!(store.assigned_name(¶meters::RHS), None);
115 /// ```
116 pub fn assigned_name(&self, parameter: &Parameter) -> Option<&str> {
117 self.dict.get(parameter).map(|name| name.as_str())
118 }
119
120 /// Returns the name for a parameter, either from this store or from the
121 /// parameter itself.
122 ///
123 /// If the parameter exists in the store, returns its assigned name.
124 /// Otherwise, returns the parameter's own name.
125 ///
126 /// # Parameters
127 ///
128 /// * `parameter` - The parameter to look up
129 ///
130 /// # Returns
131 ///
132 /// The name of the parameter as a String
133 ///
134 /// # Examples
135 ///
136 /// ```
137 /// use bc_envelope::{
138 /// extension::expressions::{ParametersStore, parameters},
139 /// prelude::*,
140 /// };
141 ///
142 /// let store = ParametersStore::new([parameters::LHS]);
143 /// assert_eq!(store.name(¶meters::LHS), "lhs");
144 /// // Not in store, so uses parameter's own name
145 /// assert_eq!(store.name(¶meters::RHS), "rhs");
146 /// ```
147 pub fn name(&self, parameter: &Parameter) -> String {
148 self.assigned_name(parameter)
149 .map(|name| name.to_string())
150 .unwrap_or_else(|| parameter.name())
151 }
152
153 /// A static method that returns the name of a parameter, using an optional
154 /// store.
155 ///
156 /// This utility method is useful when you have an optional store and want
157 /// to get a parameter name without additional unwrapping logic.
158 ///
159 /// # Parameters
160 ///
161 /// * `parameter` - The parameter to look up
162 /// * `parameters` - An optional reference to a ParametersStore
163 ///
164 /// # Returns
165 ///
166 /// The name of the parameter as a String
167 ///
168 /// # Examples
169 ///
170 /// ```
171 /// use bc_envelope::{
172 /// extension::expressions::{ParametersStore, parameters},
173 /// prelude::*,
174 /// };
175 ///
176 /// let store = ParametersStore::new([parameters::LHS]);
177 ///
178 /// // Using the store
179 /// assert_eq!(
180 /// ParametersStore::name_for_parameter(¶meters::LHS, Some(&store)),
181 /// "lhs"
182 /// );
183 ///
184 /// // Without a store
185 /// assert_eq!(
186 /// ParametersStore::name_for_parameter(¶meters::LHS, None),
187 /// "lhs"
188 /// );
189 /// ```
190 pub fn name_for_parameter(
191 parameter: &Parameter,
192 parameters: Option<&Self>,
193 ) -> String {
194 parameters
195 .and_then(|parameters| parameters.assigned_name(parameter))
196 .map(|name| name.to_string())
197 .unwrap_or_else(|| parameter.name())
198 }
199
200 /// Private helper method to insert a parameter into the dictionary.
201 ///
202 /// This handles the validation and naming logic for parameter insertion.
203 fn _insert(parameter: Parameter, dict: &mut HashMap<Parameter, String>) {
204 match parameter {
205 Parameter::Known(_, _) => {
206 let name = parameter.name();
207 dict.insert(parameter, name);
208 }
209 _ => panic!(),
210 }
211 }
212}
213
214/// Provides a default empty store.
215impl Default for ParametersStore {
216 fn default() -> Self { Self::new([]) }
217}