1use super::{
6 elem_type::{IntegerRepresentation, NamedValue, Slope},
7 formula::{Expr, Formula},
8 interface::{IInteger, INode, IncrementMode},
9 node_base::{NodeAttributeBase, NodeBase, NodeElementBase},
10 store::{CacheStore, NodeId, NodeStore, ValueStore},
11 utils, Device, GenApiError, GenApiResult, ValueCtxt,
12};
13
14#[derive(Debug, Clone)]
15pub struct IntConverterNode {
16 pub(crate) attr_base: NodeAttributeBase,
17 pub(crate) elem_base: NodeElementBase,
18
19 pub(crate) streamable: bool,
20 pub(crate) p_variables: Vec<NamedValue<NodeId>>,
21 pub(crate) constants: Vec<NamedValue<i64>>,
22 pub(crate) expressions: Vec<NamedValue<Expr>>,
23 pub(crate) formula_to: Formula,
24 pub(crate) formula_from: Formula,
25 pub(crate) p_value: NodeId,
26 pub(crate) unit: Option<String>,
27 pub(crate) representation: IntegerRepresentation,
28 pub(crate) slope: Slope,
29}
30
31impl IntConverterNode {
32 #[must_use]
33 pub fn p_variables(&self) -> &[NamedValue<NodeId>] {
34 &self.p_variables
35 }
36
37 #[must_use]
38 pub fn constants(&self) -> &[NamedValue<i64>] {
39 &self.constants
40 }
41
42 #[must_use]
43 pub fn expressions(&self) -> &[NamedValue<Expr>] {
44 &self.expressions
45 }
46
47 #[must_use]
48 pub fn formula_to(&self) -> &Formula {
49 &self.formula_to
50 }
51
52 #[must_use]
53 pub fn formula_from(&self) -> &Formula {
54 &self.formula_from
55 }
56
57 #[must_use]
58 pub fn p_value(&self) -> NodeId {
59 self.p_value
60 }
61
62 #[must_use]
63 pub fn unit_elem(&self) -> Option<&str> {
64 self.unit.as_deref()
65 }
66
67 #[must_use]
68 pub fn representation_elem(&self) -> IntegerRepresentation {
69 self.representation
70 }
71
72 #[must_use]
73 pub fn slope(&self) -> Slope {
74 self.slope
75 }
76}
77
78impl INode for IntConverterNode {
79 fn node_base(&self) -> NodeBase {
80 NodeBase::new(&self.attr_base, &self.elem_base)
81 }
82
83 fn streamable(&self) -> bool {
84 self.streamable
85 }
86}
87
88impl IInteger for IntConverterNode {
89 #[tracing::instrument(skip(self, device, store, cx),
90 level = "trace",
91 fields(node = store.name_by_id(self.node_base().id()).unwrap()))]
92 fn value<T: ValueStore, U: CacheStore>(
93 &self,
94 device: &mut impl Device,
95 store: &impl NodeStore,
96 cx: &mut ValueCtxt<T, U>,
97 ) -> GenApiResult<i64> {
98 let mut collector =
99 utils::FormulaEnvCollector::new(&self.p_variables, &self.constants, &self.expressions);
100 collector.insert("TO", self.p_value(), device, store, cx)?;
101 let var_env = collector.collect(device, store, cx)?;
102
103 let eval_result = self.formula_from.eval(&var_env)?;
104 Ok(eval_result.as_integer())
105 }
106
107 #[tracing::instrument(skip(self, device, store, cx),
108 level = "trace",
109 fields(node = store.name_by_id(self.node_base().id()).unwrap()))]
110 fn set_value<T: ValueStore, U: CacheStore>(
111 &self,
112 value: i64,
113 device: &mut impl Device,
114 store: &impl NodeStore,
115 cx: &mut ValueCtxt<T, U>,
116 ) -> GenApiResult<()> {
117 cx.invalidate_cache_by(self.node_base().id());
118
119 let mut collector =
120 utils::FormulaEnvCollector::new(&self.p_variables, &self.constants, &self.expressions);
121 collector.insert_imm("FROM", value);
122 let var_env = collector.collect(device, store, cx)?;
123
124 let eval_result = self.formula_to.eval(&var_env)?;
125 utils::set_eval_result(self.p_value, eval_result, device, store, cx)?;
126 Ok(())
127 }
128
129 fn min<T: ValueStore, U: CacheStore>(
130 &self,
131 _: &mut impl Device,
132 _: &impl NodeStore,
133 _: &mut ValueCtxt<T, U>,
134 ) -> GenApiResult<i64> {
135 Ok(i64::MIN)
136 }
137
138 fn max<T: ValueStore, U: CacheStore>(
139 &self,
140 _: &mut impl Device,
141 _: &impl NodeStore,
142 _: &mut ValueCtxt<T, U>,
143 ) -> GenApiResult<i64> {
144 Ok(i64::MAX)
145 }
146
147 fn inc_mode(&self, _: &impl NodeStore) -> Option<IncrementMode> {
148 None
149 }
150
151 fn inc<T: ValueStore, U: CacheStore>(
152 &self,
153 _: &mut impl Device,
154 _: &impl NodeStore,
155 _: &mut ValueCtxt<T, U>,
156 ) -> GenApiResult<Option<i64>> {
157 Ok(None)
158 }
159
160 fn valid_value_set(&self, _: &impl NodeStore) -> &[i64] {
161 &[]
162 }
163
164 fn representation(&self, _: &impl NodeStore) -> IntegerRepresentation {
165 self.representation
166 }
167
168 fn unit(&self, _: &impl NodeStore) -> Option<&str> {
169 None
170 }
171
172 #[tracing::instrument(skip(self, store),
173 level = "trace",
174 fields(node = store.name_by_id(self.node_base().id()).unwrap()))]
175 fn set_min<T: ValueStore, U: CacheStore>(
176 &self,
177 _: i64,
178 _: &mut impl Device,
179 store: &impl NodeStore,
180 _: &mut ValueCtxt<T, U>,
181 ) -> GenApiResult<()> {
182 Err(GenApiError::not_writable())
183 }
184
185 #[tracing::instrument(skip(self, store),
186 level = "trace",
187 fields(node = store.name_by_id(self.node_base().id()).unwrap()))]
188 fn set_max<T: ValueStore, U: CacheStore>(
189 &self,
190 _: i64,
191 _: &mut impl Device,
192 store: &impl NodeStore,
193 _: &mut ValueCtxt<T, U>,
194 ) -> GenApiResult<()> {
195 Err(GenApiError::not_writable())
196 }
197
198 #[tracing::instrument(skip(self, device, store, cx),
199 level = "trace",
200 fields(node = store.name_by_id(self.node_base().id()).unwrap()))]
201 fn is_readable<T: ValueStore, U: CacheStore>(
202 &self,
203 device: &mut impl Device,
204 store: &impl NodeStore,
205 cx: &mut ValueCtxt<T, U>,
206 ) -> GenApiResult<bool> {
207 let collector =
208 utils::FormulaEnvCollector::new(&self.p_variables, &self.constants, &self.expressions);
209 Ok(self.elem_base.is_readable(device, store, cx)?
210 && utils::is_nid_readable(self.p_value, device, store, cx)?
211 && collector.is_readable(device, store, cx)?)
212 }
213
214 #[tracing::instrument(skip(self, device, store, cx),
215 level = "trace",
216 fields(node = store.name_by_id(self.node_base().id()).unwrap()))]
217 fn is_writable<T: ValueStore, U: CacheStore>(
218 &self,
219 device: &mut impl Device,
220 store: &impl NodeStore,
221 cx: &mut ValueCtxt<T, U>,
222 ) -> GenApiResult<bool> {
223 let collector =
224 utils::FormulaEnvCollector::new(&self.p_variables, &self.constants, &self.expressions);
225 Ok(self.elem_base.is_writable(device, store, cx)?
226 && utils::is_nid_writable(self.p_value, device, store, cx)?
227 && collector.is_readable(device, store, cx)?) }
229}