eva_common/
dobj.rs

1use crate::{value::Value, EResult, Error, OID};
2use std::{
3    borrow::Borrow,
4    collections::{BTreeMap, BTreeSet},
5    fmt,
6    io::Cursor,
7    ops::Deref,
8};
9
10use binrw::prelude::*;
11
12use serde::{Deserialize, Deserializer, Serialize};
13
14impl Borrow<str> for Name {
15    fn borrow(&self) -> &str {
16        &self.0
17    }
18}
19
20#[derive(Default, Serialize, Deserialize, Copy, Clone, Eq, PartialEq, Debug)]
21#[serde(rename_all = "lowercase")]
22pub enum Endianess {
23    Big,
24    #[default]
25    Little,
26}
27
28impl From<Endianess> for binrw::Endian {
29    #[inline]
30    fn from(e: Endianess) -> binrw::Endian {
31        match e {
32            Endianess::Big => binrw::Endian::Big,
33            Endianess::Little => binrw::Endian::Little,
34        }
35    }
36}
37
38#[derive(Deserialize, Serialize, Debug, Default, Clone)]
39#[serde(deny_unknown_fields)]
40pub struct ObjectMap {
41    #[serde(rename = "data_objects")]
42    pub objects: BTreeMap<Name, DataObject>,
43}
44
45fn parse_value_by_kind(
46    buf: &mut Cursor<&[u8]>,
47    kind: &Kind,
48    map: &BTreeMap<Name, DataObject>,
49    endianess: Endianess,
50) -> EResult<Value> {
51    let value = match kind {
52        Kind::Bool => {
53            let v = u8::read(buf).map_err(Error::invalid_data)?;
54            Value::Bool(v > 0)
55        }
56        Kind::U8 => {
57            let v = u8::read(buf).map_err(Error::invalid_data)?;
58            Value::U8(v)
59        }
60        Kind::I8 => {
61            let v = i8::read(buf).map_err(Error::invalid_data)?;
62            Value::I8(v)
63        }
64        Kind::U16 => {
65            let v = u16::read_options(buf, endianess.into(), ()).map_err(Error::invalid_data)?;
66            Value::U16(v)
67        }
68        Kind::I16 => {
69            let v = i16::read_options(buf, endianess.into(), ()).map_err(Error::invalid_data)?;
70            Value::I16(v)
71        }
72        Kind::U32 => {
73            let v = u32::read_options(buf, endianess.into(), ()).map_err(Error::invalid_data)?;
74            Value::U32(v)
75        }
76        Kind::I32 => {
77            let v = i32::read_options(buf, endianess.into(), ()).map_err(Error::invalid_data)?;
78            Value::I32(v)
79        }
80        Kind::U64 => {
81            let v = u64::read_options(buf, endianess.into(), ()).map_err(Error::invalid_data)?;
82            Value::U64(v)
83        }
84        Kind::I64 => {
85            let v = i64::read_options(buf, endianess.into(), ()).map_err(Error::invalid_data)?;
86            Value::I64(v)
87        }
88        Kind::F32 => {
89            let v = f32::read_options(buf, endianess.into(), ()).map_err(Error::invalid_data)?;
90            Value::F32(v)
91        }
92        Kind::F64 => {
93            let v = f64::read_options(buf, endianess.into(), ()).map_err(Error::invalid_data)?;
94            Value::F64(v)
95        }
96        Kind::Array(k, n) => {
97            let mut values = Vec::with_capacity(*k);
98            for _ in 0..*k {
99                let value = parse_value_by_kind(buf, n, map, endianess)?;
100                values.push(value);
101            }
102            Value::Seq(values)
103        }
104        Kind::DataObject(ref s) => {
105            if let Some(object) = map.get(s) {
106                let mut values = BTreeMap::new();
107                for field in &object.fields {
108                    let kind = &field.kind;
109                    let value = parse_value_by_kind(buf, kind, map, endianess)?;
110                    values.insert(Value::String(field.name.to_string()), value);
111                }
112                Value::Map(values)
113            } else {
114                return Err(Error::not_found(s));
115            }
116        }
117    };
118    Ok(value)
119}
120
121impl ObjectMap {
122    pub fn new() -> Self {
123        Self::default()
124    }
125    pub fn merge(&mut self, other: Self) {
126        for (k, v) in other.objects {
127            self.objects.insert(k, v);
128        }
129    }
130    pub fn extend(&mut self, objects: Vec<DataObject>) {
131        for object in objects {
132            self.objects.insert(object.name.clone(), object);
133        }
134    }
135    pub fn mapped_oids(&self, name: &Name) -> BTreeSet<OID> {
136        let mut oids = BTreeSet::new();
137        self.mapped_oids_recursive(name, &mut oids);
138        oids
139    }
140    pub fn mapped_oids_recursive(&self, name: &Name, oids: &mut BTreeSet<OID>) {
141        let Some(object) = self.objects.get(name) else {
142            return;
143        };
144        for field in &object.fields {
145            if let Some(ref oid) = field.oid {
146                oids.insert(oid.clone());
147            }
148            match field.kind {
149                Kind::Array(_, ref k) => {
150                    if let Kind::DataObject(ref s) = k.as_ref() {
151                        self.mapped_oids_recursive(s, oids);
152                    }
153                }
154                Kind::DataObject(ref s) => {
155                    self.mapped_oids_recursive(s, oids);
156                }
157                _ => {}
158            }
159        }
160    }
161    pub fn remove_bulk<B: Borrow<str> + Ord>(&mut self, names: &[B]) {
162        for name in names {
163            self.objects.remove(name.borrow());
164        }
165    }
166    pub fn validate(&self) -> EResult<()> {
167        let mut invalid_objects: BTreeSet<&Name> = <_>::default();
168        for v in self.objects.values() {
169            for field in &v.fields {
170                self.validate_kind(&field.kind, &mut invalid_objects);
171            }
172        }
173        if !invalid_objects.is_empty() {
174            let mut err = String::new();
175            for (s, i) in invalid_objects.into_iter().enumerate() {
176                if s > 0 {
177                    err.push_str(", ");
178                }
179                err.push_str(i);
180            }
181            return Err(Error::invalid_data(format!("objects not found: {}", err)));
182        }
183        Ok(())
184    }
185    pub fn parse_values(
186        &self,
187        object: &Name,
188        buf: &[u8],
189        endianess: Endianess,
190    ) -> EResult<BTreeMap<OID, Value>> {
191        let mut cursor = Cursor::new(buf);
192        let mut values = BTreeMap::new();
193        self.parse_values_recursive(&mut cursor, object, &self.objects, &mut values, endianess)?;
194        Ok(values)
195    }
196    fn parse_values_recursive(
197        &self,
198        buf: &mut Cursor<&[u8]>,
199        object: &Name,
200        map: &BTreeMap<Name, DataObject>,
201        values: &mut BTreeMap<OID, Value>,
202        endianess: Endianess,
203    ) -> EResult<()> {
204        let Some(object) = map.get(object) else {
205            return Err(Error::not_found(object));
206        };
207        for field in &object.fields {
208            let kind = &field.kind;
209            if let Some(ref oid) = field.oid {
210                let pos = buf.position();
211                let value = parse_value_by_kind(buf, kind, map, endianess)?;
212                values.insert(oid.clone(), value);
213                buf.set_position(pos);
214            }
215            match kind {
216                Kind::Array(n, ref k) => {
217                    if let Kind::DataObject(ref s) = k.as_ref() {
218                        for _ in 0..*n {
219                            self.parse_values_recursive(buf, s, map, values, endianess)?;
220                        }
221                    } else {
222                        buf.set_position(buf.position() + u64::try_from(self.kind_size(kind)?)?);
223                    }
224                    continue;
225                }
226                Kind::DataObject(ref s) => {
227                    self.parse_values_recursive(buf, s, map, values, endianess)?;
228                    continue;
229                }
230                _ => {
231                    buf.set_position(buf.position() + u64::try_from(self.kind_size(kind)?)?);
232                    continue;
233                }
234            }
235        }
236        Ok(())
237    }
238    pub fn size_of(&self, name: &Name) -> EResult<usize> {
239        let mut size = 0;
240        for field in &self
241            .objects
242            .get(name)
243            .ok_or_else(|| Error::invalid_data(format!("object not found: {}", name)))?
244            .fields
245        {
246            size += self.kind_size(&field.kind)?;
247        }
248        Ok(size)
249    }
250    fn kind_size(&self, kind: &Kind) -> EResult<usize> {
251        match kind {
252            Kind::Bool | Kind::I8 | Kind::U8 => Ok(1),
253            Kind::I16 | Kind::U16 => Ok(2),
254            Kind::I32 | Kind::U32 | Kind::F32 => Ok(4),
255            Kind::I64 | Kind::U64 | Kind::F64 => Ok(8),
256            Kind::Array(n, k) => {
257                let k_size = self.kind_size(k)?;
258                Ok(n * k_size)
259            }
260            Kind::DataObject(ref s) => self.size_of(s),
261        }
262    }
263    fn validate_kind<'a>(&self, kind: &'a Kind, invalid_objects: &mut BTreeSet<&'a Name>) {
264        match kind {
265            Kind::Array(_, ref k) => self.validate_kind(k, invalid_objects),
266            Kind::DataObject(ref s) => {
267                if !self.objects.contains_key(s) {
268                    invalid_objects.insert(s);
269                }
270            }
271            _ => {}
272        }
273    }
274}
275
276#[derive(Deserialize, Serialize, Debug, Clone)]
277#[serde(deny_unknown_fields)]
278pub struct DataObject {
279    #[serde(alias = "i")]
280    pub name: Name,
281    #[serde(default, alias = "f")]
282    pub fields: Vec<Field>,
283}
284
285#[derive(Deserialize, Serialize, Debug, Clone)]
286pub struct Field {
287    #[serde(alias = "i")]
288    pub name: Name,
289    #[serde(rename = "type", alias = "t")]
290    pub kind: Kind,
291    #[serde(skip_serializing_if = "Option::is_none")]
292    pub oid: Option<OID>,
293}
294
295#[derive(Debug, Ord, PartialEq, Eq, PartialOrd, Clone)]
296pub struct Name(String);
297
298impl Deref for Name {
299    type Target = str;
300
301    fn deref(&self) -> &Self::Target {
302        &self.0
303    }
304}
305
306fn is_valid_name(s: &str) -> bool {
307    s.chars()
308        .all(|c| c.is_alphanumeric() || c.is_numeric() || c == '_')
309}
310
311impl TryFrom<String> for Name {
312    type Error = Error;
313
314    fn try_from(s: String) -> Result<Self, Self::Error> {
315        if is_valid_name(&s) {
316            Ok(Name(s))
317        } else {
318            Err(Error::invalid_data(format!("invalid name: {}", s)))
319        }
320    }
321}
322
323impl TryFrom<&str> for Name {
324    type Error = Error;
325
326    fn try_from(s: &str) -> Result<Self, Self::Error> {
327        if is_valid_name(s) {
328            Ok(Name(s.to_owned()))
329        } else {
330            Err(Error::invalid_data(format!("invalid name: {}", s)))
331        }
332    }
333}
334
335impl From<Name> for String {
336    fn from(n: Name) -> String {
337        n.0
338    }
339}
340
341impl fmt::Display for Name {
342    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
343        write!(f, "{}", self.0)
344    }
345}
346
347impl<'de> Deserialize<'de> for Name {
348    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
349    where
350        D: Deserializer<'de>,
351    {
352        let s = String::deserialize(deserializer)?;
353        Name::try_from(s).map_err(serde::de::Error::custom)
354    }
355}
356
357impl Serialize for Name {
358    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
359    where
360        S: serde::Serializer,
361    {
362        self.0.serialize(serializer)
363    }
364}
365
366#[derive(Clone, Eq, PartialEq, Debug)]
367pub enum Kind {
368    Bool,
369    I8,
370    I16,
371    I32,
372    I64,
373    U8,
374    U16,
375    U32,
376    U64,
377    F32,
378    F64,
379    Array(usize, Box<Kind>),
380    DataObject(Name),
381}
382
383impl<'de> Deserialize<'de> for Kind {
384    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
385    where
386        D: Deserializer<'de>,
387    {
388        let s = String::deserialize(deserializer)?;
389        let mut sp = s.split(',');
390        let kind = sp.next().unwrap();
391        let maybe_array: Option<usize> = if let Some(n) = sp.next() {
392            let n = n.parse().map_err(serde::de::Error::custom)?;
393            Some(n)
394        } else {
395            None
396        };
397        if sp.next().is_some() {
398            return Err(serde::de::Error::custom("too many commas in type"));
399        }
400        let data_kind = match kind {
401            "bool" | "BOOL" | "BOOLEAN" => {
402                maybe_array.map_or_else(|| Kind::Bool, |n| Kind::Array(n, Box::new(Kind::Bool)))
403            }
404            "i8" | "SINT" => {
405                maybe_array.map_or_else(|| Kind::I8, |n| Kind::Array(n, Box::new(Kind::I8)))
406            }
407            "i16" | "INT" => {
408                maybe_array.map_or_else(|| Kind::I16, |n| Kind::Array(n, Box::new(Kind::I16)))
409            }
410            "i32" | "DINT" => {
411                maybe_array.map_or_else(|| Kind::I32, |n| Kind::Array(n, Box::new(Kind::I32)))
412            }
413            "i64" | "LINT" => {
414                maybe_array.map_or_else(|| Kind::I64, |n| Kind::Array(n, Box::new(Kind::I64)))
415            }
416            "u8" | "USINT" => {
417                maybe_array.map_or_else(|| Kind::U8, |n| Kind::Array(n, Box::new(Kind::U8)))
418            }
419            "u16" | "UINT" => {
420                maybe_array.map_or_else(|| Kind::U16, |n| Kind::Array(n, Box::new(Kind::U16)))
421            }
422            "u32" | "UDINT" => {
423                maybe_array.map_or_else(|| Kind::U32, |n| Kind::Array(n, Box::new(Kind::U32)))
424            }
425            "u64" | "ULINT" => {
426                maybe_array.map_or_else(|| Kind::U64, |n| Kind::Array(n, Box::new(Kind::U64)))
427            }
428            "f32" | "REAL" => {
429                maybe_array.map_or_else(|| Kind::F32, |n| Kind::Array(n, Box::new(Kind::F32)))
430            }
431            "f64" | "LREAL" => {
432                maybe_array.map_or_else(|| Kind::F64, |n| Kind::Array(n, Box::new(Kind::F64)))
433            }
434            v => {
435                let name: Name = Name::try_from(v).map_err(serde::de::Error::custom)?;
436                if let Some(n) = maybe_array {
437                    Kind::Array(n, Box::new(Kind::DataObject(name)))
438                } else {
439                    Kind::DataObject(name)
440                }
441            }
442        };
443        Ok(data_kind)
444    }
445}
446
447impl fmt::Display for Kind {
448    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
449        match self {
450            Kind::Bool => write!(f, "bool"),
451            Kind::I8 => write!(f, "i8"),
452            Kind::I16 => write!(f, "i16"),
453            Kind::I32 => write!(f, "i32"),
454            Kind::I64 => write!(f, "i64"),
455            Kind::U8 => write!(f, "u8"),
456            Kind::U16 => write!(f, "u16"),
457            Kind::U32 => write!(f, "u32"),
458            Kind::U64 => write!(f, "u64"),
459            Kind::F32 => write!(f, "f32"),
460            Kind::F64 => write!(f, "f64"),
461            Kind::Array(n, k) => write!(f, "{},{}", k, n),
462            Kind::DataObject(s) => write!(f, "{}", s),
463        }
464    }
465}
466
467impl Serialize for Kind {
468    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
469    where
470        S: serde::Serializer,
471    {
472        serializer.serialize_str(&self.to_string())
473    }
474}