cameleon_genapi/
lib.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
5#![allow(
6    clippy::module_name_repetitions,
7    clippy::similar_names,
8    clippy::missing_errors_doc,
9    clippy::missing_panics_doc,
10    clippy::option_if_let_else,
11    clippy::cast_sign_loss,
12    clippy::cast_possible_truncation
13)]
14
15pub mod builder;
16pub mod elem_type;
17pub mod formula;
18pub mod interface;
19pub mod parser;
20pub mod store;
21
22mod boolean;
23mod category;
24mod command;
25mod converter;
26mod enumeration;
27mod float;
28mod float_reg;
29mod int_converter;
30mod int_reg;
31mod int_swiss_knife;
32mod integer;
33mod ivalue;
34mod masked_int_reg;
35mod node;
36mod node_base;
37mod port;
38mod register;
39mod register_base;
40mod register_description;
41mod string;
42mod string_reg;
43mod swiss_knife;
44mod utils;
45
46pub use boolean::BooleanNode;
47pub use category::CategoryNode;
48pub use command::CommandNode;
49pub use converter::ConverterNode;
50pub use enumeration::{EnumEntryNode, EnumerationNode};
51pub use float::FloatNode;
52pub use float_reg::FloatRegNode;
53pub use int_converter::IntConverterNode;
54pub use int_reg::IntRegNode;
55pub use int_swiss_knife::IntSwissKnifeNode;
56pub use integer::IntegerNode;
57pub use masked_int_reg::MaskedIntRegNode;
58pub use node::Node;
59pub use node_base::NodeBase;
60pub use port::PortNode;
61pub use register::RegisterNode;
62pub use register_base::RegisterBase;
63pub use register_description::RegisterDescription;
64pub use store::{CacheStore, NodeId, NodeStore, ValueStore};
65pub use string::StringNode;
66pub use string_reg::StringRegNode;
67pub use swiss_knife::SwissKnifeNode;
68
69use std::borrow::Cow;
70
71use auto_impl::auto_impl;
72use tracing::error;
73
74pub mod prelude {
75    pub use super::interface::{
76        IBoolean, ICategory, ICommand, IEnumeration, IFloat, IInteger, INode, IPort, IRegister,
77        ISelector, IString,
78    };
79}
80
81#[auto_impl(&mut, Box)]
82pub trait Device {
83    fn read_mem(
84        &mut self,
85        address: i64,
86        buf: &mut [u8],
87    ) -> Result<(), Box<dyn std::error::Error + Send + Sync>>;
88
89    fn write_mem(
90        &mut self,
91        address: i64,
92        data: &[u8],
93    ) -> Result<(), Box<dyn std::error::Error + Send + Sync>>;
94}
95
96#[derive(Debug, thiserror::Error)]
97pub enum GenApiError {
98    #[error("device I/O error: {0}")]
99    Device(Box<dyn std::error::Error + Send + Sync>),
100
101    /// The node is not writable.
102    #[error("attempt to write a value to non writable node")]
103    NotWritable,
104
105    /// Invalid node.
106    #[error("invalid node: {0}")]
107    InvalidNode(Cow<'static, str>),
108
109    /// Try to write invalid value to the node.
110    ///
111    /// e.g. try to write the value that exceeds the max value of the node.
112    #[error("invalid data: {0}")]
113    InvalidData(Cow<'static, str>),
114
115    /// Operation on the node failed due to the lack of chunk data where it's required to complete the operation.
116    #[error("chunk data missing")]
117    ChunkDataMissing,
118
119    /// Invalid buffer.
120    #[error("invalid buffer: {0}")]
121    InvalidBuffer(Cow<'static, str>),
122}
123
124impl GenApiError {
125    fn device(inner: Box<dyn std::error::Error + Send + Sync>) -> Self {
126        let err = GenApiError::Device(inner);
127        error!("{}", err);
128        err
129    }
130
131    fn not_writable() -> Self {
132        let err = GenApiError::NotWritable;
133        error!("{}", err);
134        err
135    }
136
137    fn invalid_node(inner: Cow<'static, str>) -> Self {
138        let err = GenApiError::InvalidNode(inner);
139        error!("{}", err);
140        err
141    }
142
143    fn invalid_data(inner: Cow<'static, str>) -> Self {
144        let err = GenApiError::InvalidData(inner);
145        error!("{}", err);
146        err
147    }
148
149    fn chunk_data_missing() -> Self {
150        let err = GenApiError::ChunkDataMissing;
151        error!("{}", err);
152        err
153    }
154
155    fn invalid_buffer(inner: Cow<'static, str>) -> Self {
156        let err = GenApiError::InvalidBuffer(inner);
157        error!("{}", err);
158        err
159    }
160}
161
162pub type GenApiResult<T> = std::result::Result<T, GenApiError>;
163
164#[derive(Clone, Debug)]
165pub struct ValueCtxt<T, U> {
166    pub value_store: T,
167    pub cache_store: U,
168}
169
170impl<T, U> ValueCtxt<T, U> {
171    pub fn new(value_store: T, cache_store: U) -> Self {
172        Self {
173            value_store,
174            cache_store,
175        }
176    }
177
178    pub fn value_store(&self) -> &T {
179        &self.value_store
180    }
181
182    pub fn value_store_mut(&mut self) -> &mut T {
183        &mut self.value_store
184    }
185
186    pub fn cache_store(&mut self) -> &U
187    where
188        T: store::ValueStore,
189        U: store::CacheStore,
190    {
191        &self.cache_store
192    }
193
194    pub fn cache_store_mut(&mut self) -> &mut U {
195        &mut self.cache_store
196    }
197
198    pub fn cache_data(&mut self, nid: store::NodeId, address: i64, length: i64, value: &[u8])
199    where
200        U: store::CacheStore,
201    {
202        self.cache_store.cache(nid, address, length, value);
203    }
204
205    pub fn get_cache(&self, nid: store::NodeId, address: i64, length: i64) -> Option<&[u8]>
206    where
207        U: store::CacheStore,
208    {
209        self.cache_store.get_cache(nid, address, length)
210    }
211
212    pub fn invalidate_cache_by(&mut self, nid: store::NodeId)
213    where
214        U: store::CacheStore,
215    {
216        self.cache_store.invalidate_by(nid)
217    }
218
219    pub fn invalidate_cache_of(&mut self, nid: store::NodeId)
220    where
221        U: store::CacheStore,
222    {
223        self.cache_store.invalidate_of(nid)
224    }
225
226    pub fn clear_cache(&mut self)
227    where
228        U: store::CacheStore,
229    {
230        self.cache_store.clear()
231    }
232}