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}