1use std::{collections::HashMap, convert::TryFrom};
6
7use auto_impl::auto_impl;
8use string_interner::{DefaultBackend, StringInterner, Symbol};
9
10use super::{
11 builder,
12 interface::{
13 IBooleanKind, ICategoryKind, ICommandKind, IEnumerationKind, IFloatKind, IIntegerKind,
14 INode, INodeKind, IPortKind, IRegisterKind, ISelectorKind, IStringKind,
15 },
16 node_base::NodeBase,
17 BooleanNode, CategoryNode, CommandNode, ConverterNode, EnumEntryNode, EnumerationNode,
18 FloatNode, FloatRegNode, GenApiError, GenApiResult, IntConverterNode, IntRegNode,
19 IntSwissKnifeNode, IntegerNode, MaskedIntRegNode, Node, PortNode, RegisterNode, StringNode,
20 StringRegNode, SwissKnifeNode,
21};
22
23#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
24pub struct NodeId(u32);
25
26#[derive(Debug, Clone)]
27pub enum NodeData {
28 Node(Box<Node>),
29 Category(Box<CategoryNode>),
30 Integer(Box<IntegerNode>),
31 IntReg(Box<IntRegNode>),
32 MaskedIntReg(Box<MaskedIntRegNode>),
33 Boolean(Box<BooleanNode>),
34 Command(Box<CommandNode>),
35 Enumeration(Box<EnumerationNode>),
36 EnumEntry(Box<EnumEntryNode>),
37 Float(Box<FloatNode>),
38 FloatReg(Box<FloatRegNode>),
39 String(Box<StringNode>),
40 StringReg(Box<StringRegNode>),
41 Register(Box<RegisterNode>),
42 Converter(Box<ConverterNode>),
43 IntConverter(Box<IntConverterNode>),
44 SwissKnife(Box<SwissKnifeNode>),
45 IntSwissKnife(Box<IntSwissKnifeNode>),
46 Port(Box<PortNode>),
47
48 ConfRom(()),
50 TextDesc(()),
51 IntKey(()),
52 AdvFeatureLock(()),
53 SmartFeature(()),
54}
55
56#[auto_impl(&, &mut, Box, Rc, Arc)]
57pub trait NodeStore {
58 fn name_by_id(&self, nid: NodeId) -> Option<&str>;
59
60 fn id_by_name<T>(&self, s: T) -> Option<NodeId>
61 where
62 T: AsRef<str>;
63
64 fn node_opt(&self, nid: NodeId) -> Option<&NodeData>;
65
66 fn node(&self, nid: NodeId) -> &NodeData {
67 self.node_opt(nid).unwrap()
68 }
69
70 fn visit_nodes<F>(&self, f: F)
71 where
72 F: FnMut(&NodeData);
73}
74
75#[auto_impl(&mut, Box)]
76pub trait ValueStore {
77 fn value_opt<T>(&self, id: T) -> Option<&ValueData>
78 where
79 T: Into<ValueId>;
80
81 fn update<T, U>(&mut self, id: T, value: U) -> Option<ValueData>
82 where
83 T: Into<ValueId>,
84 U: Into<ValueData>;
85
86 fn value(&self, id: impl Into<ValueId>) -> &ValueData {
87 self.value_opt(id).unwrap()
88 }
89
90 fn integer_value<T>(&self, id: T) -> Option<i64>
91 where
92 T: Into<ValueId>,
93 {
94 match self.value_opt(id)? {
95 ValueData::Integer(i) => Some(*i),
96 ValueData::Float(f) => Some(*f as i64),
97 _ => None,
98 }
99 }
100
101 fn float_value<T>(&self, id: T) -> Option<f64>
102 where
103 T: Into<ValueId>,
104 {
105 match self.value_opt(id)? {
106 ValueData::Integer(i) => Some(*i as f64),
107 ValueData::Float(f) => Some(*f),
108 _ => None,
109 }
110 }
111
112 fn str_value<T>(&self, id: T) -> Option<&String>
113 where
114 T: Into<ValueId>,
115 {
116 if let ValueData::Str(s) = self.value_opt(id)? {
117 Some(s)
118 } else {
119 None
120 }
121 }
122}
123
124#[auto_impl(&mut, Box)]
125pub trait CacheStore {
126 fn cache(&mut self, nid: NodeId, address: i64, length: i64, data: &[u8]);
127
128 fn get_cache(&self, nid: NodeId, address: i64, length: i64) -> Option<&[u8]>;
129
130 fn invalidate_by(&mut self, nid: NodeId);
131
132 fn invalidate_of(&mut self, nid: NodeId);
133
134 fn clear(&mut self);
135}
136
137impl Symbol for NodeId {
138 fn try_from_usize(index: usize) -> Option<Self> {
139 if ((u32::MAX - 1) as usize) < index {
140 None
141 } else {
142 #[allow(clippy::cast_possible_truncation)]
143 Some(Self(index as u32))
144 }
145 }
146
147 fn to_usize(self) -> usize {
148 self.0 as usize
149 }
150}
151
152impl NodeId {
153 pub fn name(self, store: &impl NodeStore) -> &str {
154 store.name_by_id(self).unwrap()
155 }
156
157 pub fn as_inode_kind(self, store: &impl NodeStore) -> Option<INodeKind> {
158 INodeKind::maybe_from(self, store)
159 }
160
161 pub fn expect_inode_kind(self, store: &impl NodeStore) -> GenApiResult<INodeKind> {
162 self.as_inode_kind(store).ok_or_else(|| {
163 GenApiError::invalid_node("the node doesn't implement `IInteger`".into())
164 })
165 }
166
167 pub fn as_iinteger_kind(self, store: &impl NodeStore) -> Option<IIntegerKind> {
168 IIntegerKind::maybe_from(self, store)
169 }
170
171 pub fn expect_iinteger_kind(self, store: &impl NodeStore) -> GenApiResult<IIntegerKind> {
172 self.as_iinteger_kind(store).ok_or_else(|| {
173 GenApiError::invalid_node("the node doesn't implement `IInteger`".into())
174 })
175 }
176
177 pub fn as_ifloat_kind(self, store: &impl NodeStore) -> Option<IFloatKind> {
178 IFloatKind::maybe_from(self, store)
179 }
180
181 pub fn expect_ifloat_kind(self, store: &impl NodeStore) -> GenApiResult<IFloatKind> {
182 self.as_ifloat_kind(store)
183 .ok_or_else(|| GenApiError::invalid_node("the node doesn't implement `IFloat`".into()))
184 }
185
186 pub fn as_istring_kind(self, store: &impl NodeStore) -> Option<IStringKind> {
187 IStringKind::maybe_from(self, store)
188 }
189
190 pub fn expect_istring_kind(self, store: &impl NodeStore) -> GenApiResult<IStringKind> {
191 self.as_istring_kind(store)
192 .ok_or_else(|| GenApiError::invalid_node("the node doesn't implement `IString`".into()))
193 }
194
195 pub fn as_icommand_kind(self, store: &impl NodeStore) -> Option<ICommandKind> {
196 ICommandKind::maybe_from(self, store)
197 }
198
199 pub fn expect_icommand_kind(self, store: &impl NodeStore) -> GenApiResult<ICommandKind> {
200 self.as_icommand_kind(store).ok_or_else(|| {
201 GenApiError::invalid_node("the node doesn't implement `ICommand`".into())
202 })
203 }
204
205 pub fn as_ienumeration_kind(self, store: &impl NodeStore) -> Option<IEnumerationKind> {
206 IEnumerationKind::maybe_from(self, store)
207 }
208
209 pub fn expect_ienumeration_kind(
210 self,
211 store: &impl NodeStore,
212 ) -> GenApiResult<IEnumerationKind> {
213 self.as_ienumeration_kind(store).ok_or_else(|| {
214 GenApiError::invalid_node("the node doesn't implement `IEnumeration`".into())
215 })
216 }
217
218 pub fn as_iboolean_kind(self, store: &impl NodeStore) -> Option<IBooleanKind> {
219 IBooleanKind::maybe_from(self, store)
220 }
221
222 pub fn expect_iboolean_kind(self, store: &impl NodeStore) -> GenApiResult<IBooleanKind> {
223 self.as_iboolean_kind(store).ok_or_else(|| {
224 GenApiError::invalid_node("the node doesn't implement `IBoolean`".into())
225 })
226 }
227
228 pub fn as_iregister_kind(self, store: &impl NodeStore) -> Option<IRegisterKind> {
229 IRegisterKind::maybe_from(self, store)
230 }
231
232 pub fn expect_iregister_kind(self, store: &impl NodeStore) -> GenApiResult<IRegisterKind> {
233 self.as_iregister_kind(store).ok_or_else(|| {
234 GenApiError::invalid_node("the node doesn't implement `IRegister`".into())
235 })
236 }
237
238 pub fn as_icategory_kind(self, store: &impl NodeStore) -> Option<ICategoryKind> {
239 ICategoryKind::maybe_from(self, store)
240 }
241
242 pub fn expect_icategory_kind(self, store: &impl NodeStore) -> GenApiResult<ICategoryKind> {
243 self.as_icategory_kind(store).ok_or_else(|| {
244 GenApiError::invalid_node("the node doesn't implement `ICategory`".into())
245 })
246 }
247
248 pub fn as_iport_kind(self, store: &impl NodeStore) -> Option<IPortKind> {
249 IPortKind::maybe_from(self, store)
250 }
251
252 pub fn expect_iport_kind(self, store: &impl NodeStore) -> GenApiResult<IPortKind> {
253 self.as_iport_kind(store)
254 .ok_or_else(|| GenApiError::invalid_node("the node doesn't implement `IPort`".into()))
255 }
256
257 pub fn as_iselector_kind(self, store: &impl NodeStore) -> Option<ISelectorKind> {
258 ISelectorKind::maybe_from(self, store)
259 }
260
261 pub fn expect_iselector_kind(self, store: &impl NodeStore) -> GenApiResult<ISelectorKind> {
262 self.as_iselector_kind(store).ok_or_else(|| {
263 GenApiError::invalid_node("the node doesn't implement `ISelector`".into())
264 })
265 }
266
267 pub fn as_enum_entry(self, store: &impl NodeStore) -> Option<&EnumEntryNode> {
268 match store.node_opt(self)? {
269 NodeData::EnumEntry(n) => Some(n),
270 _ => None,
271 }
272 }
273
274 pub fn expect_enum_entry(self, store: &impl NodeStore) -> GenApiResult<&EnumEntryNode> {
275 self.as_enum_entry(store)
276 .ok_or_else(|| GenApiError::invalid_node("the node doesn't `EnumEntryNode`".into()))
277 }
278}
279
280impl NodeData {
281 #[allow(clippy::missing_panics_doc)]
282 #[must_use]
283 pub fn node_base(&self) -> NodeBase<'_> {
284 match self {
285 Self::Node(node) => node.node_base(),
286 Self::Category(node) => node.node_base(),
287 Self::Integer(node) => node.node_base(),
288 Self::IntReg(node) => node.node_base(),
289 Self::MaskedIntReg(node) => node.node_base(),
290 Self::Boolean(node) => node.node_base(),
291 Self::Command(node) => node.node_base(),
292 Self::Enumeration(node) => node.node_base(),
293 Self::Float(node) => node.node_base(),
294 Self::FloatReg(node) => node.node_base(),
295 Self::String(node) => node.node_base(),
296 Self::StringReg(node) => node.node_base(),
297 Self::Register(node) => node.node_base(),
298 Self::Converter(node) => node.node_base(),
299 Self::IntConverter(node) => node.node_base(),
300 Self::SwissKnife(node) => node.node_base(),
301 Self::IntSwissKnife(node) => node.node_base(),
302 Self::Port(node) => node.node_base(),
303 _ => todo!(),
304 }
305 }
306}
307
308#[derive(Debug)]
309pub struct DefaultNodeStore {
310 pub(super) interner: StringInterner<DefaultBackend<NodeId>>,
311 pub(super) store: Vec<Option<NodeData>>,
312
313 fresh_id: u32,
314}
315
316impl DefaultNodeStore {
317 #[must_use]
318 pub fn new() -> Self {
319 Self {
320 interner: StringInterner::new(),
321 store: Vec::new(),
322 fresh_id: 0,
323 }
324 }
325}
326
327impl NodeStore for DefaultNodeStore {
328 fn name_by_id(&self, nid: NodeId) -> Option<&str> {
329 self.interner.resolve(nid)
330 }
331
332 fn id_by_name<T>(&self, s: T) -> Option<NodeId>
333 where
334 T: AsRef<str>,
335 {
336 self.interner.get(s)
337 }
338
339 fn node_opt(&self, nid: NodeId) -> Option<&NodeData> {
340 self.store.get(nid.to_usize())?.as_ref()
341 }
342
343 fn visit_nodes<F>(&self, mut f: F)
344 where
345 F: FnMut(&NodeData),
346 {
347 for data in self.store.iter().flatten() {
348 f(data);
349 }
350 }
351}
352
353impl builder::NodeStoreBuilder for DefaultNodeStore {
354 type Store = Self;
355
356 fn build(self) -> Self {
357 self
358 }
359
360 fn get_or_intern<T>(&mut self, s: T) -> NodeId
361 where
362 T: AsRef<str>,
363 {
364 self.interner.get_or_intern(s)
365 }
366
367 fn store_node(&mut self, nid: NodeId, data: NodeData) {
368 let id = nid.to_usize();
369 if self.store.len() <= id {
370 self.store.resize(id + 1, None)
371 }
372 debug_assert!(self.store[id].is_none());
373 self.store[id] = Some(data);
374 }
375
376 fn fresh_id(&mut self) -> u32 {
377 let id = self.fresh_id;
378 self.fresh_id += 1;
379 id
380 }
381}
382
383impl Default for DefaultNodeStore {
384 fn default() -> Self {
385 Self::new()
386 }
387}
388
389#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
390pub struct ValueId(u32);
391
392impl ValueId {
393 #[must_use]
394 pub fn from_u32(i: u32) -> Self {
395 Self(i)
396 }
397}
398
399macro_rules! declare_value_id {
400 ($name:ident) => {
401 #[derive(Debug, Clone, Copy, PartialEq, Eq)]
402 pub struct $name(u32);
403
404 impl From<$name> for ValueId {
405 fn from(v: $name) -> ValueId {
406 ValueId(v.0)
407 }
408 }
409
410 impl From<ValueId> for $name {
411 fn from(vid: ValueId) -> Self {
412 Self(vid.0)
413 }
414 }
415 };
416}
417declare_value_id!(IntegerId);
418declare_value_id!(FloatId);
419declare_value_id!(StringId);
420
421#[derive(Debug, Clone, PartialEq)]
422pub enum ValueData {
423 Integer(i64),
424 Float(f64),
425 Str(String),
426 Boolean(bool),
427}
428
429macro_rules! impl_value_data_conversion {
430 ($ty:ty, $ctor:expr) => {
431 impl From<$ty> for ValueData {
432 fn from(v: $ty) -> Self {
433 $ctor(v)
434 }
435 }
436 };
437}
438impl_value_data_conversion!(i64, Self::Integer);
439impl_value_data_conversion!(f64, Self::Float);
440impl_value_data_conversion!(String, Self::Str);
441impl_value_data_conversion!(bool, Self::Boolean);
442
443#[derive(Debug, Default)]
444pub struct DefaultValueStore(Vec<ValueData>);
445
446impl DefaultValueStore {
447 #[must_use]
448 pub fn new() -> Self {
449 Self::default()
450 }
451}
452
453impl builder::ValueStoreBuilder for DefaultValueStore {
454 type Store = Self;
455
456 fn build(self) -> Self {
457 self
458 }
459
460 fn store<T, U>(&mut self, data: T) -> U
461 where
462 T: Into<ValueData>,
463 U: From<ValueId>,
464 {
465 let id = u32::try_from(self.0.len())
466 .expect("the number of value stored in `ValueStore` must not exceed u32::MAX");
467 let id = ValueId(id);
468 self.0.push(data.into());
469 id.into()
470 }
471}
472
473impl ValueStore for DefaultValueStore {
474 fn value_opt<T>(&self, id: T) -> Option<&ValueData>
475 where
476 T: Into<ValueId>,
477 {
478 self.0.get(id.into().0 as usize)
479 }
480
481 fn update<T, U>(&mut self, id: T, value: U) -> Option<ValueData>
482 where
483 T: Into<ValueId>,
484 U: Into<ValueData>,
485 {
486 self.0
487 .get_mut(id.into().0 as usize)
488 .map(|old| std::mem::replace(old, value.into()))
489 }
490}
491
492#[derive(Debug, Default)]
493pub struct DefaultCacheStore {
494 store: HashMap<NodeId, HashMap<(i64, i64), Vec<u8>>>,
495 invalidators: HashMap<NodeId, Vec<NodeId>>,
496}
497
498impl DefaultCacheStore {
499 #[must_use]
500 pub fn new() -> Self {
501 Self::default()
502 }
503}
504
505impl builder::CacheStoreBuilder for DefaultCacheStore {
506 type Store = Self;
507
508 fn build(self) -> Self {
509 self
510 }
511
512 fn store_invalidator(&mut self, invalidator: NodeId, target: NodeId) {
513 let entry = self.invalidators.entry(invalidator).or_default();
514 entry.push(target)
515 }
516}
517
518impl CacheStore for DefaultCacheStore {
519 fn cache(&mut self, nid: NodeId, address: i64, length: i64, data: &[u8]) {
520 self.store
521 .entry(nid)
522 .and_modify(|level1| {
523 level1
524 .entry((address, length))
525 .and_modify(|level2| data.clone_into(level2))
526 .or_insert_with(|| data.to_owned());
527 })
528 .or_insert_with(|| {
529 let mut level1 = HashMap::new();
530 level1.insert((address, length), data.to_owned());
531 level1
532 });
533 }
534
535 fn get_cache(&self, nid: NodeId, address: i64, length: i64) -> Option<&[u8]> {
536 Some(self.store.get(&nid)?.get(&(address, length))?.as_ref())
537 }
538
539 fn invalidate_by(&mut self, nid: NodeId) {
540 if let Some(target_nodes) = self.invalidators.get(&nid) {
541 for nid in target_nodes {
542 if let Some(cache) = self.store.get_mut(nid) {
543 *cache = HashMap::new();
544 }
545 }
546 }
547 }
548
549 fn invalidate_of(&mut self, nid: NodeId) {
550 if let Some(cache) = self.store.get_mut(&nid) {
551 *cache = HashMap::new();
552 }
553 }
554
555 fn clear(&mut self) {
556 self.store.clear()
557 }
558}
559
560#[derive(Default, Copy, Clone, Debug)]
561pub struct CacheSink {
562 _priv: (),
563}
564
565impl CacheSink {
566 #[must_use]
567 pub fn new() -> Self {
568 Self::default()
569 }
570}
571
572impl builder::CacheStoreBuilder for CacheSink {
573 type Store = Self;
574
575 fn build(self) -> Self {
576 self
577 }
578
579 fn store_invalidator(&mut self, _: NodeId, _: NodeId) {}
581}
582
583impl CacheStore for CacheSink {
584 fn cache(&mut self, _: NodeId, _: i64, _: i64, _: &[u8]) {}
585
586 fn get_cache(&self, _: NodeId, _: i64, _: i64) -> Option<&[u8]> {
587 None
588 }
589
590 fn invalidate_by(&mut self, _: NodeId) {}
591
592 fn invalidate_of(&mut self, _: NodeId) {}
593
594 fn clear(&mut self) {}
595}