cameleon_genapi/
store.rs

1/* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
4
5use 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    // TODO: Implement DCAM specific ndoes.
49    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    /// Store invalidator and its target to be invalidated.
580    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}