tango_client/
serde.rs

1//! This module implements the serde `Serialize` and `Deserialize` traits for
2//! the Tango data types `CommandData`, `AttrValue` and `PropertyValue`.
3//!
4//! This means that you can easily deserialize the values from any storage
5//! format, e.g. JSON or TOML.
6//!
7//! However, there is a caveat: Most storage formats do not offer details such
8//! as differently sized integer types, or empty arrays of different types.
9//! This means that the deserializer cannot know if an empty array is meant to
10//! be a `LongArray` or a `StringArray`, for example.  Tango, however, wants
11//! its command arguments and attribute values to be of the exact type that the
12//! API specifies and does not make implicit conversions.
13//!
14//! As a workaround, all of the three types provide a `convert` method, which
15//! takes a [`TangoDataType`](crate::TangoDataType) to try to convert to.  This
16//! type can be directly taken from the [`CommandInfo`](crate::CommandInfo) or
17//! [`AttributeInfo`](crate::AttributeInfo) for the command/attribute.
18//!
19//! The `convert` method will convert integral types into each other and into
20//! floats, as well any empty array to any other type of array, and integral
21//! arrays into arrays of other integral or floating types.
22
23use std::fmt;
24use serde::{ser, de};
25use serde::de::{Visitor, Error as _};
26use serde::ser::{Serialize, SerializeSeq};
27
28use crate::{CommandData, AttrValue, PropertyValue};
29
30impl<'de> de::Deserialize<'de> for CommandData {
31    #[inline]
32    fn deserialize<D: de::Deserializer<'de>>(deser: D) -> Result<CommandData, D::Error> {
33        struct ValueVisitor;
34
35        impl<'de> Visitor<'de> for ValueVisitor {
36            type Value = CommandData;
37
38            #[inline]
39            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
40                formatter.write_str("a CommandData value")
41            }
42
43            #[inline]
44            fn visit_bool<E>(self, value: bool) -> Result<CommandData, E> {
45                Ok(CommandData::Boolean(value))
46            }
47
48            #[inline]
49            fn visit_i16<E>(self, value: i16) -> Result<CommandData, E> {
50                Ok(CommandData::Short(value))
51            }
52
53            #[inline]
54            fn visit_i32<E>(self, value: i32) -> Result<CommandData, E> {
55                Ok(CommandData::Long(value))
56            }
57
58            #[inline]
59            fn visit_i64<E>(self, value: i64) -> Result<CommandData, E> {
60                Ok(CommandData::Long64(value))
61            }
62
63            #[inline]
64            fn visit_u16<E>(self, value: u16) -> Result<CommandData, E> {
65                Ok(CommandData::UShort(value))
66            }
67
68            #[inline]
69            fn visit_u32<E>(self, value: u32) -> Result<CommandData, E> {
70                Ok(CommandData::ULong(value))
71            }
72
73            #[inline]
74            fn visit_u64<E>(self, value: u64) -> Result<CommandData, E> {
75                Ok(CommandData::ULong64(value))
76            }
77
78            #[inline]
79            fn visit_f32<E>(self, value: f32) -> Result<CommandData, E> {
80                Ok(CommandData::Float(value))
81            }
82
83            #[inline]
84            fn visit_f64<E>(self, value: f64) -> Result<CommandData, E> {
85                Ok(CommandData::Double(value))
86            }
87
88            #[inline]
89            fn visit_str<E: de::Error>(self, value: &str) -> Result<CommandData, E> {
90                Ok(CommandData::String(value.as_bytes().to_vec()))
91            }
92
93            #[inline]
94            fn visit_string<E>(self, value: String) -> Result<CommandData, E> {
95                Ok(CommandData::String(value.into_bytes()))
96            }
97
98            #[inline]
99            fn visit_bytes<E: de::Error>(self, value: &[u8]) -> Result<CommandData, E> {
100                Ok(CommandData::CharArray(value.to_vec()))
101            }
102
103            #[inline]
104            fn visit_byte_buf<E: de::Error>(self, value: Vec<u8>) -> Result<CommandData, E> {
105                Ok(CommandData::CharArray(value))
106            }
107
108            #[inline]
109            fn visit_none<E>(self) -> Result<CommandData, E> {
110                Ok(CommandData::Void)
111            }
112
113            #[inline]
114            fn visit_some<D: de::Deserializer<'de>>(self, deser: D) -> Result<CommandData, D::Error> {
115                de::Deserialize::deserialize(deser)
116            }
117
118            #[inline]
119            fn visit_unit<E>(self) -> Result<CommandData, E> {
120                Ok(CommandData::Void)
121            }
122
123            #[inline]
124            fn visit_seq<V: de::SeqAccess<'de>>(self, mut visitor: V) -> Result<CommandData, V::Error> {
125
126                macro_rules! get_array {
127                    ($v:ident, $alt:ident, $arralt:ident) => {
128                        {
129                            let mut values = Vec::new();
130                            values.push($v);
131                            while let Some(el) = visitor.next_element()? {
132                                match el {
133                                    CommandData::$alt(v) => values.push(v),
134                                    _ => Err(V::Error::custom("array elements must have same type"))?,
135                                }
136                            }
137                            Ok(CommandData::$arralt(values))
138                        }
139                    }
140                }
141
142                match visitor.next_element()? {
143                    // For an empty list, we can't decide which type is meant.
144                    // Conversion methods must be used to get a desired type.
145                    None => Ok(CommandData::DoubleArray(vec![])),
146                    Some(val) => match val {
147                        CommandData::Boolean(v) => get_array!(v, Boolean, BooleanArray),
148                        CommandData::Short(v) => get_array!(v, Short, ShortArray),
149                        CommandData::Long(v) => get_array!(v, Long, LongArray),
150                        CommandData::Long64(v) => get_array!(v, Long64, Long64Array),
151                        CommandData::UShort(v) => get_array!(v, UShort, UShortArray),
152                        CommandData::ULong(v) => get_array!(v, ULong, ULongArray),
153                        CommandData::ULong64(v) => get_array!(v, ULong64, ULong64Array),
154                        CommandData::Float(v) => get_array!(v, Float, FloatArray),
155                        CommandData::Double(v) => get_array!(v, Double, DoubleArray),
156                        // TODO: Encoded is String/Vec<u8>
157                        CommandData::String(v) => get_array!(v, String, StringArray),
158                        CommandData::LongArray(v) => match (visitor.next_element()?,
159                                                            visitor.next_element()?) {
160                            (Some(CommandData::StringArray(w)), None::<CommandData>) =>
161                                Ok(CommandData::LongStringArray(v, w)),
162                            _ => Err(V::Error::custom("invalid type inside array")),
163                        }
164                        CommandData::DoubleArray(v) => match (visitor.next_element()?,
165                                                              visitor.next_element()?) {
166                            (Some(CommandData::StringArray(w)), None::<CommandData>) =>
167                                Ok(CommandData::DoubleStringArray(v, w)),
168                            _ => Err(V::Error::custom("invalid type inside array")),
169                        }
170                        _ => Err(V::Error::custom("invalid type inside array")),
171                    }
172                }
173            }
174        }
175
176        deser.deserialize_any(ValueVisitor)
177    }
178}
179
180impl<'de> de::Deserialize<'de> for AttrValue {
181    #[inline]
182    fn deserialize<D: de::Deserializer<'de>>(deser: D) -> Result<AttrValue, D::Error> {
183        struct ValueVisitor;
184
185        impl<'de> Visitor<'de> for ValueVisitor {
186            type Value = AttrValue;
187
188            #[inline]
189            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
190                formatter.write_str("a AttrValue value")
191            }
192
193            #[inline]
194            fn visit_bool<E>(self, value: bool) -> Result<AttrValue, E> {
195                Ok(AttrValue::Boolean(value))
196            }
197
198            #[inline]
199            fn visit_i16<E>(self, value: i16) -> Result<AttrValue, E> {
200                Ok(AttrValue::Short(value))
201            }
202
203            #[inline]
204            fn visit_i32<E>(self, value: i32) -> Result<AttrValue, E> {
205                Ok(AttrValue::Long(value))
206            }
207
208            #[inline]
209            fn visit_i64<E>(self, value: i64) -> Result<AttrValue, E> {
210                Ok(AttrValue::Long64(value))
211            }
212
213            #[inline]
214            fn visit_u16<E>(self, value: u16) -> Result<AttrValue, E> {
215                Ok(AttrValue::UShort(value))
216            }
217
218            #[inline]
219            fn visit_u32<E>(self, value: u32) -> Result<AttrValue, E> {
220                Ok(AttrValue::ULong(value))
221            }
222
223            #[inline]
224            fn visit_u64<E>(self, value: u64) -> Result<AttrValue, E> {
225                Ok(AttrValue::ULong64(value))
226            }
227
228            #[inline]
229            fn visit_f32<E>(self, value: f32) -> Result<AttrValue, E> {
230                Ok(AttrValue::Float(value))
231            }
232
233            #[inline]
234            fn visit_f64<E>(self, value: f64) -> Result<AttrValue, E> {
235                Ok(AttrValue::Double(value))
236            }
237
238            #[inline]
239            fn visit_str<E: de::Error>(self, value: &str) -> Result<AttrValue, E> {
240                Ok(AttrValue::String(value.as_bytes().to_vec()))
241            }
242
243            #[inline]
244            fn visit_string<E>(self, value: String) -> Result<AttrValue, E> {
245                Ok(AttrValue::String(value.into_bytes()))
246            }
247
248            #[inline]
249            fn visit_bytes<E: de::Error>(self, value: &[u8]) -> Result<AttrValue, E> {
250                Ok(AttrValue::UCharArray(value.to_vec()))
251            }
252
253            #[inline]
254            fn visit_byte_buf<E: de::Error>(self, value: Vec<u8>) -> Result<AttrValue, E> {
255                Ok(AttrValue::UCharArray(value))
256            }
257
258            #[inline]
259            fn visit_some<D: de::Deserializer<'de>>(self, deser: D) -> Result<AttrValue, D::Error> {
260                de::Deserialize::deserialize(deser)
261            }
262
263            #[inline]
264            fn visit_seq<V: de::SeqAccess<'de>>(self, mut visitor: V) -> Result<AttrValue, V::Error> {
265
266                macro_rules! get_array {
267                    ($v:ident, $alt:ident, $arralt:ident) => {
268                        {
269                            let mut values = Vec::new();
270                            values.push($v);
271                            while let Some(el) = visitor.next_element()? {
272                                match el {
273                                    AttrValue::$alt(v) => values.push(v),
274                                    _ => Err(V::Error::custom("array elements must have same type"))?,
275                                }
276                            }
277                            Ok(AttrValue::$arralt(values))
278                        }
279                    }
280                }
281
282                match visitor.next_element()? {
283                    // For an empty list, we can't decide which type is meant.
284                    // Conversion methods must be used to get a desired type.
285                    None => Ok(AttrValue::DoubleArray(vec![])),
286                    Some(val) => match val {
287                        AttrValue::Boolean(v) => get_array!(v, Boolean, BooleanArray),
288                        AttrValue::Short(v) => get_array!(v, Short, ShortArray),
289                        AttrValue::Long(v) => get_array!(v, Long, LongArray),
290                        AttrValue::Long64(v) => get_array!(v, Long64, Long64Array),
291                        AttrValue::UShort(v) => get_array!(v, UShort, UShortArray),
292                        AttrValue::ULong(v) => get_array!(v, ULong, ULongArray),
293                        AttrValue::ULong64(v) => get_array!(v, ULong64, ULong64Array),
294                        AttrValue::Float(v) => get_array!(v, Float, FloatArray),
295                        AttrValue::Double(v) => get_array!(v, Double, DoubleArray),
296                        AttrValue::String(v) => get_array!(v, String, StringArray),
297                        _ => Err(V::Error::custom("invalid type inside array")),
298                    }
299                }
300            }
301        }
302
303        deser.deserialize_any(ValueVisitor)
304    }
305}
306
307impl<'de> de::Deserialize<'de> for PropertyValue {
308    #[inline]
309    fn deserialize<D: de::Deserializer<'de>>(deser: D) -> Result<PropertyValue, D::Error> {
310        struct ValueVisitor;
311
312        impl<'de> Visitor<'de> for ValueVisitor {
313            type Value = PropertyValue;
314
315            #[inline]
316            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
317                formatter.write_str("a PropertyValue value")
318            }
319
320            #[inline]
321            fn visit_bool<E>(self, value: bool) -> Result<PropertyValue, E> {
322                Ok(PropertyValue::Boolean(value))
323            }
324
325            #[inline]
326            fn visit_i16<E>(self, value: i16) -> Result<PropertyValue, E> {
327                Ok(PropertyValue::Short(value))
328            }
329
330            #[inline]
331            fn visit_i32<E>(self, value: i32) -> Result<PropertyValue, E> {
332                Ok(PropertyValue::Long(value))
333            }
334
335            #[inline]
336            fn visit_i64<E>(self, value: i64) -> Result<PropertyValue, E> {
337                Ok(PropertyValue::Long64(value))
338            }
339
340            #[inline]
341            fn visit_u16<E>(self, value: u16) -> Result<PropertyValue, E> {
342                Ok(PropertyValue::UShort(value))
343            }
344
345            #[inline]
346            fn visit_u32<E>(self, value: u32) -> Result<PropertyValue, E> {
347                Ok(PropertyValue::ULong(value))
348            }
349
350            #[inline]
351            fn visit_u64<E>(self, value: u64) -> Result<PropertyValue, E> {
352                Ok(PropertyValue::ULong64(value))
353            }
354
355            #[inline]
356            fn visit_f32<E>(self, value: f32) -> Result<PropertyValue, E> {
357                Ok(PropertyValue::Float(value))
358            }
359
360            #[inline]
361            fn visit_f64<E>(self, value: f64) -> Result<PropertyValue, E> {
362                Ok(PropertyValue::Double(value))
363            }
364
365            #[inline]
366            fn visit_str<E: de::Error>(self, value: &str) -> Result<PropertyValue, E> {
367                Ok(PropertyValue::String(value.as_bytes().to_vec()))
368            }
369
370            #[inline]
371            fn visit_string<E>(self, value: String) -> Result<PropertyValue, E> {
372                Ok(PropertyValue::String(value.into_bytes()))
373            }
374
375            #[inline]
376            fn visit_some<D: de::Deserializer<'de>>(self, deser: D) -> Result<PropertyValue, D::Error> {
377                de::Deserialize::deserialize(deser)
378            }
379
380            #[inline]
381            fn visit_seq<V: de::SeqAccess<'de>>(self, mut visitor: V) -> Result<PropertyValue, V::Error> {
382
383                macro_rules! get_array {
384                    ($v:ident, $alt:ident, $arralt:ident) => {
385                        {
386                            let mut values = Vec::new();
387                            values.push($v);
388                            while let Some(el) = visitor.next_element()? {
389                                match el {
390                                    PropertyValue::$alt(v) => values.push(v),
391                                    _ => Err(V::Error::custom("array elements must have same type"))?,
392                                }
393                            }
394                            Ok(PropertyValue::$arralt(values))
395                        }
396                    }
397                }
398
399                match visitor.next_element()? {
400                    // For an empty list, we can't decide which type is meant.
401                    // Conversion methods must be used to get a desired type.
402                    None => Ok(PropertyValue::DoubleArray(vec![])),
403                    Some(val) => match val {
404                        PropertyValue::Short(v) => get_array!(v, Short, ShortArray),
405                        PropertyValue::Long(v) => get_array!(v, Long, LongArray),
406                        PropertyValue::Long64(v) => get_array!(v, Long64, Long64Array),
407                        PropertyValue::UShort(v) => get_array!(v, UShort, UShortArray),
408                        PropertyValue::ULong(v) => get_array!(v, ULong, ULongArray),
409                        PropertyValue::ULong64(v) => get_array!(v, ULong64, ULong64Array),
410                        PropertyValue::Float(v) => get_array!(v, Float, FloatArray),
411                        PropertyValue::Double(v) => get_array!(v, Double, DoubleArray),
412                        PropertyValue::String(v) => get_array!(v, String, StringArray),
413                        _ => Err(V::Error::custom("invalid type inside array")),
414                    }
415                }
416            }
417        }
418
419        deser.deserialize_any(ValueVisitor)
420    }
421}
422
423
424struct StringSeq<'a>(&'a Vec<Vec<u8>>);
425
426impl<'a> Serialize for StringSeq<'a> {
427    fn serialize<S: ser::Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
428        let mut seq = s.serialize_seq(Some(self.0.len()))?;
429        for el in self.0 {
430            match std::str::from_utf8(el) {
431                Ok(vs) => seq.serialize_element(vs),
432                Err(_) => seq.serialize_element(el)
433            }?;
434        }
435        seq.end()
436    }
437}
438
439impl Serialize for CommandData {
440    fn serialize<S: ser::Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
441        match self {
442            CommandData::Void => s.serialize_unit(),
443            CommandData::Boolean(v) => s.serialize_bool(*v),
444            CommandData::Short(v) => s.serialize_i16(*v),
445            CommandData::Long(v) => s.serialize_i32(*v),
446            CommandData::Long64(v) => s.serialize_i64(*v),
447            CommandData::UShort(v) => s.serialize_u16(*v),
448            CommandData::ULong(v) => s.serialize_u32(*v),
449            CommandData::ULong64(v) => s.serialize_u64(*v),
450            CommandData::Float(v) => s.serialize_f32(*v),
451            CommandData::Double(v) => s.serialize_f64(*v),
452            CommandData::String(v) => match std::str::from_utf8(v) {
453                Ok(vs) => s.serialize_str(vs),
454                Err(_) => s.serialize_bytes(v)
455            },
456            CommandData::State(v) => s.serialize_str(&v.to_string()),
457            CommandData::Encoded(v) => v.serialize(s),
458            CommandData::BooleanArray(v) => s.collect_seq(v),
459            CommandData::CharArray(v) => s.collect_seq(v),
460            CommandData::ShortArray(v) => s.collect_seq(v),
461            CommandData::LongArray(v) => s.collect_seq(v),
462            CommandData::Long64Array(v) => s.collect_seq(v),
463            CommandData::UShortArray(v) => s.collect_seq(v),
464            CommandData::ULongArray(v) => s.collect_seq(v),
465            CommandData::ULong64Array(v) => s.collect_seq(v),
466            CommandData::FloatArray(v) => s.collect_seq(v),
467            CommandData::DoubleArray(v) => s.collect_seq(v),
468            CommandData::StringArray(v) => StringSeq(v).serialize(s),
469            CommandData::LongStringArray(v, w) => {
470                let mut seq = s.serialize_seq(Some(2))?;
471                seq.serialize_element(v)?;
472                seq.serialize_element(&StringSeq(w))?;
473                seq.end()
474            }
475            CommandData::DoubleStringArray(v, w) => {
476                let mut seq = s.serialize_seq(Some(2))?;
477                seq.serialize_element(v)?;
478                seq.serialize_element(&StringSeq(w))?;
479                seq.end()
480            }
481        }
482    }
483}
484
485impl Serialize for AttrValue {
486    fn serialize<S: ser::Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
487        match self {
488            AttrValue::Boolean(v) => s.serialize_bool(*v),
489            AttrValue::Short(v) => s.serialize_i16(*v),
490            AttrValue::Long(v) => s.serialize_i32(*v),
491            AttrValue::Long64(v) => s.serialize_i64(*v),
492            AttrValue::UChar(v) => s.serialize_u8(*v),
493            AttrValue::UShort(v) => s.serialize_u16(*v),
494            AttrValue::ULong(v) => s.serialize_u32(*v),
495            AttrValue::ULong64(v) => s.serialize_u64(*v),
496            AttrValue::Float(v) => s.serialize_f32(*v),
497            AttrValue::Double(v) => s.serialize_f64(*v),
498            AttrValue::String(v) => match std::str::from_utf8(v) {
499                Ok(vs) => s.serialize_str(vs),
500                Err(_) => s.serialize_bytes(v)
501            },
502            AttrValue::State(v) => s.serialize_str(&v.to_string()),
503            AttrValue::Encoded(v) => v.serialize(s),
504            AttrValue::BooleanArray(v) => s.collect_seq(v),
505            AttrValue::ShortArray(v) => s.collect_seq(v),
506            AttrValue::LongArray(v) => s.collect_seq(v),
507            AttrValue::Long64Array(v) => s.collect_seq(v),
508            AttrValue::UCharArray(v) => s.collect_seq(v),
509            AttrValue::UShortArray(v) => s.collect_seq(v),
510            AttrValue::ULongArray(v) => s.collect_seq(v),
511            AttrValue::ULong64Array(v) => s.collect_seq(v),
512            AttrValue::FloatArray(v) => s.collect_seq(v),
513            AttrValue::DoubleArray(v) => s.collect_seq(v),
514            AttrValue::StringArray(v) => StringSeq(v).serialize(s),
515            AttrValue::StateArray(v) => s.collect_seq(v.iter().map(ToString::to_string)),
516            AttrValue::EncodedArray(v) => s.collect_seq(v),
517        }
518    }
519}
520
521impl Serialize for PropertyValue {
522    fn serialize<S: ser::Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
523        match self {
524            PropertyValue::Empty => s.serialize_unit(),
525            PropertyValue::Boolean(v) => s.serialize_bool(*v),
526            PropertyValue::Short(v) => s.serialize_i16(*v),
527            PropertyValue::Long(v) => s.serialize_i32(*v),
528            PropertyValue::Long64(v) => s.serialize_i64(*v),
529            PropertyValue::UChar(v) => s.serialize_u8(*v),
530            PropertyValue::UShort(v) => s.serialize_u16(*v),
531            PropertyValue::ULong(v) => s.serialize_u32(*v),
532            PropertyValue::ULong64(v) => s.serialize_u64(*v),
533            PropertyValue::Float(v) => s.serialize_f32(*v),
534            PropertyValue::Double(v) => s.serialize_f64(*v),
535            PropertyValue::String(v) => match std::str::from_utf8(v) {
536                Ok(vs) => s.serialize_str(vs),
537                Err(_) => s.serialize_bytes(v)
538            },
539            PropertyValue::ShortArray(v) => s.collect_seq(v),
540            PropertyValue::LongArray(v) => s.collect_seq(v),
541            PropertyValue::Long64Array(v) => s.collect_seq(v),
542            PropertyValue::UShortArray(v) => s.collect_seq(v),
543            PropertyValue::ULongArray(v) => s.collect_seq(v),
544            PropertyValue::ULong64Array(v) => s.collect_seq(v),
545            PropertyValue::FloatArray(v) => s.collect_seq(v),
546            PropertyValue::DoubleArray(v) => s.collect_seq(v),
547            PropertyValue::StringArray(v) => StringSeq(v).serialize(s),
548        }
549    }
550}