1use super::{
6 elem_type::ImmOrPNode,
7 interface::{IBoolean, INode, ISelector},
8 ivalue::IValue,
9 node_base::{NodeAttributeBase, NodeBase, NodeElementBase},
10 store::{CacheStore, IntegerId, NodeId, NodeStore, ValueStore},
11 Device, GenApiError, GenApiResult, ValueCtxt,
12};
13
14#[derive(Debug, Clone)]
15pub struct BooleanNode {
16 pub(crate) attr_base: NodeAttributeBase,
17 pub(crate) elem_base: NodeElementBase,
18
19 pub(crate) streamable: bool,
20 pub(crate) value: ImmOrPNode<IntegerId>,
21 pub(crate) on_value: i64,
22 pub(crate) off_value: i64,
23 pub(crate) p_selected: Vec<NodeId>,
24}
25
26impl BooleanNode {
27 #[must_use]
28 pub fn value_elem(&self) -> ImmOrPNode<IntegerId> {
29 self.value
30 }
31
32 #[must_use]
33 pub fn on_value(&self) -> i64 {
34 self.on_value
35 }
36
37 #[must_use]
38 pub fn off_value(&self) -> i64 {
39 self.off_value
40 }
41
42 #[must_use]
43 pub fn p_selected(&self) -> &[NodeId] {
44 &self.p_selected
45 }
46}
47
48impl INode for BooleanNode {
49 fn node_base(&self) -> NodeBase {
50 NodeBase::new(&self.attr_base, &self.elem_base)
51 }
52
53 fn streamable(&self) -> bool {
54 self.streamable
55 }
56}
57
58impl IBoolean for BooleanNode {
59 #[tracing::instrument(skip(self, device, store, cx),
60 level = "trace",
61 fields(node = store.name_by_id(self.node_base().id()).unwrap()))]
62 fn value<T: ValueStore, U: CacheStore>(
63 &self,
64 device: &mut impl Device,
65 store: &impl NodeStore,
66 cx: &mut ValueCtxt<T, U>,
67 ) -> GenApiResult<bool> {
68 let value: i64 = self.value.value(device, store, cx)?;
69 if value == self.on_value {
70 Ok(true)
71 } else if value == self.off_value {
72 Ok(false)
73 } else {
74 Err(GenApiError::invalid_node(
75 "the internal integer value cannot be interpreted as boolean".into(),
76 ))
77 }
78 }
79
80 #[tracing::instrument(skip(self, device, store, cx),
81 level = "trace",
82 fields(node = store.name_by_id(self.node_base().id()).unwrap()))]
83 fn set_value<T: ValueStore, U: CacheStore>(
84 &self,
85 value: bool,
86 device: &mut impl Device,
87 store: &impl NodeStore,
88 cx: &mut ValueCtxt<T, U>,
89 ) -> GenApiResult<()> {
90 cx.invalidate_cache_by(self.node_base().id());
91 let value = if value { self.on_value } else { self.off_value };
92 self.value.set_value(value, device, store, cx)
93 }
94
95 #[tracing::instrument(skip(self, device, store, cx),
96 level = "trace",
97 fields(node = store.name_by_id(self.node_base().id()).unwrap()))]
98 fn is_readable<T: ValueStore, U: CacheStore>(
99 &self,
100 device: &mut impl Device,
101 store: &impl NodeStore,
102 cx: &mut ValueCtxt<T, U>,
103 ) -> GenApiResult<bool> {
104 Ok(self.elem_base.is_readable(device, store, cx)?
105 && IValue::<i64>::is_readable(&self.value, device, store, cx)?)
106 }
107
108 #[tracing::instrument(skip(self, device, store, cx),
109 level = "trace",
110 fields(node = store.name_by_id(self.node_base().id()).unwrap()))]
111 fn is_writable<T: ValueStore, U: CacheStore>(
112 &self,
113 device: &mut impl Device,
114 store: &impl NodeStore,
115 cx: &mut ValueCtxt<T, U>,
116 ) -> GenApiResult<bool> {
117 Ok(self.elem_base.is_writable(device, store, cx)?
118 && IValue::<i64>::is_writable(&self.value, device, store, cx)?)
119 }
120}
121
122impl ISelector for BooleanNode {
123 fn selecting_nodes(&self, _store: &impl NodeStore) -> GenApiResult<&[NodeId]> {
124 Ok(self.p_selected())
125 }
126}