1use ambassador::delegatable_trait;
6
7use super::{
8 elem_type::{ImmOrPNode, PIndex, PValue, ValueKind},
9 interface::{IEnumeration, IFloat, IInteger, IString},
10 store::{CacheStore, FloatId, IntegerId, NodeId, NodeStore, StringId, ValueStore},
11 Device, GenApiError, GenApiResult, ValueCtxt,
12};
13
14#[delegatable_trait]
15pub(super) trait IValue<T> {
16 fn value<U: ValueStore, S: CacheStore>(
17 &self,
18 device: &mut impl Device,
19 store: &impl NodeStore,
20 cx: &mut ValueCtxt<U, S>,
21 ) -> GenApiResult<T>;
22
23 fn set_value<U: ValueStore, S: CacheStore>(
24 &self,
25 value: T,
26 device: &mut impl Device,
27 store: &impl NodeStore,
28 cx: &mut ValueCtxt<U, S>,
29 ) -> GenApiResult<()>;
30
31 fn is_readable<U: ValueStore, S: CacheStore>(
32 &self,
33 device: &mut impl Device,
34 store: &impl NodeStore,
35 cx: &mut ValueCtxt<U, S>,
36 ) -> GenApiResult<bool>;
37
38 fn is_writable<U: ValueStore, S: CacheStore>(
39 &self,
40 device: &mut impl Device,
41 store: &impl NodeStore,
42 cx: &mut ValueCtxt<U, S>,
43 ) -> GenApiResult<bool>;
44}
45
46macro_rules! impl_ivalue_for_imm {
47 ($imm_ty:ty, $result_ty:ty) => {
48 impl IValue<$result_ty> for $imm_ty {
49 fn value<U: ValueStore, S: CacheStore>(
50 &self,
51 _: &mut impl Device,
52 _: &impl NodeStore,
53 _: &mut ValueCtxt<U, S>,
54 ) -> GenApiResult<$result_ty> {
55 Ok(*self as $result_ty)
56 }
57
58 fn set_value<U, S>(
59 &self,
60 _: $result_ty,
61 _: &mut impl Device,
62 _: &impl NodeStore,
63 _: &mut ValueCtxt<U, S>,
64 ) -> GenApiResult<()> {
65 Err(GenApiError::not_writable())
66 }
67
68 fn is_readable<U: ValueStore, S: CacheStore>(
69 &self,
70 _: &mut impl Device,
71 _: &impl NodeStore,
72 _: &mut ValueCtxt<U, S>,
73 ) -> GenApiResult<bool> {
74 Ok(true)
75 }
76
77 fn is_writable<U: ValueStore, S: CacheStore>(
78 &self,
79 _: &mut impl Device,
80 _: &impl NodeStore,
81 _: &mut ValueCtxt<U, S>,
82 ) -> GenApiResult<bool> {
83 Ok(false)
84 }
85 }
86 };
87}
88impl_ivalue_for_imm!(i64, i64);
89impl_ivalue_for_imm!(i64, f64);
90impl_ivalue_for_imm!(f64, i64);
91impl_ivalue_for_imm!(f64, f64);
92
93macro_rules! impl_ivalue_for_vid {
94 ($ty:ty, $vid:ty, $f:ident) => {
95 impl IValue<$ty> for $vid {
96 fn value<U: ValueStore, S: CacheStore>(
97 &self,
98 _: &mut impl Device,
99 _: &impl NodeStore,
100 cx: &mut ValueCtxt<U, S>,
101 ) -> GenApiResult<$ty> {
102 Ok(cx.value_store.$f(*self).unwrap() as $ty)
103 }
104
105 fn set_value<U: ValueStore, S: CacheStore>(
106 &self,
107 value: $ty,
108 _: &mut impl Device,
109 _: &impl NodeStore,
110 cx: &mut ValueCtxt<U, S>,
111 ) -> GenApiResult<()> {
112 cx.value_store_mut().update(*self, value);
113 Ok(())
114 }
115
116 fn is_readable<U: ValueStore, S: CacheStore>(
117 &self,
118 _: &mut impl Device,
119 _: &impl NodeStore,
120 _: &mut ValueCtxt<U, S>,
121 ) -> GenApiResult<bool> {
122 Ok(true)
123 }
124
125 fn is_writable<U: ValueStore, S: CacheStore>(
126 &self,
127 _: &mut impl Device,
128 _: &impl NodeStore,
129 _: &mut ValueCtxt<U, S>,
130 ) -> GenApiResult<bool> {
131 Ok(true)
132 }
133 }
134 };
135}
136impl_ivalue_for_vid!(i64, IntegerId, integer_value);
137impl_ivalue_for_vid!(f64, IntegerId, integer_value);
138impl_ivalue_for_vid!(f64, FloatId, float_value);
139impl_ivalue_for_vid!(i64, FloatId, float_value);
140impl IValue<String> for StringId {
141 fn value<U: ValueStore, S: CacheStore>(
142 &self,
143 _: &mut impl Device,
144 _: &impl NodeStore,
145 cx: &mut ValueCtxt<U, S>,
146 ) -> GenApiResult<String> {
147 Ok(cx.value_store.str_value(*self).unwrap().into())
148 }
149
150 fn set_value<U: ValueStore, S: CacheStore>(
151 &self,
152 value: String,
153 _: &mut impl Device,
154 _: &impl NodeStore,
155 cx: &mut ValueCtxt<U, S>,
156 ) -> GenApiResult<()> {
157 cx.value_store_mut().update(*self, value);
158 Ok(())
159 }
160
161 fn is_readable<U: ValueStore, S: CacheStore>(
162 &self,
163 _: &mut impl Device,
164 _: &impl NodeStore,
165 _: &mut ValueCtxt<U, S>,
166 ) -> GenApiResult<bool> {
167 Ok(true)
168 }
169
170 fn is_writable<U: ValueStore, S: CacheStore>(
171 &self,
172 _: &mut impl Device,
173 _: &impl NodeStore,
174 _: &mut ValueCtxt<U, S>,
175 ) -> GenApiResult<bool> {
176 Ok(true)
177 }
178}
179
180impl IValue<i64> for NodeId {
181 fn value<U: ValueStore, S: CacheStore>(
182 &self,
183 device: &mut impl Device,
184 store: &impl NodeStore,
185 cx: &mut ValueCtxt<U, S>,
186 ) -> GenApiResult<i64> {
187 if let Some(i) = self.as_iinteger_kind(store) {
188 i.value(device, store, cx)
189 } else if let Some(f) = self.as_ifloat_kind(store) {
190 f.value(device, store, cx).map(|f| f as i64)
191 } else if let Some(e) = self.as_ienumeration_kind(store) {
192 e.current_value(device, store, cx)
193 } else {
194 Err(GenApiError::invalid_node(
195 format!("Node {:?} is not an integer, float, or enumeration", self).into(),
196 ))
197 }
198 }
199
200 fn set_value<U: ValueStore, S: CacheStore>(
201 &self,
202 value: i64,
203 device: &mut impl Device,
204 store: &impl NodeStore,
205 cx: &mut ValueCtxt<U, S>,
206 ) -> GenApiResult<()> {
207 if let Some(i) = self.as_iinteger_kind(store) {
208 i.set_value(value, device, store, cx)
209 } else if let Some(f) = self.as_ifloat_kind(store) {
210 f.set_value(value as f64, device, store, cx)
211 } else if let Some(e) = self.as_ienumeration_kind(store) {
212 e.set_entry_by_value(value, device, store, cx)
213 } else {
214 Err(GenApiError::not_writable())
215 }
216 }
217
218 fn is_readable<U: ValueStore, S: CacheStore>(
219 &self,
220 device: &mut impl Device,
221 store: &impl NodeStore,
222 cx: &mut ValueCtxt<U, S>,
223 ) -> GenApiResult<bool> {
224 if let Some(i) = self.as_iinteger_kind(store) {
225 i.is_readable(device, store, cx)
226 } else if let Some(f) = self.as_ifloat_kind(store) {
227 f.is_readable(device, store, cx)
228 } else if let Some(e) = self.as_ienumeration_kind(store) {
229 e.is_readable(device, store, cx)
230 } else {
231 Ok(false)
232 }
233 }
234
235 fn is_writable<U: ValueStore, S: CacheStore>(
236 &self,
237 device: &mut impl Device,
238 store: &impl NodeStore,
239 cx: &mut ValueCtxt<U, S>,
240 ) -> GenApiResult<bool> {
241 if let Some(i) = self.as_iinteger_kind(store) {
242 i.is_writable(device, store, cx)
243 } else if let Some(f) = self.as_ifloat_kind(store) {
244 f.is_writable(device, store, cx)
245 } else {
246 Ok(false)
247 }
248 }
249}
250
251impl IValue<f64> for NodeId {
252 fn value<U: ValueStore, S: CacheStore>(
253 &self,
254 device: &mut impl Device,
255 store: &impl NodeStore,
256 cx: &mut ValueCtxt<U, S>,
257 ) -> GenApiResult<f64> {
258 if let Some(i) = self.as_iinteger_kind(store) {
259 i.value(device, store, cx).map(|i| i as f64)
260 } else if let Some(f) = self.as_ifloat_kind(store) {
261 f.value(device, store, cx)
262 } else if let Some(e) = self.as_ienumeration_kind(store) {
263 e.current_value(device, store, cx).map(|i| i as f64)
264 } else {
265 Err(GenApiError::invalid_node(
266 format!("Node {:?} is not an integer, float, or enumeration", self).into(),
267 ))
268 }
269 }
270
271 fn set_value<U: ValueStore, S: CacheStore>(
272 &self,
273 value: f64,
274 device: &mut impl Device,
275 store: &impl NodeStore,
276 cx: &mut ValueCtxt<U, S>,
277 ) -> GenApiResult<()> {
278 if let Some(i) = self.as_iinteger_kind(store) {
279 i.set_value(value as i64, device, store, cx)
280 } else if let Some(f) = self.as_ifloat_kind(store) {
281 f.set_value(value, device, store, cx)
282 } else if let Some(e) = self.as_ienumeration_kind(store) {
283 e.set_entry_by_value(value as i64, device, store, cx)
284 } else {
285 Err(GenApiError::not_writable())
286 }
287 }
288
289 fn is_readable<U: ValueStore, S: CacheStore>(
290 &self,
291 device: &mut impl Device,
292 store: &impl NodeStore,
293 cx: &mut ValueCtxt<U, S>,
294 ) -> GenApiResult<bool> {
295 if let Some(i) = self.as_iinteger_kind(store) {
296 i.is_readable(device, store, cx)
297 } else if let Some(f) = self.as_ifloat_kind(store) {
298 f.is_readable(device, store, cx)
299 } else if let Some(e) = self.as_ienumeration_kind(store) {
300 e.is_readable(device, store, cx)
301 } else {
302 Ok(false)
303 }
304 }
305
306 fn is_writable<U: ValueStore, S: CacheStore>(
307 &self,
308 device: &mut impl Device,
309 store: &impl NodeStore,
310 cx: &mut ValueCtxt<U, S>,
311 ) -> GenApiResult<bool> {
312 if let Some(i) = self.as_iinteger_kind(store) {
313 i.is_writable(device, store, cx)
314 } else if let Some(f) = self.as_ifloat_kind(store) {
315 f.is_writable(device, store, cx)
316 } else {
317 Ok(false)
318 }
319 }
320}
321
322impl IValue<String> for NodeId {
323 fn value<U: ValueStore, S: CacheStore>(
324 &self,
325 device: &mut impl Device,
326 store: &impl NodeStore,
327 cx: &mut ValueCtxt<U, S>,
328 ) -> GenApiResult<String> {
329 self.expect_istring_kind(store)?.value(device, store, cx)
330 }
331
332 fn set_value<U: ValueStore, S: CacheStore>(
333 &self,
334 value: String,
335 device: &mut impl Device,
336 store: &impl NodeStore,
337 cx: &mut ValueCtxt<U, S>,
338 ) -> GenApiResult<()> {
339 self.expect_istring_kind(store)?
340 .set_value(value, device, store, cx)
341 }
342
343 fn is_readable<U: ValueStore, S: CacheStore>(
344 &self,
345 device: &mut impl Device,
346 store: &impl NodeStore,
347 cx: &mut ValueCtxt<U, S>,
348 ) -> GenApiResult<bool> {
349 self.expect_istring_kind(store)?
350 .is_readable(device, store, cx)
351 }
352
353 fn is_writable<U: ValueStore, S: CacheStore>(
354 &self,
355 device: &mut impl Device,
356 store: &impl NodeStore,
357 cx: &mut ValueCtxt<U, S>,
358 ) -> GenApiResult<bool> {
359 self.expect_istring_kind(store)?
360 .is_writable(device, store, cx)
361 }
362}
363
364impl<T, Ty> IValue<T> for ImmOrPNode<Ty>
365where
366 Ty: IValue<T>,
367 NodeId: IValue<T>,
368{
369 fn value<U: ValueStore, S: CacheStore>(
370 &self,
371 device: &mut impl Device,
372 store: &impl NodeStore,
373 cx: &mut ValueCtxt<U, S>,
374 ) -> GenApiResult<T> {
375 match self {
376 ImmOrPNode::Imm(i) => i.value(device, store, cx),
377 ImmOrPNode::PNode(nid) => nid.value(device, store, cx),
378 }
379 }
380
381 fn set_value<U: ValueStore, S: CacheStore>(
382 &self,
383 value: T,
384 device: &mut impl Device,
385 store: &impl NodeStore,
386 cx: &mut ValueCtxt<U, S>,
387 ) -> GenApiResult<()> {
388 match self {
389 ImmOrPNode::Imm(i) => i.set_value(value, device, store, cx),
390 ImmOrPNode::PNode(nid) => nid.set_value(value, device, store, cx),
391 }
392 }
393
394 fn is_readable<U: ValueStore, S: CacheStore>(
395 &self,
396 device: &mut impl Device,
397 store: &impl NodeStore,
398 cx: &mut ValueCtxt<U, S>,
399 ) -> GenApiResult<bool> {
400 match self {
401 ImmOrPNode::Imm(i) => i.is_readable(device, store, cx),
402 ImmOrPNode::PNode(nid) => nid.is_readable(device, store, cx),
403 }
404 }
405
406 fn is_writable<U: ValueStore, S: CacheStore>(
407 &self,
408 device: &mut impl Device,
409 store: &impl NodeStore,
410 cx: &mut ValueCtxt<U, S>,
411 ) -> GenApiResult<bool> {
412 match self {
413 ImmOrPNode::Imm(i) => i.is_writable(device, store, cx),
414 ImmOrPNode::PNode(nid) => nid.is_writable(device, store, cx),
415 }
416 }
417}
418
419impl<T, Ty> IValue<T> for ValueKind<Ty>
420where
421 Ty: IValue<T>,
422 PValue<Ty>: IValue<T>,
423 PIndex<Ty>: IValue<T>,
424{
425 fn value<U: ValueStore, S: CacheStore>(
426 &self,
427 device: &mut impl Device,
428 store: &impl NodeStore,
429 cx: &mut ValueCtxt<U, S>,
430 ) -> GenApiResult<T> {
431 match self {
432 ValueKind::Value(i) => i.value(device, store, cx),
433 ValueKind::PValue(p_value) => p_value.value(device, store, cx),
434 ValueKind::PIndex(p_index) => p_index.value(device, store, cx),
435 }
436 }
437
438 fn set_value<U: ValueStore, S: CacheStore>(
439 &self,
440 value: T,
441 device: &mut impl Device,
442 store: &impl NodeStore,
443 cx: &mut ValueCtxt<U, S>,
444 ) -> GenApiResult<()> {
445 match self {
446 ValueKind::Value(i) => i.set_value(value, device, store, cx),
447 ValueKind::PValue(p_value) => p_value.set_value(value, device, store, cx),
448 ValueKind::PIndex(p_index) => p_index.set_value(value, device, store, cx),
449 }
450 }
451
452 fn is_readable<U: ValueStore, S: CacheStore>(
453 &self,
454 device: &mut impl Device,
455 store: &impl NodeStore,
456 cx: &mut ValueCtxt<U, S>,
457 ) -> GenApiResult<bool> {
458 match self {
459 ValueKind::Value(i) => i.is_readable(device, store, cx),
460 ValueKind::PValue(p_value) => p_value.is_readable(device, store, cx),
461 ValueKind::PIndex(p_index) => p_index.is_readable(device, store, cx),
462 }
463 }
464
465 fn is_writable<U: ValueStore, S: CacheStore>(
466 &self,
467 device: &mut impl Device,
468 store: &impl NodeStore,
469 cx: &mut ValueCtxt<U, S>,
470 ) -> GenApiResult<bool> {
471 match self {
472 ValueKind::Value(i) => i.is_writable(device, store, cx),
473 ValueKind::PValue(p_value) => p_value.is_writable(device, store, cx),
474 ValueKind::PIndex(p_index) => p_index.is_writable(device, store, cx),
475 }
476 }
477}
478
479impl<T, Ty> IValue<T> for PValue<Ty>
480where
481 NodeId: IValue<T>,
482 T: Copy,
483{
484 fn value<U: ValueStore, S: CacheStore>(
485 &self,
486 device: &mut impl Device,
487 store: &impl NodeStore,
488 cx: &mut ValueCtxt<U, S>,
489 ) -> GenApiResult<T> {
490 self.p_value.value(device, store, cx)
491 }
492
493 fn set_value<U: ValueStore, S: CacheStore>(
494 &self,
495 value: T,
496 device: &mut impl Device,
497 store: &impl NodeStore,
498 cx: &mut ValueCtxt<U, S>,
499 ) -> GenApiResult<()> {
500 self.p_value.set_value(value, device, store, cx)?;
501 for nid in self.p_value_copies() {
502 nid.set_value(value, device, store, cx)?;
503 }
504 Ok(())
505 }
506
507 fn is_readable<U: ValueStore, S: CacheStore>(
508 &self,
509 device: &mut impl Device,
510 store: &impl NodeStore,
511 cx: &mut ValueCtxt<U, S>,
512 ) -> GenApiResult<bool> {
513 self.p_value.is_readable(device, store, cx)
514 }
515
516 fn is_writable<U: ValueStore, S: CacheStore>(
517 &self,
518 device: &mut impl Device,
519 store: &impl NodeStore,
520 cx: &mut ValueCtxt<U, S>,
521 ) -> GenApiResult<bool> {
522 let mut b = self.p_value.is_writable(device, store, cx)?;
523 for nid in self.p_value_copies() {
524 b &= nid.is_writable(device, store, cx)?;
525 }
526 Ok(b)
527 }
528}
529
530impl<T, Ty> IValue<T> for PIndex<Ty>
531where
532 Ty: IValue<T>,
533 ImmOrPNode<Ty>: IValue<T>,
534{
535 fn value<U: ValueStore, S: CacheStore>(
536 &self,
537 device: &mut impl Device,
538 store: &impl NodeStore,
539 cx: &mut ValueCtxt<U, S>,
540 ) -> GenApiResult<T> {
541 let index = self.index(device, store, cx)?;
542 if let Some(value_indexed) = self.value_indexed.iter().find(|vi| vi.index == index) {
543 value_indexed.indexed.value(device, store, cx)
544 } else {
545 self.value_default.value(device, store, cx)
546 }
547 }
548
549 fn set_value<U: ValueStore, S: CacheStore>(
550 &self,
551 value: T,
552 device: &mut impl Device,
553 store: &impl NodeStore,
554 cx: &mut ValueCtxt<U, S>,
555 ) -> GenApiResult<()> {
556 let index = self.index(device, store, cx)?;
557 if let Some(value_indexed) = self.value_indexed.iter().find(|vi| vi.index == index) {
558 value_indexed.indexed.set_value(value, device, store, cx)
559 } else {
560 self.value_default.set_value(value, device, store, cx)
561 }
562 }
563
564 fn is_readable<U: ValueStore, S: CacheStore>(
565 &self,
566 device: &mut impl Device,
567 store: &impl NodeStore,
568 cx: &mut ValueCtxt<U, S>,
569 ) -> GenApiResult<bool> {
570 Ok(self
571 .p_index
572 .expect_iinteger_kind(store)?
573 .is_readable(device, store, cx)?
574 && {
575 let index = self.index(device, store, cx)?;
576 if let Some(value_indexed) = self.value_indexed.iter().find(|vi| vi.index == index)
577 {
578 value_indexed.indexed.is_readable(device, store, cx)?
579 } else {
580 self.value_default.is_readable(device, store, cx)?
581 }
582 })
583 }
584
585 fn is_writable<U: ValueStore, S: CacheStore>(
586 &self,
587 device: &mut impl Device,
588 store: &impl NodeStore,
589 cx: &mut ValueCtxt<U, S>,
590 ) -> GenApiResult<bool> {
591 Ok(self
592 .p_index
593 .expect_iinteger_kind(store)?
594 .is_readable(device, store, cx)?
595 && {
596 let index = self.index(device, store, cx)?;
597 if let Some(value_indexed) = self.value_indexed.iter().find(|vi| vi.index == index)
598 {
599 value_indexed.indexed.is_writable(device, store, cx)?
600 } else {
601 self.value_default.is_writable(device, store, cx)?
602 }
603 })
604 }
605}
606
607impl<T> PIndex<T> {
608 fn index<U: ValueStore, S: CacheStore>(
609 &self,
610 device: &mut impl Device,
611 store: &impl NodeStore,
612 cx: &mut ValueCtxt<U, S>,
613 ) -> GenApiResult<i64> {
614 self.p_index
615 .expect_iinteger_kind(store)?
616 .value(device, store, cx)
617 }
618}