zencan_common/
objects.rs

1//! Object Definitions
2//!
3
4/// A container for the address of a subobject
5#[derive(Clone, Copy, Debug, PartialEq)]
6pub struct ObjectId {
7    /// Object index
8    pub index: u16,
9    /// Sub index
10    pub sub: u8,
11}
12
13/// Object Code value
14///
15/// Defines the type of an object or sub object
16#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
17#[repr(u8)]
18pub enum ObjectCode {
19    /// An empty object
20    ///
21    /// Zencan does not support Null objects
22    Null = 0,
23    /// A large chunk of data
24    ///
25    /// Zencan does not support Domain Object; it only supports domain sub-objects.
26    Domain = 2,
27    /// Unused
28    DefType = 5,
29    /// Unused
30    DefStruct = 6,
31    /// An object which has a single sub object
32    #[default]
33    Var = 7,
34    /// An array of sub-objects all with the same data type
35    Array = 8,
36    /// A collection of sub-objects with varying types
37    Record = 9,
38}
39
40impl TryFrom<u8> for ObjectCode {
41    type Error = ();
42
43    fn try_from(value: u8) -> Result<Self, Self::Error> {
44        match value {
45            0 => Ok(ObjectCode::Null),
46            2 => Ok(ObjectCode::Domain),
47            5 => Ok(ObjectCode::DefType),
48            6 => Ok(ObjectCode::DefStruct),
49            7 => Ok(ObjectCode::Var),
50            8 => Ok(ObjectCode::Array),
51            9 => Ok(ObjectCode::Record),
52            _ => Err(()),
53        }
54    }
55}
56
57/// Access type enum
58#[derive(Copy, Clone, Debug, Default, PartialEq)]
59pub enum AccessType {
60    /// Read-only
61    #[default]
62    Ro,
63    /// Write-only
64    Wo,
65    /// Read-write
66    Rw,
67    /// Read-only, and also will never be changed, even internally by the device
68    Const,
69}
70
71impl AccessType {
72    /// Returns true if an object with this access type can be read
73    pub fn is_readable(&self) -> bool {
74        matches!(self, AccessType::Ro | AccessType::Rw | AccessType::Const)
75    }
76
77    /// Returns true if an object with this access type can be written
78    pub fn is_writable(&self) -> bool {
79        matches!(self, AccessType::Rw | AccessType::Wo)
80    }
81}
82
83/// Possible PDO mapping values for an object
84#[derive(Copy, Clone, Debug, Default, PartialEq)]
85pub enum PdoMapping {
86    /// Object cannot be mapped to PDOs
87    #[default]
88    None,
89    /// Object can be mapped to RPDOs only
90    Rpdo,
91    /// Object can be mapped to TPDOs only
92    Tpdo,
93    /// Object can be mapped to both RPDOs and TPDOs
94    Both,
95}
96
97/// Indicate the type of data stored in an object
98#[derive(Copy, Clone, Debug, Default, PartialEq)]
99#[repr(u16)]
100pub enum DataType {
101    /// A true false value, encoded as a single byte, with 0 for false and 1 for true
102    Boolean = 1,
103    #[default]
104    /// A signed 8-bit integer
105    Int8 = 2,
106    /// A signed 16-bit integer
107    Int16 = 3,
108    /// A signed 32-bit integer
109    Int32 = 4,
110    /// An unsigned 8-bit integer
111    UInt8 = 5,
112    /// An unsigned 16-bit integer
113    UInt16 = 6,
114    /// An unsigned 32-bit integer
115    UInt32 = 7,
116    /// A 32-bit floating point value
117    Real32 = 8,
118    /// An ASCII/utf-8 string
119    VisibleString = 9,
120    /// A byte string
121    OctetString = 0xa,
122    /// A unicode string
123    UnicodeString = 0xb,
124    /// Currently Unimplemented
125    TimeOfDay = 0xc,
126    /// Currently Unimplemented
127    TimeDifference = 0xd,
128    /// An arbitrary byte access type for e.g. data streams, or large chunks of
129    /// data. Size is typically not known at build time.
130    Domain = 0xf,
131    /// A contained for an unrecognized data type value
132    Other(u16),
133}
134
135impl From<u16> for DataType {
136    fn from(value: u16) -> Self {
137        use DataType::*;
138        match value {
139            1 => Boolean,
140            2 => Int8,
141            3 => Int16,
142            4 => Int32,
143            5 => UInt8,
144            6 => UInt16,
145            7 => UInt32,
146            8 => Real32,
147            9 => VisibleString,
148            0xa => OctetString,
149            0xb => UnicodeString,
150            0xf => Domain,
151            _ => Other(value),
152        }
153    }
154}
155
156impl DataType {
157    /// Returns true if data type is one of the string types
158    pub fn is_str(&self) -> bool {
159        matches!(
160            self,
161            Self::VisibleString | Self::OctetString | Self::UnicodeString
162        )
163    }
164}
165
166/// Information about a sub object
167#[derive(Clone, Copy, Debug, Default, PartialEq)]
168pub struct SubInfo {
169    /// The size (or max size) of this sub object, in bytes
170    pub size: usize,
171    /// The data type of this sub object
172    pub data_type: DataType,
173    /// Indicates what accesses (i.e. read/write) are allowed on this sub object
174    pub access_type: AccessType,
175    /// Indicates whether this sub may be mapped to PDOs
176    pub pdo_mapping: PdoMapping,
177    /// Indicates whether this sub should be persisted when data is saved
178    pub persist: bool,
179}
180
181impl SubInfo {
182    /// A shorthand value for sub0 on record and array objects
183    pub const MAX_SUB_NUMBER: SubInfo = SubInfo {
184        size: 1,
185        data_type: DataType::UInt8,
186        access_type: AccessType::Const,
187        pdo_mapping: PdoMapping::None,
188        persist: false,
189    };
190
191    /// Convenience function for creating a new sub-info by type
192    pub const fn new_u32() -> Self {
193        Self {
194            size: 4,
195            data_type: DataType::UInt32,
196            access_type: AccessType::Ro,
197            pdo_mapping: PdoMapping::None,
198            persist: false,
199        }
200    }
201
202    /// Convenience function for creating a new sub-info by type
203    pub const fn new_u16() -> Self {
204        Self {
205            size: 2,
206            data_type: DataType::UInt16,
207            access_type: AccessType::Ro,
208            pdo_mapping: PdoMapping::None,
209            persist: false,
210        }
211    }
212
213    /// Convenience function for creating a new sub-info by type
214    pub const fn new_u8() -> Self {
215        Self {
216            size: 1,
217            data_type: DataType::UInt8,
218            access_type: AccessType::Ro,
219            pdo_mapping: PdoMapping::None,
220            persist: false,
221        }
222    }
223
224    /// Convenience function for creating a new sub-info by type
225    pub const fn new_i32() -> Self {
226        Self {
227            size: 4,
228            data_type: DataType::Int32,
229            access_type: AccessType::Ro,
230            pdo_mapping: PdoMapping::None,
231            persist: false,
232        }
233    }
234
235    /// Convenience function for creating a new sub-info by type
236    pub const fn new_i16() -> Self {
237        Self {
238            size: 2,
239            data_type: DataType::Int16,
240            access_type: AccessType::Ro,
241            pdo_mapping: PdoMapping::None,
242            persist: false,
243        }
244    }
245
246    /// Convenience function for creating a new sub-info by type
247    pub const fn new_i8() -> Self {
248        Self {
249            size: 1,
250            data_type: DataType::Int8,
251            access_type: AccessType::Ro,
252            pdo_mapping: PdoMapping::None,
253            persist: false,
254        }
255    }
256
257    /// Convenience function for creating a new sub-info by type
258    pub const fn new_f32() -> Self {
259        Self {
260            size: 4,
261            data_type: DataType::Real32,
262            access_type: AccessType::Ro,
263            pdo_mapping: PdoMapping::None,
264            persist: false,
265        }
266    }
267
268    /// Convenience function for creating a new sub-info by type
269    pub const fn new_visibile_str(size: usize) -> Self {
270        Self {
271            size,
272            data_type: DataType::VisibleString,
273            access_type: AccessType::Ro,
274            pdo_mapping: PdoMapping::None,
275            persist: false,
276        }
277    }
278
279    /// Convenience function to set the access_type to read-only
280    pub const fn ro_access(mut self) -> Self {
281        self.access_type = AccessType::Ro;
282        self
283    }
284
285    /// Convenience function to set the access_type to read-write
286    pub const fn rw_access(mut self) -> Self {
287        self.access_type = AccessType::Rw;
288        self
289    }
290
291    /// Convenience function to set the access_type to const
292    pub const fn const_access(mut self) -> Self {
293        self.access_type = AccessType::Const;
294        self
295    }
296
297    /// Convenience function to set the access_type to write-only
298    pub const fn wo_access(mut self) -> Self {
299        self.access_type = AccessType::Wo;
300        self
301    }
302
303    /// Convenience function to set the persist value
304    pub const fn persist(mut self, value: bool) -> Self {
305        self.persist = value;
306        self
307    }
308}