tango_client/
types.rs

1//! Data types used with the Tango API.
2
3use std::convert::TryInto;
4use std::ffi::{CStr, CString};
5use std::str::FromStr;
6use std::{fmt, mem, slice};
7use libc::{self, c_char, c_long};
8use time::{get_time, Timespec};
9
10use crate::c;
11
12
13pub(crate) unsafe fn string_from(ptr: *const c_char) -> String {
14    CStr::from_ptr(ptr).to_string_lossy().into_owned()
15}
16
17fn cstring_from<I: Into<Vec<u8>>>(v: I) -> CString {
18    match CString::new(v) {
19        Ok(s) => s,
20        Err(err) => {
21            let end = err.nul_position();
22            let v = err.into_vec();
23            CString::new(&v[..end]).unwrap()
24        }
25    }
26}
27
28fn check_bool(val: i64) -> Result<bool, ()> {
29    if val == 0 { Ok(false) }
30    else if val == 1 { Ok(true) }
31    else { Err(()) }
32}
33
34
35/// The type of a Tango command argument/result, attribute data, or property
36/// value.
37///
38/// Not all types can be used for all of the three!  For example,
39/// `LongStringArray` is only valid as a command argument or result.
40#[derive(Debug, PartialEq, Eq, Clone, Copy)]
41pub enum TangoDataType {
42    Void = 0,
43    Boolean,
44    Short,
45    Long,
46    Float,
47    Double,
48    UShort,
49    ULong,
50    String,
51    CharArray,
52    ShortArray,
53    LongArray,
54    FloatArray,
55    DoubleArray,
56    UShortArray,
57    ULongArray,
58    StringArray,
59    LongStringArray,
60    DoubleStringArray,
61    State,
62    ConstString,
63    BooleanArray,
64    UChar,
65    Long64,
66    ULong64,
67    Long64Array,
68    ULong64Array,
69    Int,
70    Encoded,
71}
72
73impl TangoDataType {
74    fn from_c(val: c::TangoDataType) -> TangoDataType {
75        match val {
76            c::TangoDataType_DEV_VOID => TangoDataType::Void,
77            c::TangoDataType_DEV_BOOLEAN => TangoDataType::Boolean,
78            c::TangoDataType_DEV_SHORT => TangoDataType::Short,
79            c::TangoDataType_DEV_LONG => TangoDataType::Long,
80            c::TangoDataType_DEV_FLOAT => TangoDataType::Float,
81            c::TangoDataType_DEV_DOUBLE => TangoDataType::Double,
82            c::TangoDataType_DEV_USHORT => TangoDataType::UShort,
83            c::TangoDataType_DEV_ULONG => TangoDataType::ULong,
84            c::TangoDataType_DEV_STRING => TangoDataType::String,
85            c::TangoDataType_DEVVAR_CHARARRAY => TangoDataType::CharArray,
86            c::TangoDataType_DEVVAR_SHORTARRAY => TangoDataType::ShortArray,
87            c::TangoDataType_DEVVAR_LONGARRAY => TangoDataType::LongArray,
88            c::TangoDataType_DEVVAR_FLOATARRAY => TangoDataType::FloatArray,
89            c::TangoDataType_DEVVAR_DOUBLEARRAY => TangoDataType::DoubleArray,
90            c::TangoDataType_DEVVAR_USHORTARRAY => TangoDataType::UShortArray,
91            c::TangoDataType_DEVVAR_ULONGARRAY => TangoDataType::ULongArray,
92            c::TangoDataType_DEVVAR_STRINGARRAY => TangoDataType::StringArray,
93            c::TangoDataType_DEVVAR_LONGSTRINGARRAY => TangoDataType::LongStringArray,
94            c::TangoDataType_DEVVAR_DOUBLESTRINGARRAY => TangoDataType::DoubleStringArray,
95            c::TangoDataType_DEV_STATE => TangoDataType::State,
96            c::TangoDataType_CONST_DEV_STRING => TangoDataType::ConstString,
97            c::TangoDataType_DEVVAR_BOOLEANARRAY => TangoDataType::BooleanArray,
98            c::TangoDataType_DEV_UCHAR => TangoDataType::UChar,
99            c::TangoDataType_DEV_LONG64 => TangoDataType::Long64,
100            c::TangoDataType_DEV_ULONG64 => TangoDataType::ULong64,
101            c::TangoDataType_DEVVAR_LONG64ARRAY => TangoDataType::Long64Array,
102            c::TangoDataType_DEVVAR_ULONG64ARRAY => TangoDataType::ULong64Array,
103            c::TangoDataType_DEV_INT => TangoDataType::Int,
104            c::TangoDataType_DEV_ENCODED => TangoDataType::Encoded,
105            _ => panic!("unknown Tango data type tag={:?}", val)
106        }
107    }
108}
109
110/// Representation of a Tango `DevEncoded` value.
111pub type DevEncoded = (String, Vec<u8>);
112
113
114/// Device states supported by Tango as the `DevState` value type.
115#[derive(Debug, PartialEq, Eq, Clone, Copy)]
116pub enum TangoDevState {
117    On,
118    Off,
119    Close,
120    Open,
121    Insert,
122    Extract,
123    Moving,
124    Standby,
125    Fault,
126    Init,
127    Running,
128    Alarm,
129    Disable,
130    Unknown,
131}
132
133impl TangoDevState {
134    fn from_c(val: c::TangoDevState) -> TangoDevState {
135        match val {
136            c::TangoDevState_ON => TangoDevState::On,
137            c::TangoDevState_OFF => TangoDevState::Off,
138            c::TangoDevState_CLOSE => TangoDevState::Close,
139            c::TangoDevState_OPEN => TangoDevState::Open,
140            c::TangoDevState_INSERT => TangoDevState::Insert,
141            c::TangoDevState_EXTRACT => TangoDevState::Extract,
142            c::TangoDevState_MOVING => TangoDevState::Moving,
143            c::TangoDevState_STANDBY => TangoDevState::Standby,
144            c::TangoDevState_FAULT => TangoDevState::Fault,
145            c::TangoDevState_INIT => TangoDevState::Init,
146            c::TangoDevState_RUNNING => TangoDevState::Running,
147            c::TangoDevState_ALARM => TangoDevState::Alarm,
148            c::TangoDevState_DISABLE => TangoDevState::Disable,
149            c::TangoDevState_UNKNOWN => TangoDevState::Unknown,
150            _ => unreachable!("no TangoDevState for {}", val)
151        }
152    }
153}
154
155impl fmt::Display for TangoDevState {
156    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
157        f.pad(match self {
158            TangoDevState::On => "ON",
159            TangoDevState::Off => "OFF",
160            TangoDevState::Close => "CLOSE",
161            TangoDevState::Open => "OPEN",
162            TangoDevState::Insert => "INSERT",
163            TangoDevState::Extract => "EXTRACT",
164            TangoDevState::Moving => "MOVING",
165            TangoDevState::Standby => "STANDBY",
166            TangoDevState::Fault => "FAULT",
167            TangoDevState::Init => "INIT",
168            TangoDevState::Running => "RUNNING",
169            TangoDevState::Alarm => "ALARM",
170            TangoDevState::Disable => "DISABLE",
171            TangoDevState::Unknown => "UNKNOWN",
172        })
173    }
174}
175
176impl FromStr for TangoDevState {
177    type Err = ();
178
179    fn from_str(s: &str) -> Result<Self, Self::Err> {
180        match s {
181            "ON" => Ok(TangoDevState::On),
182            "OFF" => Ok(TangoDevState::Off),
183            "CLOSE" => Ok(TangoDevState::Close),
184            "OPEN" => Ok(TangoDevState::Open),
185            "INSERT" => Ok(TangoDevState::Insert),
186            "EXTRACT" => Ok(TangoDevState::Extract),
187            "MOVING" => Ok(TangoDevState::Moving),
188            "STANDBY" => Ok(TangoDevState::Standby),
189            "FAULT" => Ok(TangoDevState::Fault),
190            "INIT" => Ok(TangoDevState::Init),
191            "RUNNING" => Ok(TangoDevState::Running),
192            "ALARM" => Ok(TangoDevState::Alarm),
193            "DISABLE" => Ok(TangoDevState::Disable),
194            "UNKNOWN" => Ok(TangoDevState::Unknown),
195            _ => Err(()),
196        }
197    }
198}
199
200
201/// Attribute "quality" constants.
202#[derive(Debug, PartialEq, Eq, Clone, Copy)]
203pub enum AttrQuality {
204    Valid,
205    Invalid,
206    Alarm,
207    Changing,
208    Warning,
209}
210
211impl AttrQuality {
212    fn from_c(val: c::AttrQuality) -> AttrQuality {
213        match val {
214            c::AttrQuality_ATTR_VALID => AttrQuality::Valid,
215            c::AttrQuality_ATTR_INVALID => AttrQuality::Invalid,
216            c::AttrQuality_ATTR_ALARM => AttrQuality::Alarm,
217            c::AttrQuality_ATTR_CHANGING => AttrQuality::Changing,
218            c::AttrQuality_ATTR_WARNING => AttrQuality::Warning,
219            _ => unreachable!("no TangoAttrQuality for {}", val)
220        }
221    }
222}
223
224
225/// Attribute "write type" constants.
226#[derive(Debug, PartialEq, Eq, Clone, Copy)]
227pub enum AttrWriteType {
228    Read,
229    ReadWithWrite,
230    Write,
231    ReadWrite,
232}
233
234impl AttrWriteType {
235    fn from_c(val: c::AttrWriteType) -> AttrWriteType {
236        match val {
237            c::AttrWriteType_READ => AttrWriteType::Read,
238            c::AttrWriteType_READ_WITH_WRITE => AttrWriteType::ReadWithWrite,
239            c::AttrWriteType_WRITE => AttrWriteType::Write,
240            c::AttrWriteType_READ_WRITE => AttrWriteType::ReadWrite,
241            _ => unreachable!("no TangoAttrWriteType for {}", val)
242        }
243    }
244}
245
246
247/// Attribute "data format" constants.
248#[derive(Debug, PartialEq, Eq, Clone, Copy)]
249pub enum AttrDataFormat {
250    Scalar,
251    Spectrum,
252    Image,
253}
254
255impl AttrDataFormat {
256    fn from_c(val: c::AttrDataFormat) -> AttrDataFormat {
257        match val {
258            c::AttrDataFormat_SCALAR => AttrDataFormat::Scalar,
259            c::AttrDataFormat_SPECTRUM => AttrDataFormat::Spectrum,
260            c::AttrDataFormat_IMAGE => AttrDataFormat::Image,
261            _ => unreachable!("no TangoAttrDataFormat for {}", val)
262        }
263    }
264}
265
266
267/// Device "display level" constants.
268#[derive(Debug, PartialEq, Eq, Clone, Copy)]
269pub enum DispLevel {
270    Operator,
271    Expert,
272}
273
274impl DispLevel {
275    fn from_c(val: c::DispLevel) -> DispLevel {
276        match val {
277            c::DispLevel_OPERATOR => DispLevel::Operator,
278            c::DispLevel_EXPERT => DispLevel::Expert,
279            _ => unreachable!("no TangoDispLevel for {}", val)
280        }
281    }
282}
283
284
285/// Error severity constants.
286#[derive(Debug, PartialEq, Eq, Clone, Copy)]
287pub enum ErrSeverity {
288    Warn,
289    Err,
290    Panic,
291}
292
293impl ErrSeverity {
294    pub(crate) fn from_c(val: c::ErrSeverity) -> ErrSeverity {
295        match val {
296            c::ErrSeverity_WARN => ErrSeverity::Warn,
297            c::ErrSeverity_ERR => ErrSeverity::Err,
298            c::ErrSeverity_PANIC => ErrSeverity::Panic,
299            _ => unreachable!("no TangoErrSeverity for {}", val)
300        }
301    }
302}
303
304
305/// Device data source constants.
306#[derive(Debug, PartialEq, Eq, Clone, Copy)]
307pub enum DevSource {
308    Dev,
309    Cache,
310    CacheDev,
311}
312
313impl DevSource {
314    pub(crate) fn from_c(val: c::DevSource) -> DevSource {
315        match val {
316            c::DevSource_DEV => DevSource::Dev,
317            c::DevSource_CACHE => DevSource::Cache,
318            c::DevSource_CACHE_DEV => DevSource::CacheDev,
319            _ => unreachable!("no TangoDevSource for {}", val)
320        }
321    }
322}
323
324
325/// Provides information about the API of a single command.
326#[derive(Debug)]
327pub struct CommandInfo {
328    pub name: String,
329    pub in_type: TangoDataType,
330    pub out_type: TangoDataType,
331    pub in_type_desc: String,
332    pub out_type_desc: String,
333    pub disp_level: DispLevel,
334}
335
336impl CommandInfo {
337    pub(crate) unsafe fn from_c(mut info: c::CommandInfo, free: bool) -> CommandInfo {
338        let res = CommandInfo {
339            name: string_from(info.cmd_name),
340            in_type: TangoDataType::from_c(info.in_type as u32),
341            out_type: TangoDataType::from_c(info.out_type as u32),
342            in_type_desc: string_from(info.in_type_desc),
343            out_type_desc: string_from(info.out_type_desc),
344            disp_level: DispLevel::from_c(info.disp_level),
345        };
346        if free {
347            c::tango_free_CommandInfo(&mut info);
348        }
349        res
350    }
351}
352
353
354/// Represents the input or output arguments of a command.
355///
356/// The normal way to construct this is to use the desired variant directly.
357#[derive(Debug, PartialEq, Clone)]
358pub enum CommandData {
359    Void,
360
361    Boolean(bool),
362    Short(i16),
363    UShort(u16),
364    Long(i32),
365    ULong(u32),
366    Long64(i64),
367    ULong64(u64),
368
369    Float(f32),
370    Double(f64),
371
372    String(Vec<u8>),
373    State(TangoDevState),
374    Encoded(DevEncoded),
375
376    BooleanArray(Vec<bool>),
377    CharArray(Vec<u8>),
378    ShortArray(Vec<i16>),
379    UShortArray(Vec<u16>),
380    LongArray(Vec<i32>),
381    ULongArray(Vec<u32>),
382    Long64Array(Vec<i64>),
383    ULong64Array(Vec<u64>),
384
385    FloatArray(Vec<f32>),
386    DoubleArray(Vec<f64>),
387
388    StringArray(Vec<Vec<u8>>),
389    LongStringArray(Vec<i32>, Vec<Vec<u8>>),
390    DoubleStringArray(Vec<f64>, Vec<Vec<u8>>),
391}
392
393impl CommandData {
394    /// Construct a CommandData from a Rust string slice.
395    pub fn from_str(s: &str) -> Self {
396        Self::String(s.to_owned().into_bytes())
397    }
398
399    /// Try to convert this data into a different type.
400    ///
401    /// If the conversion fails or is impossible, `Self` is returned unchanged
402    /// in the `Err` variant.
403    pub fn convert(self, to: TangoDataType) -> Result<Self, Self> {
404        match self {
405            Self::Void => match to {
406                TangoDataType::Void => Ok(self),
407                _ => Err(self),
408            }
409            Self::Boolean(v) => match to {
410                TangoDataType::Boolean => Ok(self),
411                TangoDataType::Short => Ok(Self::Short(v as _)),
412                TangoDataType::UShort => Ok(Self::UShort(v as _)),
413                TangoDataType::Int |
414                TangoDataType::Long => Ok(Self::Long(v as _)),
415                TangoDataType::ULong => Ok(Self::ULong(v as _)),
416                TangoDataType::Long64 => Ok(Self::Long64(v as _)),
417                TangoDataType::ULong64 => Ok(Self::ULong64(v as _)),
418                TangoDataType::Float => Ok(Self::Float(v as i32 as _)),
419                TangoDataType::Double => Ok(Self::Double(v as i32 as _)),
420                _ => Err(self)
421            }
422            Self::Short(v) => match to {
423                TangoDataType::Boolean => check_bool(v as i64).map(Self::Boolean).map_err(|_| self),
424                TangoDataType::Short => Ok(self),
425                TangoDataType::UShort => v.try_into().map(Self::UShort).map_err(|_| self),
426                TangoDataType::Int |
427                TangoDataType::Long => Ok(Self::Long(v as _)),
428                TangoDataType::ULong => Ok(Self::ULong(v as _)),
429                TangoDataType::Long64 => Ok(Self::Long64(v as _)),
430                TangoDataType::ULong64 => Ok(Self::ULong64(v as _)),
431                TangoDataType::Float => Ok(Self::Float(v as _)),
432                TangoDataType::Double => Ok(Self::Double(v as _)),
433                _ => Err(self)
434            }
435            Self::UShort(v) => match to {
436                TangoDataType::Boolean => check_bool(v as i64).map(Self::Boolean).map_err(|_| self),
437                TangoDataType::Short => v.try_into().map(Self::Short).map_err(|_| self),
438                TangoDataType::UShort => Ok(self),
439                TangoDataType::Int |
440                TangoDataType::Long => Ok(Self::Long(v as _)),
441                TangoDataType::ULong => Ok(Self::ULong(v as _)),
442                TangoDataType::Long64 => Ok(Self::Long64(v as _)),
443                TangoDataType::ULong64 => Ok(Self::ULong64(v as _)),
444                TangoDataType::Float => Ok(Self::Float(v as _)),
445                TangoDataType::Double => Ok(Self::Double(v as _)),
446                _ => Err(self)
447            }
448            Self::Long(v) => match to {
449                TangoDataType::Boolean => check_bool(v as i64).map(Self::Boolean).map_err(|_| self),
450                TangoDataType::Short => v.try_into().map(Self::Short).map_err(|_| self),
451                TangoDataType::UShort => v.try_into().map(Self::UShort).map_err(|_| self),
452                TangoDataType::Int |
453                TangoDataType::Long => Ok(self),
454                TangoDataType::ULong => v.try_into().map(Self::ULong).map_err(|_| self),
455                TangoDataType::Long64 => Ok(Self::Long64(v as _)),
456                TangoDataType::ULong64 => Ok(Self::ULong64(v as _)),
457                TangoDataType::Float => Ok(Self::Float(v as _)),
458                TangoDataType::Double => Ok(Self::Double(v as _)),
459                _ => Err(self)
460            }
461            Self::ULong(v) => match to {
462                TangoDataType::Boolean => check_bool(v as i64).map(Self::Boolean).map_err(|_| self),
463                TangoDataType::Short => v.try_into().map(Self::Short).map_err(|_| self),
464                TangoDataType::UShort => v.try_into().map(Self::UShort).map_err(|_| self),
465                TangoDataType::Int |
466                TangoDataType::Long => v.try_into().map(Self::Long).map_err(|_| self),
467                TangoDataType::ULong => Ok(self),
468                TangoDataType::Long64 => Ok(Self::Long64(v as _)),
469                TangoDataType::ULong64 => Ok(Self::ULong64(v as _)),
470                TangoDataType::Float => Ok(Self::Float(v as _)),
471                TangoDataType::Double => Ok(Self::Double(v as _)),
472                _ => Err(self)
473            }
474            Self::Long64(v) => match to {
475                TangoDataType::Boolean => check_bool(v as i64).map(Self::Boolean).map_err(|_| self),
476                TangoDataType::Short => v.try_into().map(Self::Short).map_err(|_| self),
477                TangoDataType::UShort => v.try_into().map(Self::UShort).map_err(|_| self),
478                TangoDataType::Int |
479                TangoDataType::Long => v.try_into().map(Self::Long).map_err(|_| self),
480                TangoDataType::ULong => v.try_into().map(Self::ULong).map_err(|_| self),
481                TangoDataType::Long64 => Ok(self),
482                TangoDataType::ULong64 => v.try_into().map(Self::ULong64).map_err(|_| self),
483                TangoDataType::Float => Ok(Self::Float(v as _)),
484                TangoDataType::Double => Ok(Self::Double(v as _)),
485                _ => Err(self)
486            }
487            Self::ULong64(v) => match to {
488                TangoDataType::Boolean => check_bool(v as i64).map(Self::Boolean).map_err(|_| self),
489                TangoDataType::Short => v.try_into().map(Self::Short).map_err(|_| self),
490                TangoDataType::UShort => v.try_into().map(Self::UShort).map_err(|_| self),
491                TangoDataType::Int |
492                TangoDataType::Long => v.try_into().map(Self::Long).map_err(|_| self),
493                TangoDataType::ULong => v.try_into().map(Self::ULong).map_err(|_| self),
494                TangoDataType::Long64 => v.try_into().map(Self::Long64).map_err(|_| self),
495                TangoDataType::ULong64 => Ok(self),
496                TangoDataType::Float => Ok(Self::Float(v as _)),
497                TangoDataType::Double => Ok(Self::Double(v as _)),
498                _ => Err(self)
499            }
500            Self::Float(v) => match to {
501                TangoDataType::Float => Ok(self),
502                TangoDataType::Double => Ok(Self::Double(v as _)),
503                _ => Err(self)
504            }
505            Self::Double(v) => match to {
506                TangoDataType::Float => Ok(Self::Float(v as _)),
507                TangoDataType::Double => Ok(self),
508                _ => Err(self)
509            }
510            Self::String(ref v) => match to {
511                TangoDataType::ConstString |
512                TangoDataType::String => Ok(self),
513                TangoDataType::State => std::str::from_utf8(v).map_err(drop)
514                                                              .and_then(|s| s.parse())
515                                                              .map(Self::State)
516                                                              .map_err(|_| self),
517                _ => Err(self)
518            }
519            Self::State(_) => match to {
520                TangoDataType::State => Ok(self),
521                _ => Err(self),
522            }
523            Self::Encoded(_) => match to {
524                TangoDataType::Encoded => Ok(self),
525                _ => Err(self),
526            }
527            Self::BooleanArray(v) => match to {
528                TangoDataType::BooleanArray => Ok(Self::BooleanArray(v)),
529                TangoDataType::CharArray => Ok(Self::CharArray(v.into_iter().map(|v| v as _).collect())),
530                TangoDataType::ShortArray => Ok(Self::ShortArray(v.into_iter().map(|v| v as _).collect())),
531                TangoDataType::UShortArray => Ok(Self::UShortArray(v.into_iter().map(|v| v as _).collect())),
532                TangoDataType::LongArray => Ok(Self::LongArray(v.into_iter().map(|v| v as _).collect())),
533                TangoDataType::ULongArray => Ok(Self::ULongArray(v.into_iter().map(|v| v as _).collect())),
534                TangoDataType::Long64Array => Ok(Self::Long64Array(v.into_iter().map(|v| v as _).collect())),
535                TangoDataType::ULong64Array => Ok(Self::ULong64Array(v.into_iter().map(|v| v as _).collect())),
536                TangoDataType::FloatArray => Ok(Self::FloatArray(v.into_iter().map(|v| v as i32 as _).collect())),
537                TangoDataType::DoubleArray => Ok(Self::DoubleArray(v.into_iter().map(|v| v as i32 as _).collect())),
538                TangoDataType::StringArray if v.len() == 0 => Ok(Self::StringArray(vec![])),
539                _ => Err(Self::BooleanArray(v)),
540            }
541            Self::CharArray(v) => match to {
542                TangoDataType::BooleanArray if v.len() == 0 => Ok(Self::BooleanArray(vec![])),
543                TangoDataType::CharArray => Ok(Self::CharArray(v)),
544                TangoDataType::ShortArray => Ok(Self::ShortArray(v.into_iter().map(|v| v as _).collect())),
545                TangoDataType::UShortArray => Ok(Self::UShortArray(v.into_iter().map(|v| v as _).collect())),
546                TangoDataType::LongArray => Ok(Self::LongArray(v.into_iter().map(|v| v as _).collect())),
547                TangoDataType::ULongArray => Ok(Self::ULongArray(v.into_iter().map(|v| v as _).collect())),
548                TangoDataType::Long64Array => Ok(Self::Long64Array(v.into_iter().map(|v| v as _).collect())),
549                TangoDataType::ULong64Array => Ok(Self::ULong64Array(v.into_iter().map(|v| v as _).collect())),
550                TangoDataType::FloatArray => Ok(Self::FloatArray(v.into_iter().map(|v| v as _).collect())),
551                TangoDataType::DoubleArray => Ok(Self::DoubleArray(v.into_iter().map(|v| v as _).collect())),
552                TangoDataType::StringArray if v.len() == 0 => Ok(Self::StringArray(vec![])),
553                _ => Err(Self::CharArray(v)),
554            }
555            Self::ShortArray(v) => match to {
556                TangoDataType::BooleanArray if v.len() == 0 => Ok(Self::BooleanArray(vec![])),
557                TangoDataType::CharArray => v.iter().map(|&v| v.try_into())
558                                                    .collect::<Result<Vec<_>, _>>()
559                                                    .map(Self::CharArray)
560                                                    .map_err(|_| Self::ShortArray(v)),
561                TangoDataType::ShortArray => Ok(Self::ShortArray(v)),
562                TangoDataType::UShortArray => v.iter().map(|&v| v.try_into())
563                                                    .collect::<Result<Vec<_>, _>>()
564                                                    .map(Self::UShortArray)
565                                                    .map_err(|_| Self::ShortArray(v)),
566                TangoDataType::LongArray => Ok(Self::LongArray(v.into_iter().map(|v| v as _).collect())),
567                TangoDataType::ULongArray => Ok(Self::ULongArray(v.into_iter().map(|v| v as _).collect())),
568                TangoDataType::Long64Array => Ok(Self::Long64Array(v.into_iter().map(|v| v as _).collect())),
569                TangoDataType::ULong64Array => Ok(Self::ULong64Array(v.into_iter().map(|v| v as _).collect())),
570                TangoDataType::FloatArray => Ok(Self::FloatArray(v.into_iter().map(|v| v as _).collect())),
571                TangoDataType::DoubleArray => Ok(Self::DoubleArray(v.into_iter().map(|v| v as _).collect())),
572                TangoDataType::StringArray if v.len() == 0 => Ok(Self::StringArray(vec![])),
573                _ => Err(Self::ShortArray(v)),
574            }
575            Self::UShortArray(v) => match to {
576                TangoDataType::BooleanArray if v.len() == 0 => Ok(Self::BooleanArray(vec![])),
577                TangoDataType::CharArray => v.iter().map(|&v| v.try_into())
578                                                    .collect::<Result<Vec<_>, _>>()
579                                                    .map(Self::CharArray)
580                                                    .map_err(|_| Self::UShortArray(v)),
581                TangoDataType::ShortArray => v.iter().map(|&v| v.try_into())
582                                                    .collect::<Result<Vec<_>, _>>()
583                                                    .map(Self::ShortArray)
584                                                    .map_err(|_| Self::UShortArray(v)),
585                TangoDataType::UShortArray => Ok(Self::UShortArray(v)),
586                TangoDataType::LongArray => Ok(Self::LongArray(v.into_iter().map(|v| v as _).collect())),
587                TangoDataType::ULongArray => Ok(Self::ULongArray(v.into_iter().map(|v| v as _).collect())),
588                TangoDataType::Long64Array => Ok(Self::Long64Array(v.into_iter().map(|v| v as _).collect())),
589                TangoDataType::ULong64Array => Ok(Self::ULong64Array(v.into_iter().map(|v| v as _).collect())),
590                TangoDataType::FloatArray => Ok(Self::FloatArray(v.into_iter().map(|v| v as _).collect())),
591                TangoDataType::DoubleArray => Ok(Self::DoubleArray(v.into_iter().map(|v| v as _).collect())),
592                TangoDataType::StringArray if v.len() == 0 => Ok(Self::StringArray(vec![])),
593                _ => Err(Self::UShortArray(v)),
594            }
595            Self::LongArray(v) => match to {
596                TangoDataType::BooleanArray if v.len() == 0 => Ok(Self::BooleanArray(vec![])),
597                TangoDataType::CharArray => v.iter().map(|&v| v.try_into())
598                                                    .collect::<Result<Vec<_>, _>>()
599                                                    .map(Self::CharArray)
600                                                    .map_err(|_| Self::LongArray(v)),
601                TangoDataType::ShortArray => v.iter().map(|&v| v.try_into())
602                                                    .collect::<Result<Vec<_>, _>>()
603                                                    .map(Self::ShortArray)
604                                                    .map_err(|_| Self::LongArray(v)),
605                TangoDataType::UShortArray => v.iter().map(|&v| v.try_into())
606                                                    .collect::<Result<Vec<_>, _>>()
607                                                    .map(Self::UShortArray)
608                                                    .map_err(|_| Self::LongArray(v)),
609                TangoDataType::LongArray => Ok(Self::LongArray(v)),
610                TangoDataType::ULongArray => v.iter().map(|&v| v.try_into())
611                                                    .collect::<Result<Vec<_>, _>>()
612                                                    .map(Self::ULongArray)
613                                                    .map_err(|_| Self::LongArray(v)),
614                TangoDataType::Long64Array => Ok(Self::Long64Array(v.into_iter().map(|v| v as _).collect())),
615                TangoDataType::ULong64Array => Ok(Self::ULong64Array(v.into_iter().map(|v| v as _).collect())),
616                TangoDataType::FloatArray => Ok(Self::FloatArray(v.into_iter().map(|v| v as _).collect())),
617                TangoDataType::DoubleArray => Ok(Self::DoubleArray(v.into_iter().map(|v| v as _).collect())),
618                TangoDataType::StringArray if v.len() == 0 => Ok(Self::StringArray(vec![])),
619                _ => Err(Self::LongArray(v)),
620            }
621            Self::ULongArray(v) => match to {
622                TangoDataType::BooleanArray if v.len() == 0 => Ok(Self::BooleanArray(vec![])),
623                TangoDataType::CharArray => v.iter().map(|&v| v.try_into())
624                                                    .collect::<Result<Vec<_>, _>>()
625                                                    .map(Self::CharArray)
626                                                    .map_err(|_| Self::ULongArray(v)),
627                TangoDataType::ShortArray => v.iter().map(|&v| v.try_into())
628                                                    .collect::<Result<Vec<_>, _>>()
629                                                    .map(Self::ShortArray)
630                                                    .map_err(|_| Self::ULongArray(v)),
631                TangoDataType::UShortArray => v.iter().map(|&v| v.try_into())
632                                                    .collect::<Result<Vec<_>, _>>()
633                                                    .map(Self::UShortArray)
634                                                    .map_err(|_| Self::ULongArray(v)),
635                TangoDataType::LongArray => v.iter().map(|&v| v.try_into())
636                                                    .collect::<Result<Vec<_>, _>>()
637                                                    .map(Self::LongArray)
638                                                    .map_err(|_| Self::ULongArray(v)),
639                TangoDataType::ULongArray => Ok(Self::ULongArray(v)),
640                TangoDataType::Long64Array => Ok(Self::Long64Array(v.into_iter().map(|v| v as _).collect())),
641                TangoDataType::ULong64Array => Ok(Self::ULong64Array(v.into_iter().map(|v| v as _).collect())),
642                TangoDataType::FloatArray => Ok(Self::FloatArray(v.into_iter().map(|v| v as _).collect())),
643                TangoDataType::DoubleArray => Ok(Self::DoubleArray(v.into_iter().map(|v| v as _).collect())),
644                TangoDataType::StringArray if v.len() == 0 => Ok(Self::StringArray(vec![])),
645                _ => Err(Self::ULongArray(v)),
646            }
647            Self::Long64Array(v) => match to {
648                TangoDataType::BooleanArray if v.len() == 0 => Ok(Self::BooleanArray(vec![])),
649                TangoDataType::CharArray => v.iter().map(|&v| v.try_into())
650                                                    .collect::<Result<Vec<_>, _>>()
651                                                    .map(Self::CharArray)
652                                                    .map_err(|_| Self::Long64Array(v)),
653                TangoDataType::ShortArray => v.iter().map(|&v| v.try_into())
654                                                    .collect::<Result<Vec<_>, _>>()
655                                                    .map(Self::ShortArray)
656                                                    .map_err(|_| Self::Long64Array(v)),
657                TangoDataType::UShortArray => v.iter().map(|&v| v.try_into())
658                                                    .collect::<Result<Vec<_>, _>>()
659                                                    .map(Self::UShortArray)
660                                                    .map_err(|_| Self::Long64Array(v)),
661                TangoDataType::LongArray => v.iter().map(|&v| v.try_into())
662                                                    .collect::<Result<Vec<_>, _>>()
663                                                    .map(Self::LongArray)
664                                                    .map_err(|_| Self::Long64Array(v)),
665                TangoDataType::ULongArray => v.iter().map(|&v| v.try_into())
666                                                    .collect::<Result<Vec<_>, _>>()
667                                                    .map(Self::ULongArray)
668                                                    .map_err(|_| Self::Long64Array(v)),
669                TangoDataType::Long64Array => Ok(Self::Long64Array(v)),
670                TangoDataType::ULong64Array => v.iter().map(|&v| v.try_into())
671                                                    .collect::<Result<Vec<_>, _>>()
672                                                    .map(Self::ULong64Array)
673                                                    .map_err(|_| Self::Long64Array(v)),
674                TangoDataType::FloatArray => Ok(Self::FloatArray(v.into_iter().map(|v| v as _).collect())),
675                TangoDataType::DoubleArray => Ok(Self::DoubleArray(v.into_iter().map(|v| v as _).collect())),
676                TangoDataType::StringArray if v.len() == 0 => Ok(Self::StringArray(vec![])),
677                _ => Err(Self::Long64Array(v)),
678            }
679            Self::ULong64Array(v) => match to {
680                TangoDataType::BooleanArray if v.len() == 0 => Ok(Self::BooleanArray(vec![])),
681                TangoDataType::CharArray => v.iter().map(|&v| v.try_into())
682                                                    .collect::<Result<Vec<_>, _>>()
683                                                    .map(Self::CharArray)
684                                                    .map_err(|_| Self::ULong64Array(v)),
685                TangoDataType::ShortArray => v.iter().map(|&v| v.try_into())
686                                                    .collect::<Result<Vec<_>, _>>()
687                                                    .map(Self::ShortArray)
688                                                    .map_err(|_| Self::ULong64Array(v)),
689                TangoDataType::UShortArray => v.iter().map(|&v| v.try_into())
690                                                    .collect::<Result<Vec<_>, _>>()
691                                                    .map(Self::UShortArray)
692                                                    .map_err(|_| Self::ULong64Array(v)),
693                TangoDataType::LongArray => v.iter().map(|&v| v.try_into())
694                                                    .collect::<Result<Vec<_>, _>>()
695                                                    .map(Self::LongArray)
696                                                    .map_err(|_| Self::ULong64Array(v)),
697                TangoDataType::ULongArray => v.iter().map(|&v| v.try_into())
698                                                    .collect::<Result<Vec<_>, _>>()
699                                                    .map(Self::ULongArray)
700                                                    .map_err(|_| Self::ULong64Array(v)),
701                TangoDataType::Long64Array => v.iter().map(|&v| v.try_into())
702                                                    .collect::<Result<Vec<_>, _>>()
703                                                    .map(Self::Long64Array)
704                                                    .map_err(|_| Self::ULong64Array(v)),
705                TangoDataType::ULong64Array => Ok(Self::ULong64Array(v)),
706                TangoDataType::FloatArray => Ok(Self::FloatArray(v.into_iter().map(|v| v as _).collect())),
707                TangoDataType::DoubleArray => Ok(Self::DoubleArray(v.into_iter().map(|v| v as _).collect())),
708                TangoDataType::StringArray if v.len() == 0 => Ok(Self::StringArray(vec![])),
709                _ => Err(Self::ULong64Array(v)),
710            }
711            Self::FloatArray(v) => match to {
712                TangoDataType::BooleanArray if v.len() == 0 => Ok(Self::BooleanArray(vec![])),
713                TangoDataType::CharArray if v.len() == 0 => Ok(Self::CharArray(vec![])),
714                TangoDataType::ShortArray if v.len() == 0 => Ok(Self::ShortArray(vec![])),
715                TangoDataType::UShortArray if v.len() == 0 => Ok(Self::UShortArray(vec![])),
716                TangoDataType::LongArray if v.len() == 0 => Ok(Self::LongArray(vec![])),
717                TangoDataType::ULongArray if v.len() == 0 => Ok(Self::ULongArray(vec![])),
718                TangoDataType::Long64Array if v.len() == 0 => Ok(Self::Long64Array(vec![])),
719                TangoDataType::ULong64Array if v.len() == 0 => Ok(Self::ULong64Array(vec![])),
720                TangoDataType::FloatArray => Ok(Self::FloatArray(v)),
721                TangoDataType::DoubleArray => Ok(Self::DoubleArray(v.into_iter().map(|v| v as _).collect())),
722                TangoDataType::StringArray if v.len() == 0 => Ok(Self::StringArray(vec![])),
723                _ => Err(Self::FloatArray(v)),
724            }
725            Self::DoubleArray(v) => match to {
726                TangoDataType::BooleanArray if v.len() == 0 => Ok(Self::BooleanArray(vec![])),
727                TangoDataType::CharArray if v.len() == 0 => Ok(Self::CharArray(vec![])),
728                TangoDataType::ShortArray if v.len() == 0 => Ok(Self::ShortArray(vec![])),
729                TangoDataType::UShortArray if v.len() == 0 => Ok(Self::UShortArray(vec![])),
730                TangoDataType::LongArray if v.len() == 0 => Ok(Self::LongArray(vec![])),
731                TangoDataType::ULongArray if v.len() == 0 => Ok(Self::ULongArray(vec![])),
732                TangoDataType::Long64Array if v.len() == 0 => Ok(Self::Long64Array(vec![])),
733                TangoDataType::ULong64Array if v.len() == 0 => Ok(Self::ULong64Array(vec![])),
734                TangoDataType::FloatArray => Ok(Self::FloatArray(v.into_iter().map(|v| v as _).collect())),
735                TangoDataType::DoubleArray => Ok(Self::DoubleArray(v)),
736                TangoDataType::StringArray if v.len() == 0 => Ok(Self::StringArray(vec![])),
737                _ => Err(Self::DoubleArray(v)),
738            }
739            Self::StringArray(v) => match to {
740                TangoDataType::BooleanArray if v.len() == 0 => Ok(Self::BooleanArray(vec![])),
741                TangoDataType::CharArray if v.len() == 0 => Ok(Self::CharArray(vec![])),
742                TangoDataType::ShortArray if v.len() == 0 => Ok(Self::ShortArray(vec![])),
743                TangoDataType::UShortArray if v.len() == 0 => Ok(Self::UShortArray(vec![])),
744                TangoDataType::LongArray if v.len() == 0 => Ok(Self::LongArray(vec![])),
745                TangoDataType::ULongArray if v.len() == 0 => Ok(Self::ULongArray(vec![])),
746                TangoDataType::Long64Array if v.len() == 0 => Ok(Self::Long64Array(vec![])),
747                TangoDataType::ULong64Array if v.len() == 0 => Ok(Self::ULong64Array(vec![])),
748                TangoDataType::FloatArray if v.len() == 0 => Ok(Self::FloatArray(vec![])),
749                TangoDataType::DoubleArray if v.len() == 0 => Ok(Self::DoubleArray(vec![])),
750                TangoDataType::StringArray => Ok(Self::StringArray(v)),
751                _ => Err(Self::StringArray(v)),
752            }
753            Self::LongStringArray(v, w) => match to {
754                TangoDataType::LongStringArray => Ok(Self::LongStringArray(v, w)),
755                _ => Err(Self::LongStringArray(v, w))
756            }
757            Self::DoubleStringArray(v, w) => match to {
758                TangoDataType::DoubleStringArray => Ok(Self::DoubleStringArray(v, w)),
759                _ => Err(Self::DoubleStringArray(v, w))
760            }
761        }
762    }
763
764    /// Return the value if it's a bool or integral 0 or 1.  Otherwise return
765    /// `Err(self)`.
766    pub fn into_bool(self) -> Result<bool, Self> {
767        match self {
768            Self::Boolean(v) => Ok(v),
769            Self::Short(v) => check_bool(v as i64).map_err(|_| self),
770            Self::UShort(v) => check_bool(v as i64).map_err(|_| self),
771            Self::Long(v) => check_bool(v as i64).map_err(|_| self),
772            Self::ULong(v) => check_bool(v as i64).map_err(|_| self),
773            Self::Long64(v) => check_bool(v as i64).map_err(|_| self),
774            Self::ULong64(v) => check_bool(v as i64).map_err(|_| self),
775            _ => Err(self),
776        }
777    }
778
779    /// Return the value as i32 if it's an integral type and inside i32 limits.
780    /// Otherwise return `Err(self)`.
781    pub fn into_i32(self) -> Result<i32, Self> {
782        match self {
783            Self::Boolean(v) => Ok(v as i32),
784            Self::Short(v) => Ok(v as i32),
785            Self::UShort(v) => Ok(v as i32),
786            Self::Long(v) => Ok(v),
787            Self::ULong(v) => v.try_into().map_err(|_| self),
788            Self::Long64(v) => v.try_into().map_err(|_| self),
789            Self::ULong64(v) => v.try_into().map_err(|_| self),
790            _ => Err(self),
791        }
792    }
793
794    /// Return the value as i64 if it's a an integral type and inside i64
795    /// limits.  Otherwise return `Err(self)`.
796    pub fn into_i64(self) -> Result<i64, Self> {
797        match self {
798            Self::Boolean(v) => Ok(v as i64),
799            Self::Short(v) => Ok(v as i64),
800            Self::UShort(v) => Ok(v as i64),
801            Self::Long(v) => Ok(v as i64),
802            Self::ULong(v) => Ok(v as i64),
803            Self::Long64(v) => Ok(v),
804            Self::ULong64(v) => v.try_into().map_err(|_| self),
805            _ => Err(self),
806        }
807    }
808
809    /// Return the value as u32 if it's an integral type and inside u32 limits.
810    /// Otherwise return `Err(self)`.
811    pub fn into_u32(self) -> Result<u32, Self> {
812        match self {
813            Self::Boolean(v) => Ok(v as u32),
814            Self::Short(v) => Ok(v as u32),
815            Self::UShort(v) => Ok(v as u32),
816            Self::Long(v) => v.try_into().map_err(|_| self),
817            Self::ULong(v) => Ok(v),
818            Self::Long64(v) => v.try_into().map_err(|_| self),
819            Self::ULong64(v) => v.try_into().map_err(|_| self),
820            _ => Err(self),
821        }
822    }
823
824    /// Return the value as u64 if it's an integral type and inside u64 limits.
825    /// Otherwise return `Err(self)`.
826    pub fn into_u64(self) -> Result<u64, Self> {
827        match self {
828            Self::Boolean(v) => Ok(v as u64),
829            Self::Short(v) => Ok(v as u64),
830            Self::Long(v) => Ok(v as u64),
831            Self::UShort(v) => Ok(v as u64),
832            Self::ULong(v) => Ok(v as u64),
833            Self::Long64(v) => v.try_into().map_err(|_| self),
834            Self::ULong64(v) => Ok(v),
835            _ => Err(self),
836        }
837    }
838
839    /// Return the value as f32 if it's a numeric type.  Otherwise return `Err(self)`.
840    pub fn into_f32(self) -> Result<f32, Self> {
841        match self {
842            Self::Boolean(v) => Ok(v as i32 as f32),
843            Self::Short(v) => Ok(v as f32),
844            Self::Long(v) => Ok(v as f32),
845            Self::Long64(v) => Ok(v as f32),
846            Self::UShort(v) => Ok(v as f32),
847            Self::ULong(v) => Ok(v as f32),
848            Self::ULong64(v) => Ok(v as f32),
849            Self::Float(v) => Ok(v),
850            Self::Double(v) => Ok(v as f32),
851            _ => Err(self),
852        }
853    }
854
855    /// Return the value as f64 if it's a numeric type.  Otherwise return `Err(self)`.
856    pub fn into_f64(self) -> Result<f64, Self> {
857        match self {
858            Self::Boolean(v) => Ok(v as i32 as f64),
859            Self::Short(v) => Ok(v as f64),
860            Self::Long(v) => Ok(v as f64),
861            Self::Long64(v) => Ok(v as f64),
862            Self::UShort(v) => Ok(v as f64),
863            Self::ULong(v) => Ok(v as f64),
864            Self::ULong64(v) => Ok(v as f64),
865            Self::Float(v) => Ok(v as f64),
866            Self::Double(v) => Ok(v),
867            _ => Err(self),
868        }
869    }
870
871    /// Return the value as a byte array if it's a string, DevEncoded or
872    /// CharArray.  Otherwise return `Err(self)`.
873    pub fn into_bytes(self) -> Result<Vec<u8>, Self> {
874        match self {
875            Self::String(s) => Ok(s),
876            Self::Encoded((_, s)) => Ok(s),
877            Self::CharArray(s) => Ok(s),
878            _ => Err(self),
879        }
880    }
881
882    /// Return the value as a string if it's a string, DevEncoded or CharArray,
883    /// and decodable as UTF-8.  Otherwise return `Err(self)`.
884    pub fn into_string(self) -> Result<String, Self> {
885        match self {
886            Self::String(s) => String::from_utf8(s).map_err(|e| Self::String(e.into_bytes())),
887            Self::Encoded((f, s)) => String::from_utf8(s).map_err(|e| Self::Encoded((f, e.into_bytes()))),
888            Self::CharArray(s) => String::from_utf8(s).map_err(|e| Self::CharArray(e.into_bytes())),
889            _ => Err(self),
890        }
891    }
892
893    pub(crate) unsafe fn from_c(mut cmd_data: c::CommandData) -> Self {
894        let tag = TangoDataType::from_c(cmd_data.arg_type);
895        let data = cmd_data.cmd_data;
896        let res = match tag {
897            TangoDataType::Void => Self::Void,
898            TangoDataType::Boolean => Self::Boolean(data.bool_val),
899            TangoDataType::Short => Self::Short(data.short_val),
900            TangoDataType::Long | TangoDataType::Int => Self::Long(data.long_val),
901            TangoDataType::Float => Self::Float(data.float_val),
902            TangoDataType::Double => Self::Double(data.double_val),
903            TangoDataType::UShort => Self::UShort(data.ushort_val),
904            TangoDataType::ULong => Self::ULong(data.ulong_val),
905            TangoDataType::UChar => unimplemented!(),  // only for attribute arrays
906            TangoDataType::Long64 => Self::Long64(data.long64_val),
907            TangoDataType::ULong64 => Self::ULong64(data.ulong64_val),
908            TangoDataType::State => Self::State(TangoDevState::from_c(data.state_val)),
909            // note: for all arrays this copies the data, instead of reusing the
910            // existing allocation
911            TangoDataType::String | TangoDataType::ConstString => Self::String({
912                let ptr = data.string_val;
913                let len = libc::strlen(ptr);
914                Vec::from(slice::from_raw_parts(ptr as *mut u8, len))
915            }),
916            TangoDataType::CharArray => Self::CharArray({
917                let ptr = data.char_arr;
918                Vec::from(slice::from_raw_parts(ptr.sequence, ptr.length as usize))
919            }),
920            TangoDataType::ShortArray => Self::ShortArray({
921                let ptr = data.short_arr;
922                Vec::from(slice::from_raw_parts(ptr.sequence, ptr.length as usize))
923            }),
924            TangoDataType::LongArray => Self::LongArray({
925                let ptr = data.long_arr;
926                Vec::from(slice::from_raw_parts(ptr.sequence, ptr.length as usize))
927            }),
928            TangoDataType::FloatArray => Self::FloatArray({
929                let ptr = data.float_arr;
930                Vec::from(slice::from_raw_parts(ptr.sequence, ptr.length as usize))
931            }),
932            TangoDataType::DoubleArray => Self::DoubleArray({
933                let ptr = data.double_arr;
934                Vec::from(slice::from_raw_parts(ptr.sequence, ptr.length as usize))
935            }),
936            TangoDataType::UShortArray => Self::UShortArray({
937                let ptr = data.ushort_arr;
938                Vec::from(slice::from_raw_parts(ptr.sequence, ptr.length as usize))
939            }),
940            TangoDataType::ULongArray => Self::ULongArray({
941                let ptr = data.ulong_arr;
942                Vec::from(slice::from_raw_parts(ptr.sequence, ptr.length as usize))
943            }),
944            TangoDataType::StringArray => Self::StringArray({
945                let ptr = data.string_arr;
946                let mut res = Vec::with_capacity(ptr.length as usize);
947                for i in 0..ptr.length {
948                    let raw = *ptr.sequence.offset(i as isize);
949                    let len = libc::strlen(raw);
950                    res.push(Vec::from(slice::from_raw_parts(raw as *mut u8, len)));
951                }
952                res
953            }),
954            TangoDataType::LongStringArray => {
955                let ptr = data.long_string_arr;
956                let mut strvec = Vec::with_capacity(ptr.string_length as usize);
957                for i in 0..ptr.string_length {
958                    let raw = *ptr.string_sequence.offset(i as isize);
959                    let len = libc::strlen(raw);
960                    strvec.push(Vec::from(slice::from_raw_parts(raw as *mut u8, len)));
961                }
962                Self::LongStringArray(
963                    Vec::from(slice::from_raw_parts(ptr.long_sequence, ptr.long_length as usize)),
964                    strvec
965                )
966            },
967            TangoDataType::DoubleStringArray => {
968                let ptr = data.double_string_arr;
969                let mut strvec = Vec::with_capacity(ptr.string_length as usize);
970                for i in 0..ptr.string_length {
971                    let raw = *ptr.string_sequence.offset(i as isize);
972                    let len = libc::strlen(raw);
973                    strvec.push(Vec::from(slice::from_raw_parts(raw as *mut u8, len)));
974                }
975                Self::DoubleStringArray(
976                    Vec::from(slice::from_raw_parts(ptr.double_sequence, ptr.double_length as usize)),
977                    strvec
978                )
979            },
980            TangoDataType::BooleanArray => Self::BooleanArray({
981                let ptr = data.bool_arr;
982                Vec::from(slice::from_raw_parts(ptr.sequence, ptr.length as usize))
983            }),
984            TangoDataType::Long64Array => Self::Long64Array({
985                let ptr = data.long64_arr;
986                Vec::from(slice::from_raw_parts(ptr.sequence, ptr.length as usize))
987            }),
988            TangoDataType::ULong64Array => Self::ULong64Array({
989                let ptr = data.ulong64_arr;
990                Vec::from(slice::from_raw_parts(ptr.sequence, ptr.length as usize))
991            }),
992            TangoDataType::Encoded => {
993                let ptr = data.encoded_val;
994                let format = string_from(ptr.encoded_format);
995                Self::Encoded((
996                    format,
997                    Vec::from(slice::from_raw_parts(ptr.encoded_data, ptr.encoded_length as usize))))
998            },
999        };
1000        c::tango_free_CommandData(&mut cmd_data);
1001        res
1002    }
1003
1004    pub(crate) unsafe fn into_c(self) -> c::CommandData {
1005        let mut content = mem::zeroed::<c::TangoCommandData>();
1006
1007        macro_rules! impl_array {
1008            ($val:ident, $alt:ident, $arr:ident, $ctype:ty) => {
1009                {
1010                    let array = &mut content.$arr;
1011                    array.length = $val.len() as u32;
1012                    array.sequence = Box::into_raw($val.into_boxed_slice()) as *mut $ctype;
1013                    TangoDataType::$alt
1014                }
1015            }
1016        }
1017
1018        let tag = match self {
1019            Self::Void => {
1020                TangoDataType::Void
1021            }
1022            Self::Boolean(v) => {
1023                content.bool_val = v;
1024                TangoDataType::Boolean
1025            }
1026            Self::Short(v) => {
1027                content.short_val = v;
1028                TangoDataType::Short
1029            }
1030            Self::Long(v) => {
1031                content.long_val = v;
1032                TangoDataType::Long
1033            }
1034            Self::Float(v) => {
1035                content.float_val = v;
1036                TangoDataType::Float
1037            }
1038            Self::Double(v) => {
1039                content.double_val = v;
1040                TangoDataType::Double
1041            }
1042            Self::UShort(v) => {
1043                content.ushort_val = v;
1044                TangoDataType::UShort
1045            }
1046            Self::ULong(v) => {
1047                content.ulong_val = v;
1048                TangoDataType::ULong
1049            }
1050            Self::Long64(v) => {
1051                content.long64_val = v;
1052                TangoDataType::Long64
1053            }
1054            Self::ULong64(v) => {
1055                content.ulong64_val = v;
1056                TangoDataType::ULong64
1057            }
1058            Self::String(v) => {
1059                let cstr = cstring_from(v);
1060                content.string_val = cstr.into_raw();
1061                TangoDataType::String
1062            }
1063            Self::Encoded((format, data)) => {
1064                let ptr = &mut content.encoded_val;
1065                ptr.encoded_format = cstring_from(format).into_raw();
1066                ptr.encoded_length = data.len() as u32;
1067                ptr.encoded_data = Box::into_raw(data.into_boxed_slice()) as *mut u8;
1068                TangoDataType::Encoded
1069            }
1070            Self::BooleanArray(v) => impl_array!(v, BooleanArray, bool_arr, bool),
1071            Self::CharArray(v) => impl_array!(v, CharArray, char_arr, u8),
1072            Self::ShortArray(v) => impl_array!(v, ShortArray, short_arr, i16),
1073            Self::UShortArray(v) => impl_array!(v, UShortArray, ushort_arr, u16),
1074            Self::LongArray(v) => impl_array!(v, LongArray, long_arr, i32),
1075            Self::ULongArray(v) => impl_array!(v, ULongArray, ulong_arr, u32),
1076            Self::Long64Array(v) => impl_array!(v, Long64Array, long64_arr, i64),
1077            Self::ULong64Array(v) => impl_array!(v, ULong64Array, ulong64_arr, u64),
1078            Self::FloatArray(v) => impl_array!(v, FloatArray, float_arr, f32),
1079            Self::DoubleArray(v) => impl_array!(v, DoubleArray, double_arr, f64),
1080            Self::StringArray(v) => {
1081                let array = &mut content.string_arr;
1082                let mut vec = Vec::with_capacity(v.len());
1083                array.length = v.len() as u32;
1084                for s in v.into_iter() {
1085                    vec.push(cstring_from(s).into_raw());
1086                }
1087                array.sequence = Box::into_raw(vec.into_boxed_slice()) as *mut *mut c_char;
1088                TangoDataType::StringArray
1089            },
1090            Self::LongStringArray(vl, vs) => {
1091                let array = &mut content.long_string_arr;
1092                array.long_length = vl.len() as u32;
1093                array.long_sequence = Box::into_raw(vl.into_boxed_slice()) as *mut i32;
1094                let mut vec = Vec::with_capacity(vs.len());
1095                array.string_length = vs.len() as u32;
1096                for s in vs.into_iter() {
1097                    vec.push(cstring_from(s).into_raw());
1098                }
1099                array.string_sequence = Box::into_raw(vec.into_boxed_slice()) as *mut *mut c_char;
1100                TangoDataType::LongStringArray
1101            },
1102            Self::DoubleStringArray(vd, vs) => {
1103                let array = &mut content.double_string_arr;
1104                array.double_length = vd.len() as u32;
1105                array.double_sequence = Box::into_raw(vd.into_boxed_slice()) as *mut f64;
1106                let mut vec = Vec::with_capacity(vs.len());
1107                array.string_length = vs.len() as u32;
1108                for s in vs.into_iter() {
1109                    vec.push(cstring_from(s).into_raw());
1110                }
1111                array.string_sequence = Box::into_raw(vec.into_boxed_slice()) as *mut *mut c_char;
1112                TangoDataType::DoubleStringArray
1113            },
1114            Self::State(_) => panic!("Cannot send input argument of type State")
1115        };
1116        c::CommandData { arg_type: tag as u32, cmd_data: content }
1117    }
1118
1119    pub(crate) unsafe fn free_c_data(cmd_data: c::CommandData) {
1120        let data = cmd_data.cmd_data;
1121        match TangoDataType::from_c(cmd_data.arg_type) {
1122            TangoDataType::Void |
1123            TangoDataType::Boolean |
1124            TangoDataType::UChar |
1125            TangoDataType::Short |
1126            TangoDataType::Long |
1127            TangoDataType::Int |
1128            TangoDataType::Float |
1129            TangoDataType::Double |
1130            TangoDataType::UShort |
1131            TangoDataType::ULong |
1132            TangoDataType::Long64 |
1133            TangoDataType::ULong64 |
1134            TangoDataType::State => {}
1135            TangoDataType::String | TangoDataType::ConstString => {
1136                drop(CString::from_raw(data.string_val));
1137            }
1138            TangoDataType::Encoded => {
1139                drop(CString::from_raw(data.encoded_val.encoded_format));
1140                drop(Box::from_raw(data.encoded_val.encoded_data));
1141            }
1142            TangoDataType::BooleanArray => drop(Box::from_raw(data.bool_arr.sequence)),
1143            TangoDataType::CharArray => drop(Box::from_raw(data.char_arr.sequence)),
1144            TangoDataType::ShortArray => drop(Box::from_raw(data.short_arr.sequence)),
1145            TangoDataType::UShortArray => drop(Box::from_raw(data.ushort_arr.sequence)),
1146            TangoDataType::LongArray => drop(Box::from_raw(data.long_arr.sequence)),
1147            TangoDataType::ULongArray => drop(Box::from_raw(data.ulong_arr.sequence)),
1148            TangoDataType::Long64Array => drop(Box::from_raw(data.long64_arr.sequence)),
1149            TangoDataType::ULong64Array => drop(Box::from_raw(data.ulong64_arr.sequence)),
1150            TangoDataType::FloatArray => drop(Box::from_raw(data.float_arr.sequence)),
1151            TangoDataType::DoubleArray => drop(Box::from_raw(data.double_arr.sequence)),
1152            TangoDataType::StringArray => {
1153                for i in 0..data.string_arr.length {
1154                    drop(CString::from_raw(*data.string_arr.sequence.offset(i as isize) as *mut c_char));
1155                }
1156                drop(Box::from_raw(data.string_arr.sequence));
1157            }
1158            TangoDataType::LongStringArray => {
1159                for i in 0..data.long_string_arr.string_length {
1160                    drop(CString::from_raw(*data.long_string_arr
1161                                           .string_sequence.offset(i as isize) as *mut c_char));
1162                }
1163                drop(Box::from_raw(data.long_string_arr.string_sequence));
1164                drop(Box::from_raw(data.long_string_arr.long_sequence));
1165            }
1166            TangoDataType::DoubleStringArray => {
1167                for i in 0..data.double_string_arr.string_length {
1168                    drop(CString::from_raw(*data.double_string_arr
1169                                           .string_sequence.offset(i as isize) as *mut c_char));
1170                }
1171                drop(Box::from_raw(data.double_string_arr.string_sequence));
1172                drop(Box::from_raw(data.double_string_arr.double_sequence));
1173            }
1174        }
1175    }
1176}
1177
1178impl fmt::Display for CommandData {
1179    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1180        match self {
1181            Self::Void => f.pad("<Void>"),
1182            Self::Boolean(v) => fmt::Display::fmt(&v, f),
1183            Self::Short(v) => fmt::Display::fmt(&v, f),
1184            Self::UShort(v) => fmt::Display::fmt(&v, f),
1185            Self::Long(v) => fmt::Display::fmt(&v, f),
1186            Self::ULong(v) => fmt::Display::fmt(&v, f),
1187            Self::Long64(v) => fmt::Display::fmt(&v, f),
1188            Self::ULong64(v) => fmt::Display::fmt(&v, f),
1189            Self::Float(v) => fmt::Display::fmt(&v, f),
1190            Self::Double(v) => fmt::Display::fmt(&v, f),
1191            Self::String(v) => fmt::Display::fmt(&String::from_utf8_lossy(v), f),
1192            Self::State(v) => fmt::Display::fmt(&v, f),
1193            Self::Encoded(_) => f.pad("<DevEncoded>"),
1194
1195            Self::BooleanArray(v) => slice_display(v, |x| x, f),
1196            Self::CharArray(v) => slice_display(v, |x| x, f),
1197            Self::ShortArray(v) => slice_display(v, |x| x, f),
1198            Self::UShortArray(v) => slice_display(v, |x| x, f),
1199            Self::LongArray(v) => slice_display(v, |x| x, f),
1200            Self::ULongArray(v) => slice_display(v, |x| x, f),
1201            Self::Long64Array(v) => slice_display(v, |x| x, f),
1202            Self::ULong64Array(v) => slice_display(v, |x| x, f),
1203            Self::FloatArray(v) => slice_display(v, |x| x, f),
1204            Self::DoubleArray(v) => slice_display(v, |x| x, f),
1205            Self::StringArray(v) => slice_display(v, |x| String::from_utf8_lossy(x), f),
1206            Self::LongStringArray(vi, vs) => {
1207                slice_display(vi, |x| x, f)?;
1208                slice_display(vs, |x| String::from_utf8_lossy(x), f)
1209            },
1210            Self::DoubleStringArray(vd, vs) => {
1211                slice_display(vd, |x| x, f)?;
1212                slice_display(vs, |x| String::from_utf8_lossy(x), f)
1213            },
1214        }
1215    }
1216}
1217
1218impl fmt::LowerHex for CommandData {
1219    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1220        match self {
1221            Self::Void => f.pad("<Void>"),
1222            Self::Boolean(v) => fmt::Display::fmt(&v, f),
1223            Self::Short(v) => fmt::LowerHex::fmt(&v, f),
1224            Self::UShort(v) => fmt::LowerHex::fmt(&v, f),
1225            Self::Long(v) => fmt::LowerHex::fmt(&v, f),
1226            Self::ULong(v) => fmt::LowerHex::fmt(&v, f),
1227            Self::Long64(v) => fmt::LowerHex::fmt(&v, f),
1228            Self::ULong64(v) => fmt::LowerHex::fmt(&v, f),
1229            Self::Float(v) => fmt::Display::fmt(&v, f),
1230            Self::Double(v) => fmt::Display::fmt(&v, f),
1231            Self::String(v) => fmt::Display::fmt(&String::from_utf8_lossy(v), f),
1232            Self::State(v) => fmt::Display::fmt(&v, f),
1233            Self::Encoded(_) => f.pad("<DevEncoded>"),
1234
1235            Self::BooleanArray(v) => slice_display(v, |x| x, f),
1236            Self::CharArray(v) => slice_lower_hex(v, |x| x, f),
1237            Self::ShortArray(v) => slice_lower_hex(v, |x| x, f),
1238            Self::UShortArray(v) => slice_lower_hex(v, |x| x, f),
1239            Self::LongArray(v) => slice_lower_hex(v, |x| x, f),
1240            Self::ULongArray(v) => slice_lower_hex(v, |x| x, f),
1241            Self::Long64Array(v) => slice_lower_hex(v, |x| x, f),
1242            Self::ULong64Array(v) => slice_lower_hex(v, |x| x, f),
1243            Self::FloatArray(v) => slice_display(v, |x| x, f),
1244            Self::DoubleArray(v) => slice_display(v, |x| x, f),
1245            Self::StringArray(v) => slice_display(v, |x| String::from_utf8_lossy(x), f),
1246            Self::LongStringArray(vi, vs) => {
1247                slice_lower_hex(vi, |x| x, f)?;
1248                slice_display(vs, |x| String::from_utf8_lossy(x), f)
1249            },
1250            Self::DoubleStringArray(vd, vs) => {
1251                slice_display(vd, |x| x, f)?;
1252                slice_display(vs, |x| String::from_utf8_lossy(x), f)
1253            },
1254        }
1255    }
1256}
1257
1258impl fmt::UpperHex for CommandData {
1259    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1260        match self {
1261            Self::Void => f.pad("<Void>"),
1262            Self::Boolean(v) => fmt::Display::fmt(&v, f),
1263            Self::Short(v) => fmt::UpperHex::fmt(&v, f),
1264            Self::UShort(v) => fmt::UpperHex::fmt(&v, f),
1265            Self::Long(v) => fmt::UpperHex::fmt(&v, f),
1266            Self::ULong(v) => fmt::UpperHex::fmt(&v, f),
1267            Self::Long64(v) => fmt::UpperHex::fmt(&v, f),
1268            Self::ULong64(v) => fmt::UpperHex::fmt(&v, f),
1269            Self::Float(v) => fmt::Display::fmt(&v, f),
1270            Self::Double(v) => fmt::Display::fmt(&v, f),
1271            Self::String(v) => fmt::Display::fmt(&String::from_utf8_lossy(v), f),
1272            Self::State(v) => fmt::Display::fmt(&v, f),
1273            Self::Encoded(_) => f.pad("<DevEncoded>"),
1274
1275            Self::BooleanArray(v) => slice_display(v, |x| x, f),
1276            Self::CharArray(v) => slice_upper_hex(v, |x| x, f),
1277            Self::ShortArray(v) => slice_upper_hex(v, |x| x, f),
1278            Self::UShortArray(v) => slice_upper_hex(v, |x| x, f),
1279            Self::LongArray(v) => slice_upper_hex(v, |x| x, f),
1280            Self::ULongArray(v) => slice_upper_hex(v, |x| x, f),
1281            Self::Long64Array(v) => slice_upper_hex(v, |x| x, f),
1282            Self::ULong64Array(v) => slice_upper_hex(v, |x| x, f),
1283            Self::FloatArray(v) => slice_display(v, |x| x, f),
1284            Self::DoubleArray(v) => slice_display(v, |x| x, f),
1285            Self::StringArray(v) => slice_display(v, |x| String::from_utf8_lossy(x), f),
1286            Self::LongStringArray(vi, vs) => {
1287                slice_upper_hex(vi, |x| x, f)?;
1288                slice_display(vs, |x| String::from_utf8_lossy(x), f)
1289            },
1290            Self::DoubleStringArray(vd, vs) => {
1291                slice_display(vd, |x| x, f)?;
1292                slice_display(vs, |x| String::from_utf8_lossy(x), f)
1293            },
1294        }
1295    }
1296}
1297
1298impl fmt::LowerExp for CommandData {
1299    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1300        match self {
1301            Self::Void => f.pad("<Void>"),
1302            Self::Boolean(v) => fmt::Display::fmt(&v, f),
1303            Self::Short(v) => fmt::Display::fmt(&v, f),
1304            Self::UShort(v) => fmt::Display::fmt(&v, f),
1305            Self::Long(v) => fmt::Display::fmt(&v, f),
1306            Self::ULong(v) => fmt::Display::fmt(&v, f),
1307            Self::Long64(v) => fmt::Display::fmt(&v, f),
1308            Self::ULong64(v) => fmt::Display::fmt(&v, f),
1309            Self::Float(v) => fmt::LowerExp::fmt(&v, f),
1310            Self::Double(v) => fmt::LowerExp::fmt(&v, f),
1311            Self::String(v) => fmt::Display::fmt(&String::from_utf8_lossy(v), f),
1312            Self::State(v) => fmt::Display::fmt(&v, f),
1313            Self::Encoded(_) => f.pad("<DevEncoded>"),
1314
1315            Self::BooleanArray(v) => slice_display(v, |x| x, f),
1316            Self::CharArray(v) => slice_display(v, |x| x, f),
1317            Self::ShortArray(v) => slice_display(v, |x| x, f),
1318            Self::UShortArray(v) => slice_display(v, |x| x, f),
1319            Self::LongArray(v) => slice_display(v, |x| x, f),
1320            Self::ULongArray(v) => slice_display(v, |x| x, f),
1321            Self::Long64Array(v) => slice_display(v, |x| x, f),
1322            Self::ULong64Array(v) => slice_display(v, |x| x, f),
1323            Self::FloatArray(v) => slice_lower_exp(v, |x| x, f),
1324            Self::DoubleArray(v) => slice_lower_exp(v, |x| x, f),
1325            Self::StringArray(v) => slice_display(v, |x| String::from_utf8_lossy(x), f),
1326            Self::LongStringArray(vi, vs) => {
1327                slice_display(vi, |x| x, f)?;
1328                slice_display(vs, |x| String::from_utf8_lossy(x), f)
1329            },
1330            Self::DoubleStringArray(vd, vs) => {
1331                slice_lower_exp(vd, |x| x, f)?;
1332                slice_display(vs, |x| String::from_utf8_lossy(x), f)
1333            },
1334        }
1335    }
1336}
1337
1338impl fmt::UpperExp for CommandData {
1339    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1340        match self {
1341            Self::Void => f.pad("<Void>"),
1342            Self::Boolean(v) => fmt::Display::fmt(&v, f),
1343            Self::Short(v) => fmt::Display::fmt(&v, f),
1344            Self::UShort(v) => fmt::Display::fmt(&v, f),
1345            Self::Long(v) => fmt::Display::fmt(&v, f),
1346            Self::ULong(v) => fmt::Display::fmt(&v, f),
1347            Self::Long64(v) => fmt::Display::fmt(&v, f),
1348            Self::ULong64(v) => fmt::Display::fmt(&v, f),
1349            Self::Float(v) => fmt::UpperExp::fmt(&v, f),
1350            Self::Double(v) => fmt::UpperExp::fmt(&v, f),
1351            Self::String(v) => fmt::Display::fmt(&String::from_utf8_lossy(v), f),
1352            Self::State(v) => fmt::Display::fmt(&v, f),
1353            Self::Encoded(_) => f.pad("<DevEncoded>"),
1354
1355            Self::BooleanArray(v) => slice_display(v, |x| x, f),
1356            Self::CharArray(v) => slice_display(v, |x| x, f),
1357            Self::ShortArray(v) => slice_display(v, |x| x, f),
1358            Self::UShortArray(v) => slice_display(v, |x| x, f),
1359            Self::LongArray(v) => slice_display(v, |x| x, f),
1360            Self::ULongArray(v) => slice_display(v, |x| x, f),
1361            Self::Long64Array(v) => slice_display(v, |x| x, f),
1362            Self::ULong64Array(v) => slice_display(v, |x| x, f),
1363            Self::FloatArray(v) => slice_upper_exp(v, |x| x, f),
1364            Self::DoubleArray(v) => slice_upper_exp(v, |x| x, f),
1365            Self::StringArray(v) => slice_display(v, |x| String::from_utf8_lossy(x), f),
1366            Self::LongStringArray(vi, vs) => {
1367                slice_display(vi, |x| x, f)?;
1368                slice_display(vs, |x| String::from_utf8_lossy(x), f)
1369            },
1370            Self::DoubleStringArray(vd, vs) => {
1371                slice_upper_exp(vd, |x| x, f)?;
1372                slice_display(vs, |x| String::from_utf8_lossy(x), f)
1373            },
1374        }
1375    }
1376}
1377
1378
1379/// Provides information about a single device attribute.
1380#[derive(Debug)]
1381pub struct AttributeInfo {
1382    pub name: String,
1383    pub writable: AttrWriteType,
1384    pub data_type: TangoDataType,
1385    pub data_format: AttrDataFormat,
1386    pub max_dim_x: usize,
1387    pub max_dim_y: usize,
1388    pub description: String,
1389    pub label: String,
1390    pub unit: String,
1391    pub standard_unit: String,
1392    pub display_unit: String,
1393    pub format: String,
1394    pub min_value: String,
1395    pub max_value: String,
1396    pub min_alarm: String,
1397    pub max_alarm: String,
1398    pub writable_attr_name: String,
1399    pub disp_level: DispLevel,
1400}
1401
1402impl AttributeInfo {
1403    pub(crate) unsafe fn from_c(info: c::AttributeInfo) -> AttributeInfo {
1404        AttributeInfo {
1405            name: string_from(info.name),
1406            writable: AttrWriteType::from_c(info.writable),
1407            data_type: TangoDataType::from_c(info.data_type),
1408            data_format: AttrDataFormat::from_c(info.data_format),
1409            max_dim_x: info.max_dim_x as usize,
1410            max_dim_y: info.max_dim_y as usize,
1411            description: string_from(info.description),
1412            label: string_from(info.label),
1413            unit: string_from(info.unit),
1414            standard_unit: string_from(info.standard_unit),
1415            display_unit: string_from(info.display_unit),
1416            format: string_from(info.format),
1417            min_value: string_from(info.min_value),
1418            max_value: string_from(info.max_value),
1419            min_alarm: string_from(info.min_alarm),
1420            max_alarm: string_from(info.max_alarm),
1421            writable_attr_name: string_from(info.writable_attr_name),
1422            disp_level: DispLevel::from_c(info.disp_level),
1423        }
1424    }
1425}
1426
1427
1428/// Represents the value and other metadata of a device attribute.
1429#[derive(Debug, Clone, PartialEq)]
1430pub struct AttributeData {
1431    pub data: AttrValue,
1432    pub written_data: Option<AttrValue>,
1433    pub format: AttrDataFormat,
1434    pub quality: AttrQuality,
1435    pub name: String,
1436    pub dim_x: usize,
1437    pub dim_y: usize,
1438    pub time_stamp: Timespec,
1439}
1440
1441impl AttributeData {
1442    /// Create a "simple" attribute data suitable for writing the attribute
1443    /// `name` to a given value.
1444    pub fn simple(name: &str, data: AttrValue) -> AttributeData {
1445        AttributeData {
1446            dim_x: data.len(),
1447            dim_y: 0,
1448            data,
1449            written_data: None,              // doesn't actually matter for writing
1450            format: AttrDataFormat::Scalar,  // doesn't actually matter for writing
1451            quality: AttrQuality::Valid,
1452            name: name.into(),
1453            time_stamp: get_time(),
1454        }
1455    }
1456
1457    pub(crate) unsafe fn from_c(mut attr_data: c::AttributeData, free: bool) -> AttributeData {
1458        use AttrValue::*;
1459
1460        let tag = TangoDataType::from_c(attr_data.data_type);
1461        let data = attr_data.attr_data;
1462        let is_scalar = AttrDataFormat::from_c(attr_data.data_format) == AttrDataFormat::Scalar;
1463        let (res_read, res_written) = if is_scalar {
1464            macro_rules! impl_simple {
1465                ($alt:ident, $arr:ident) => {
1466                    {
1467                        let ptr = data.$arr;
1468                        if ptr.length == 1 {
1469                            ($alt(*ptr.sequence), $alt(Default::default()))
1470                        } else {
1471                            ($alt(*ptr.sequence), $alt(*ptr.sequence.offset(1)))
1472                        }
1473                    }
1474                }
1475            }
1476
1477            match tag {
1478                TangoDataType::UChar => impl_simple!(UChar, char_arr),
1479                TangoDataType::Short => impl_simple!(Short, short_arr),
1480                TangoDataType::UShort => impl_simple!(UShort, ushort_arr),
1481                TangoDataType::Long => impl_simple!(Long, long_arr),
1482                TangoDataType::ULong => impl_simple!(ULong, ulong_arr),
1483                TangoDataType::Long64 => impl_simple!(Long64, long64_arr),
1484                TangoDataType::ULong64 => impl_simple!(ULong64, ulong64_arr),
1485                TangoDataType::Float => impl_simple!(Float, float_arr),
1486                TangoDataType::Double => impl_simple!(Double, double_arr),
1487                TangoDataType::Boolean => impl_simple!(Boolean, bool_arr),
1488                TangoDataType::State => {
1489                    let r = TangoDevState::from_c(*data.state_arr.sequence);
1490                    let w = if data.string_arr.length == 1 {
1491                        TangoDevState::Unknown
1492                    } else {
1493                        TangoDevState::from_c(*data.state_arr.sequence.offset(1))
1494                    };
1495                    (State(r), State(w))
1496                }
1497                TangoDataType::String => {
1498                    let rawr = *data.string_arr.sequence;
1499                    let lenr = libc::strlen(rawr);
1500                    let r = Vec::from(slice::from_raw_parts(rawr as *mut u8, lenr));
1501                    let w = if data.string_arr.length == 1 {
1502                        Vec::new()
1503                    } else {
1504                        let raww = *data.string_arr.sequence.offset(1);
1505                        let lenw = libc::strlen(raww);
1506                        Vec::from(slice::from_raw_parts(raww as *mut u8, lenw))
1507                    };
1508                    (String(r), String(w))
1509                },
1510                TangoDataType::Encoded => {
1511                    let rawr = *data.encoded_arr.sequence;
1512                    let r = (string_from(rawr.encoded_format),
1513                             Vec::from(slice::from_raw_parts(rawr.encoded_data as *mut u8,
1514                                                             rawr.encoded_length as usize)));
1515                    let w = if data.string_arr.length == 1 {
1516                        ("".into(), Vec::new())
1517                    } else {
1518                        let raww = *data.encoded_arr.sequence.offset(1);
1519                        (string_from(raww.encoded_format),
1520                         Vec::from(slice::from_raw_parts(raww.encoded_data as *mut u8,
1521                                                         raww.encoded_length as usize)))
1522                    };
1523                    (Encoded(r), Encoded(w))
1524                },
1525                _ => panic!("data type {:?} not allowed for attributes", tag)
1526            }
1527        } else {
1528            macro_rules! impl_simple {
1529                ($alt:ident, $arr:ident) => {
1530                    {
1531                        let ptr = data.$arr;
1532                        let slice = slice::from_raw_parts(ptr.sequence, ptr.length as usize);
1533                        let (p1, p2) = slice.split_at(attr_data.nb_read as usize);
1534                        ($alt(Vec::from(p1)), $alt(Vec::from(p2)))
1535                    }
1536                }
1537            }
1538
1539            match tag {
1540                TangoDataType::UChar => impl_simple!(UCharArray, char_arr),
1541                TangoDataType::Short => impl_simple!(ShortArray, short_arr),
1542                TangoDataType::UShort => impl_simple!(UShortArray, ushort_arr),
1543                TangoDataType::Long => impl_simple!(LongArray, long_arr),
1544                TangoDataType::ULong => impl_simple!(ULongArray, ulong_arr),
1545                TangoDataType::Long64 => impl_simple!(Long64Array, long64_arr),
1546                TangoDataType::ULong64 => impl_simple!(ULong64Array, ulong64_arr),
1547                TangoDataType::Float => impl_simple!(FloatArray, float_arr),
1548                TangoDataType::Double => impl_simple!(DoubleArray, double_arr),
1549                TangoDataType::Boolean => impl_simple!(BooleanArray, bool_arr),
1550                TangoDataType::State => {
1551                    let ptr = data.state_arr;
1552                    let slice = slice::from_raw_parts(ptr.sequence, ptr.length as usize);
1553                    let (p1, p2) = slice.split_at(attr_data.nb_read as usize);
1554                    (StateArray(p1.iter().map(|&v| TangoDevState::from_c(v)).collect()),
1555                     StateArray(p2.iter().map(|&v| TangoDevState::from_c(v)).collect()))
1556                },
1557                TangoDataType::String => {
1558                    let ptr = data.string_arr;
1559                    let mut res = Vec::with_capacity(ptr.length as usize);
1560                    for i in 0..ptr.length {
1561                        let raw = *ptr.sequence.offset(i as isize);
1562                        let len = libc::strlen(raw);
1563                        res.push(Vec::from(slice::from_raw_parts(raw as *mut u8, len)));
1564                    }
1565                    let res2 = res.split_off(attr_data.nb_read as usize);
1566                    (StringArray(res), StringArray(res2))
1567                },
1568                TangoDataType::Encoded => {
1569                    let ptr = data.encoded_arr;
1570                    let mut res = Vec::with_capacity(ptr.length as usize);
1571                    for i in 0..ptr.length {
1572                        let raw = *ptr.sequence.offset(i as isize);
1573                        res.push((string_from(raw.encoded_format),
1574                                  Vec::from(slice::from_raw_parts(raw.encoded_data as *mut u8,
1575                                                                  raw.encoded_length as usize))));
1576                    }
1577                    let res2 = res.split_off(attr_data.nb_read as usize);
1578                    (EncodedArray(res), EncodedArray(res2))
1579                },
1580                _ => panic!("data type {:?} not allowed for attributes", tag)
1581            }
1582        };
1583        let res = AttributeData {
1584            data: res_read,
1585            written_data: Some(res_written),
1586            format: AttrDataFormat::from_c(attr_data.data_format),
1587            quality: AttrQuality::from_c(attr_data.quality),
1588            name: string_from(attr_data.name),
1589            dim_x: attr_data.dim_x as usize,
1590            dim_y: attr_data.dim_y as usize,
1591            time_stamp: Timespec::new(attr_data.time_stamp.tv_sec.into(),
1592                                      1000 * attr_data.time_stamp.tv_usec as i32),
1593        };
1594        if free {
1595            c::tango_free_AttributeData(&mut attr_data);
1596        }
1597        res
1598    }
1599
1600    pub(crate) unsafe fn into_c(self) -> c::AttributeData {
1601        let mut content = mem::zeroed::<c::TangoAttributeData>();
1602
1603        macro_rules! impl_simple {
1604            ($val:ident, $alt:ident, $arr:ident, $ctype:ty) => {
1605                {
1606                    let array = &mut content.$arr;
1607                    array.length = 1;
1608                    array.sequence = Box::into_raw(Box::new($val)) as *mut $ctype;
1609                    TangoDataType::$alt
1610                }
1611            }
1612        }
1613
1614        macro_rules! impl_array {
1615            ($val:ident, $alt:ident, $arr:ident, $ctype:ty) => {
1616                {
1617                    let array = &mut content.$arr;
1618                    array.length = $val.len() as u32;
1619                    array.sequence = Box::into_raw($val.into_boxed_slice()) as *mut $ctype;
1620                    TangoDataType::$alt
1621                }
1622            }
1623        }
1624
1625        let tag = match self.data {
1626            AttrValue::Boolean(v) => impl_simple!(v, Boolean, bool_arr, bool),
1627            AttrValue::UChar(v) => impl_simple!(v, UChar, char_arr, u8),
1628            AttrValue::Short(v) => impl_simple!(v, Short, short_arr, i16),
1629            AttrValue::UShort(v) => impl_simple!(v, UShort, ushort_arr, u16),
1630            AttrValue::Long(v) => impl_simple!(v, Long, long_arr, i32),
1631            AttrValue::ULong(v) => impl_simple!(v, ULong, ulong_arr, u32),
1632            AttrValue::Long64(v) => impl_simple!(v, Long64, long64_arr, i64),
1633            AttrValue::ULong64(v) => impl_simple!(v, ULong64, ulong64_arr, u64),
1634            AttrValue::Float(v) => impl_simple!(v, Float, float_arr, f32),
1635            AttrValue::Double(v) => impl_simple!(v, Double, double_arr, f64),
1636            AttrValue::State(v) => impl_simple!(v, State, state_arr, c::TangoDevState),
1637            AttrValue::String(v) => {
1638                let array = &mut content.string_arr;
1639                array.length = 1;
1640                let mut vec = Vec::with_capacity(1);
1641                vec.push(cstring_from(v).into_raw());
1642                array.sequence = Box::into_raw(vec.into_boxed_slice()) as *mut *mut c_char;
1643                TangoDataType::String
1644            }
1645            AttrValue::Encoded((format, data)) => {
1646                let array = &mut content.encoded_arr;
1647                array.length = 1;
1648                let mut vec = Vec::with_capacity(1);
1649                let encoded = c::TangoDevEncoded {
1650                    encoded_format: cstring_from(format).into_raw(),
1651                    encoded_length: data.len() as u32,
1652                    encoded_data: Box::into_raw(data.into_boxed_slice()) as *mut u8,
1653                };
1654                vec.push(Box::into_raw(Box::new(encoded)));
1655                array.sequence = Box::into_raw(vec.into_boxed_slice()) as *mut c::TangoDevEncoded;
1656                TangoDataType::Encoded
1657            }
1658            AttrValue::BooleanArray(v) => impl_array!(v, Boolean, bool_arr, bool),
1659            AttrValue::UCharArray(v) => impl_array!(v, UChar, char_arr, u8),
1660            AttrValue::ShortArray(v) => impl_array!(v, Short, short_arr, i16),
1661            AttrValue::UShortArray(v) => impl_array!(v, UShort, ushort_arr, u16),
1662            AttrValue::LongArray(v) => impl_array!(v, Long, long_arr, i32),
1663            AttrValue::ULongArray(v) => impl_array!(v, ULong, ulong_arr, u32),
1664            AttrValue::Long64Array(v) => impl_array!(v, Long64, long64_arr, i64),
1665            AttrValue::ULong64Array(v) => impl_array!(v, ULong64, ulong64_arr, u64),
1666            AttrValue::FloatArray(v) => impl_array!(v, Float, float_arr, f32),
1667            AttrValue::DoubleArray(v) => impl_array!(v, Double, double_arr, f64),
1668            AttrValue::StateArray(v) => impl_array!(v, State, state_arr, c::TangoDevState),
1669            AttrValue::StringArray(v) => {
1670                let array = &mut content.string_arr;
1671                let mut vec = Vec::with_capacity(v.len());
1672                array.length = v.len() as u32;
1673                for s in v.into_iter() {
1674                    vec.push(cstring_from(s).into_raw());
1675                }
1676                array.sequence = Box::into_raw(vec.into_boxed_slice()) as *mut *mut c_char;
1677                TangoDataType::String
1678            }
1679            AttrValue::EncodedArray(v) => {
1680                let array = &mut content.encoded_arr;
1681                array.length = v.len() as u32;
1682                let mut vec = Vec::with_capacity(v.len());
1683                for (format, data) in v.into_iter() {
1684                    let encoded = c::TangoDevEncoded {
1685                        encoded_format: cstring_from(format).into_raw(),
1686                        encoded_length: data.len() as u32,
1687                        encoded_data: Box::into_raw(data.into_boxed_slice()) as *mut u8,
1688                    };
1689                    vec.push(Box::into_raw(Box::new(encoded)));
1690                }
1691                array.sequence = Box::into_raw(vec.into_boxed_slice()) as *mut c::TangoDevEncoded;
1692                TangoDataType::Encoded
1693            }
1694        };
1695        c::AttributeData {
1696            name: cstring_from(self.name).into_raw(),
1697            data_type: tag as u32,
1698            data_format: self.format as u32,
1699            attr_data: content,
1700            nb_read: 0,  // doesn't matter for writing
1701            quality: self.quality as u32,
1702            dim_x: self.dim_x as i32,
1703            dim_y: self.dim_y as i32,
1704            time_stamp: c::timeval { tv_sec: self.time_stamp.sec as c_long,
1705                                     tv_usec: self.time_stamp.nsec as c_long / 1000 }
1706        }
1707    }
1708
1709    pub(crate) unsafe fn free_c_data(attr_data: c::AttributeData) {
1710        let data = attr_data.attr_data;
1711        drop(CString::from_raw(attr_data.name));
1712        match TangoDataType::from_c(attr_data.data_type) {
1713            TangoDataType::Boolean => drop(Box::from_raw(data.bool_arr.sequence)),
1714            TangoDataType::UChar => drop(Box::from_raw(data.char_arr.sequence)),
1715            TangoDataType::Short => drop(Box::from_raw(data.short_arr.sequence)),
1716            TangoDataType::UShort => drop(Box::from_raw(data.ushort_arr.sequence)),
1717            TangoDataType::Long => drop(Box::from_raw(data.long_arr.sequence)),
1718            TangoDataType::ULong => drop(Box::from_raw(data.ulong_arr.sequence)),
1719            TangoDataType::Long64 => drop(Box::from_raw(data.long64_arr.sequence)),
1720            TangoDataType::ULong64 => drop(Box::from_raw(data.ulong64_arr.sequence)),
1721            TangoDataType::Float => drop(Box::from_raw(data.float_arr.sequence)),
1722            TangoDataType::Double => drop(Box::from_raw(data.double_arr.sequence)),
1723            TangoDataType::State => drop(Box::from_raw(data.state_arr.sequence)),
1724            TangoDataType::String => {
1725                for i in 0..data.string_arr.length {
1726                    drop(CString::from_raw(*data.string_arr.sequence.offset(i as isize) as *mut c_char));
1727                }
1728                drop(Box::from_raw(data.string_arr.sequence));
1729            }
1730            TangoDataType::Encoded => {
1731                for i in 0..data.encoded_arr.length {
1732                    let ptr = data.encoded_arr.sequence.offset(i as isize) as *mut c::TangoDevEncoded;
1733                    drop(CString::from_raw((*ptr).encoded_format as *mut c_char));
1734                    drop(Box::from_raw((*ptr).encoded_data));
1735                }
1736                drop(Box::from_raw(data.encoded_arr.sequence));
1737            }
1738            val => panic!("invalid attribute data tag={:?}", val)
1739        }
1740    }
1741}
1742
1743
1744/// Represents the value of an attribute.
1745///
1746/// The normal way to construct this is to use the desired variant directly.
1747#[derive(Debug, Clone, PartialEq)]
1748pub enum AttrValue {
1749    Boolean(bool),
1750    UChar(u8),
1751    Short(i16),
1752    UShort(u16),
1753    Long(i32),
1754    ULong(u32),
1755    Long64(i64),
1756    ULong64(u64),
1757
1758    Float(f32),
1759    Double(f64),
1760
1761    String(Vec<u8>),
1762    State(TangoDevState),
1763    Encoded(DevEncoded),
1764
1765    BooleanArray(Vec<bool>),
1766    UCharArray(Vec<u8>),
1767    ShortArray(Vec<i16>),
1768    UShortArray(Vec<u16>),
1769    LongArray(Vec<i32>),
1770    ULongArray(Vec<u32>),
1771    Long64Array(Vec<i64>),
1772    ULong64Array(Vec<u64>),
1773
1774    FloatArray(Vec<f32>),
1775    DoubleArray(Vec<f64>),
1776
1777    StringArray(Vec<Vec<u8>>),
1778    StateArray(Vec<TangoDevState>),
1779    EncodedArray(Vec<DevEncoded>),
1780}
1781
1782impl AttrValue {
1783    /// Return the number of items in this value.
1784    ///
1785    /// 1 for simple values, the length for arrays.
1786    pub fn len(&self) -> usize {
1787        match self {
1788            Self::Boolean(_) |
1789            Self::UChar(_) |
1790            Self::Short(_) |
1791            Self::UShort(_) |
1792            Self::Long(_) |
1793            Self::ULong(_) |
1794            Self::Long64(_) |
1795            Self::ULong64(_) |
1796            Self::Float(_) |
1797            Self::Double(_) |
1798            Self::String(_) |
1799            Self::State(_) |
1800            Self::Encoded(_) => 1,
1801
1802            Self::BooleanArray(v) => v.len(),
1803            Self::UCharArray(v) => v.len(),
1804            Self::ShortArray(v) => v.len(),
1805            Self::UShortArray(v) => v.len(),
1806            Self::LongArray(v) => v.len(),
1807            Self::ULongArray(v) => v.len(),
1808            Self::Long64Array(v) => v.len(),
1809            Self::ULong64Array(v) => v.len(),
1810            Self::FloatArray(v) => v.len(),
1811            Self::DoubleArray(v) => v.len(),
1812            Self::StringArray(v) => v.len(),
1813            Self::StateArray(v) => v.len(),
1814            Self::EncodedArray(v) => v.len(),
1815        }
1816    }
1817
1818    /// Try to convert this data into a different type.
1819    ///
1820    /// If the conversion fails or is impossible, `Self` is returned unchanged
1821    /// in the `Err` variant.
1822    pub fn convert(self, to: TangoDataType) -> Result<Self, Self> {
1823        match self {
1824            Self::Boolean(v) => match to {
1825                TangoDataType::Boolean => Ok(self),
1826                TangoDataType::UChar => Ok(Self::UChar(v as _)),
1827                TangoDataType::Short => Ok(Self::Short(v as _)),
1828                TangoDataType::UShort => Ok(Self::UShort(v as _)),
1829                TangoDataType::Int |
1830                TangoDataType::Long => Ok(Self::Long(v as _)),
1831                TangoDataType::ULong => Ok(Self::ULong(v as _)),
1832                TangoDataType::Long64 => Ok(Self::Long64(v as _)),
1833                TangoDataType::ULong64 => Ok(Self::ULong64(v as _)),
1834                TangoDataType::Float => Ok(Self::Float(v as i32 as _)),
1835                TangoDataType::Double => Ok(Self::Double(v as i32 as _)),
1836                _ => Err(self)
1837            }
1838            Self::UChar(v) => match to {
1839                TangoDataType::Boolean => check_bool(v as i64).map(Self::Boolean).map_err(|_| self),
1840                TangoDataType::UChar => Ok(self),
1841                TangoDataType::Short => Ok(Self::Short(v as _)),
1842                TangoDataType::UShort => Ok(Self::Short(v as _)),
1843                TangoDataType::Int |
1844                TangoDataType::Long => Ok(Self::Long(v as _)),
1845                TangoDataType::ULong => Ok(Self::ULong(v as _)),
1846                TangoDataType::Long64 => Ok(Self::Long64(v as _)),
1847                TangoDataType::ULong64 => Ok(Self::ULong64(v as _)),
1848                TangoDataType::Float => Ok(Self::Float(v as _)),
1849                TangoDataType::Double => Ok(Self::Double(v as _)),
1850                _ => Err(self)
1851            }
1852            Self::Short(v) => match to {
1853                TangoDataType::Boolean => check_bool(v as i64).map(Self::Boolean).map_err(|_| self),
1854                TangoDataType::UChar => v.try_into().map(Self::UChar).map_err(|_| self),
1855                TangoDataType::Short => Ok(self),
1856                TangoDataType::UShort => v.try_into().map(Self::UShort).map_err(|_| self),
1857                TangoDataType::Int |
1858                TangoDataType::Long => Ok(Self::Long(v as _)),
1859                TangoDataType::ULong => Ok(Self::ULong(v as _)),
1860                TangoDataType::Long64 => Ok(Self::Long64(v as _)),
1861                TangoDataType::ULong64 => Ok(Self::ULong64(v as _)),
1862                TangoDataType::Float => Ok(Self::Float(v as _)),
1863                TangoDataType::Double => Ok(Self::Double(v as _)),
1864                _ => Err(self)
1865            }
1866            Self::UShort(v) => match to {
1867                TangoDataType::Boolean => check_bool(v as i64).map(Self::Boolean).map_err(|_| self),
1868                TangoDataType::UChar => v.try_into().map(Self::UChar).map_err(|_| self),
1869                TangoDataType::Short => v.try_into().map(Self::Short).map_err(|_| self),
1870                TangoDataType::UShort => Ok(self),
1871                TangoDataType::Int |
1872                TangoDataType::Long => Ok(Self::Long(v as _)),
1873                TangoDataType::ULong => Ok(Self::ULong(v as _)),
1874                TangoDataType::Long64 => Ok(Self::Long64(v as _)),
1875                TangoDataType::ULong64 => Ok(Self::ULong64(v as _)),
1876                TangoDataType::Float => Ok(Self::Float(v as _)),
1877                TangoDataType::Double => Ok(Self::Double(v as _)),
1878                _ => Err(self)
1879            }
1880            Self::Long(v) => match to {
1881                TangoDataType::Boolean => check_bool(v as i64).map(Self::Boolean).map_err(|_| self),
1882                TangoDataType::UChar => v.try_into().map(Self::UChar).map_err(|_| self),
1883                TangoDataType::Short => v.try_into().map(Self::Short).map_err(|_| self),
1884                TangoDataType::UShort => v.try_into().map(Self::UShort).map_err(|_| self),
1885                TangoDataType::Int |
1886                TangoDataType::Long => Ok(self),
1887                TangoDataType::ULong => v.try_into().map(Self::ULong).map_err(|_| self),
1888                TangoDataType::Long64 => Ok(Self::Long64(v as _)),
1889                TangoDataType::ULong64 => Ok(Self::ULong64(v as _)),
1890                TangoDataType::Float => Ok(Self::Float(v as _)),
1891                TangoDataType::Double => Ok(Self::Double(v as _)),
1892                _ => Err(self)
1893            }
1894            Self::ULong(v) => match to {
1895                TangoDataType::Boolean => check_bool(v as i64).map(Self::Boolean).map_err(|_| self),
1896                TangoDataType::UChar => v.try_into().map(Self::UChar).map_err(|_| self),
1897                TangoDataType::Short => v.try_into().map(Self::Short).map_err(|_| self),
1898                TangoDataType::UShort => v.try_into().map(Self::UShort).map_err(|_| self),
1899                TangoDataType::Int |
1900                TangoDataType::Long => v.try_into().map(Self::Long).map_err(|_| self),
1901                TangoDataType::ULong => Ok(self),
1902                TangoDataType::Long64 => Ok(Self::Long64(v as _)),
1903                TangoDataType::ULong64 => Ok(Self::ULong64(v as _)),
1904                TangoDataType::Float => Ok(Self::Float(v as _)),
1905                TangoDataType::Double => Ok(Self::Double(v as _)),
1906                _ => Err(self)
1907            }
1908            Self::Long64(v) => match to {
1909                TangoDataType::Boolean => check_bool(v as i64).map(Self::Boolean).map_err(|_| self),
1910                TangoDataType::UChar => v.try_into().map(Self::UChar).map_err(|_| self),
1911                TangoDataType::Short => v.try_into().map(Self::Short).map_err(|_| self),
1912                TangoDataType::UShort => v.try_into().map(Self::UShort).map_err(|_| self),
1913                TangoDataType::Int |
1914                TangoDataType::Long => v.try_into().map(Self::Long).map_err(|_| self),
1915                TangoDataType::ULong => v.try_into().map(Self::ULong).map_err(|_| self),
1916                TangoDataType::Long64 => Ok(self),
1917                TangoDataType::ULong64 => v.try_into().map(Self::ULong64).map_err(|_| self),
1918                TangoDataType::Float => Ok(Self::Float(v as _)),
1919                TangoDataType::Double => Ok(Self::Double(v as _)),
1920                _ => Err(self)
1921            }
1922            Self::ULong64(v) => match to {
1923                TangoDataType::Boolean => check_bool(v as i64).map(Self::Boolean).map_err(|_| self),
1924                TangoDataType::UChar => v.try_into().map(Self::UChar).map_err(|_| self),
1925                TangoDataType::Short => v.try_into().map(Self::Short).map_err(|_| self),
1926                TangoDataType::UShort => v.try_into().map(Self::UShort).map_err(|_| self),
1927                TangoDataType::Int |
1928                TangoDataType::Long => v.try_into().map(Self::Long).map_err(|_| self),
1929                TangoDataType::ULong => v.try_into().map(Self::ULong).map_err(|_| self),
1930                TangoDataType::Long64 => v.try_into().map(Self::Long64).map_err(|_| self),
1931                TangoDataType::ULong64 => Ok(self),
1932                TangoDataType::Float => Ok(Self::Float(v as _)),
1933                TangoDataType::Double => Ok(Self::Double(v as _)),
1934                _ => Err(self)
1935            }
1936            Self::Float(v) => match to {
1937                TangoDataType::Float => Ok(self),
1938                TangoDataType::Double => Ok(Self::Double(v as _)),
1939                _ => Err(self)
1940            }
1941            Self::Double(v) => match to {
1942                TangoDataType::Float => Ok(Self::Float(v as _)),
1943                TangoDataType::Double => Ok(self),
1944                _ => Err(self)
1945            }
1946            Self::String(ref v) => match to {
1947                TangoDataType::ConstString |
1948                TangoDataType::String => Ok(self),
1949                TangoDataType::State => std::str::from_utf8(v).map_err(drop)
1950                                                              .and_then(|s| s.parse())
1951                                                              .map(Self::State)
1952                                                              .map_err(|_| self),
1953                _ => Err(self)
1954            }
1955            Self::State(_) => match to {
1956                TangoDataType::State => Ok(self),
1957                _ => Err(self),
1958            }
1959            Self::Encoded(_) => match to {
1960                TangoDataType::Encoded => Ok(self),
1961                _ => Err(self),
1962            }
1963            Self::BooleanArray(v) => match to {
1964                TangoDataType::BooleanArray => Ok(Self::BooleanArray(v)),
1965                TangoDataType::CharArray => Ok(Self::UCharArray(v.into_iter().map(|v| v as _).collect())),
1966                TangoDataType::ShortArray => Ok(Self::ShortArray(v.into_iter().map(|v| v as _).collect())),
1967                TangoDataType::UShortArray => Ok(Self::UShortArray(v.into_iter().map(|v| v as _).collect())),
1968                TangoDataType::LongArray => Ok(Self::LongArray(v.into_iter().map(|v| v as _).collect())),
1969                TangoDataType::ULongArray => Ok(Self::ULongArray(v.into_iter().map(|v| v as _).collect())),
1970                TangoDataType::Long64Array => Ok(Self::Long64Array(v.into_iter().map(|v| v as _).collect())),
1971                TangoDataType::ULong64Array => Ok(Self::ULong64Array(v.into_iter().map(|v| v as _).collect())),
1972                TangoDataType::FloatArray => Ok(Self::FloatArray(v.into_iter().map(|v| v as i32 as _).collect())),
1973                TangoDataType::DoubleArray => Ok(Self::DoubleArray(v.into_iter().map(|v| v as i32 as _).collect())),
1974                TangoDataType::StringArray if v.len() == 0 => Ok(Self::StringArray(vec![])),
1975                _ => Err(Self::BooleanArray(v)),
1976            }
1977            Self::UCharArray(v) => match to {
1978                TangoDataType::BooleanArray if v.len() == 0 => Ok(Self::BooleanArray(vec![])),
1979                TangoDataType::CharArray => Ok(Self::UCharArray(v)),
1980                TangoDataType::ShortArray => Ok(Self::ShortArray(v.into_iter().map(|v| v as _).collect())),
1981                TangoDataType::UShortArray => Ok(Self::UShortArray(v.into_iter().map(|v| v as _).collect())),
1982                TangoDataType::LongArray => Ok(Self::LongArray(v.into_iter().map(|v| v as _).collect())),
1983                TangoDataType::ULongArray => Ok(Self::ULongArray(v.into_iter().map(|v| v as _).collect())),
1984                TangoDataType::Long64Array => Ok(Self::Long64Array(v.into_iter().map(|v| v as _).collect())),
1985                TangoDataType::ULong64Array => Ok(Self::ULong64Array(v.into_iter().map(|v| v as _).collect())),
1986                TangoDataType::FloatArray => Ok(Self::FloatArray(v.into_iter().map(|v| v as _).collect())),
1987                TangoDataType::DoubleArray => Ok(Self::DoubleArray(v.into_iter().map(|v| v as _).collect())),
1988                TangoDataType::StringArray if v.len() == 0 => Ok(Self::StringArray(vec![])),
1989                _ => Err(Self::UCharArray(v)),
1990            }
1991            Self::ShortArray(v) => match to {
1992                TangoDataType::BooleanArray if v.len() == 0 => Ok(Self::BooleanArray(vec![])),
1993                TangoDataType::CharArray => v.iter().map(|&v| v.try_into())
1994                                                    .collect::<Result<Vec<_>, _>>()
1995                                                    .map(Self::UCharArray)
1996                                                    .map_err(|_| Self::ShortArray(v)),
1997                TangoDataType::ShortArray => Ok(Self::ShortArray(v)),
1998                TangoDataType::UShortArray => v.iter().map(|&v| v.try_into())
1999                                                    .collect::<Result<Vec<_>, _>>()
2000                                                    .map(Self::UShortArray)
2001                                                    .map_err(|_| Self::ShortArray(v)),
2002                TangoDataType::LongArray => Ok(Self::LongArray(v.into_iter().map(|v| v as _).collect())),
2003                TangoDataType::ULongArray => Ok(Self::ULongArray(v.into_iter().map(|v| v as _).collect())),
2004                TangoDataType::Long64Array => Ok(Self::Long64Array(v.into_iter().map(|v| v as _).collect())),
2005                TangoDataType::ULong64Array => Ok(Self::ULong64Array(v.into_iter().map(|v| v as _).collect())),
2006                TangoDataType::FloatArray => Ok(Self::FloatArray(v.into_iter().map(|v| v as _).collect())),
2007                TangoDataType::DoubleArray => Ok(Self::DoubleArray(v.into_iter().map(|v| v as _).collect())),
2008                TangoDataType::StringArray if v.len() == 0 => Ok(Self::StringArray(vec![])),
2009                _ => Err(Self::ShortArray(v)),
2010            }
2011            Self::UShortArray(v) => match to {
2012                TangoDataType::BooleanArray if v.len() == 0 => Ok(Self::BooleanArray(vec![])),
2013                TangoDataType::CharArray => v.iter().map(|&v| v.try_into())
2014                                                    .collect::<Result<Vec<_>, _>>()
2015                                                    .map(Self::UCharArray)
2016                                                    .map_err(|_| Self::UShortArray(v)),
2017                TangoDataType::ShortArray => v.iter().map(|&v| v.try_into())
2018                                                    .collect::<Result<Vec<_>, _>>()
2019                                                    .map(Self::ShortArray)
2020                                                    .map_err(|_| Self::UShortArray(v)),
2021                TangoDataType::UShortArray => Ok(Self::UShortArray(v)),
2022                TangoDataType::LongArray => Ok(Self::LongArray(v.into_iter().map(|v| v as _).collect())),
2023                TangoDataType::ULongArray => Ok(Self::ULongArray(v.into_iter().map(|v| v as _).collect())),
2024                TangoDataType::Long64Array => Ok(Self::Long64Array(v.into_iter().map(|v| v as _).collect())),
2025                TangoDataType::ULong64Array => Ok(Self::ULong64Array(v.into_iter().map(|v| v as _).collect())),
2026                TangoDataType::FloatArray => Ok(Self::FloatArray(v.into_iter().map(|v| v as _).collect())),
2027                TangoDataType::DoubleArray => Ok(Self::DoubleArray(v.into_iter().map(|v| v as _).collect())),
2028                TangoDataType::StringArray if v.len() == 0 => Ok(Self::StringArray(vec![])),
2029                _ => Err(Self::UShortArray(v)),
2030            }
2031            Self::LongArray(v) => match to {
2032                TangoDataType::BooleanArray if v.len() == 0 => Ok(Self::BooleanArray(vec![])),
2033                TangoDataType::CharArray => v.iter().map(|&v| v.try_into())
2034                                                    .collect::<Result<Vec<_>, _>>()
2035                                                    .map(Self::UCharArray)
2036                                                    .map_err(|_| Self::LongArray(v)),
2037                TangoDataType::ShortArray => v.iter().map(|&v| v.try_into())
2038                                                    .collect::<Result<Vec<_>, _>>()
2039                                                    .map(Self::ShortArray)
2040                                                    .map_err(|_| Self::LongArray(v)),
2041                TangoDataType::UShortArray => v.iter().map(|&v| v.try_into())
2042                                                    .collect::<Result<Vec<_>, _>>()
2043                                                    .map(Self::UShortArray)
2044                                                    .map_err(|_| Self::LongArray(v)),
2045                TangoDataType::LongArray => Ok(Self::LongArray(v)),
2046                TangoDataType::ULongArray => v.iter().map(|&v| v.try_into())
2047                                                    .collect::<Result<Vec<_>, _>>()
2048                                                    .map(Self::ULongArray)
2049                                                    .map_err(|_| Self::LongArray(v)),
2050                TangoDataType::Long64Array => Ok(Self::Long64Array(v.into_iter().map(|v| v as _).collect())),
2051                TangoDataType::ULong64Array => Ok(Self::ULong64Array(v.into_iter().map(|v| v as _).collect())),
2052                TangoDataType::FloatArray => Ok(Self::FloatArray(v.into_iter().map(|v| v as _).collect())),
2053                TangoDataType::DoubleArray => Ok(Self::DoubleArray(v.into_iter().map(|v| v as _).collect())),
2054                TangoDataType::StringArray if v.len() == 0 => Ok(Self::StringArray(vec![])),
2055                _ => Err(Self::LongArray(v)),
2056            }
2057            Self::ULongArray(v) => match to {
2058                TangoDataType::BooleanArray if v.len() == 0 => Ok(Self::BooleanArray(vec![])),
2059                TangoDataType::CharArray => v.iter().map(|&v| v.try_into())
2060                                                    .collect::<Result<Vec<_>, _>>()
2061                                                    .map(Self::UCharArray)
2062                                                    .map_err(|_| Self::ULongArray(v)),
2063                TangoDataType::ShortArray => v.iter().map(|&v| v.try_into())
2064                                                    .collect::<Result<Vec<_>, _>>()
2065                                                    .map(Self::ShortArray)
2066                                                    .map_err(|_| Self::ULongArray(v)),
2067                TangoDataType::UShortArray => v.iter().map(|&v| v.try_into())
2068                                                    .collect::<Result<Vec<_>, _>>()
2069                                                    .map(Self::UShortArray)
2070                                                    .map_err(|_| Self::ULongArray(v)),
2071                TangoDataType::LongArray => v.iter().map(|&v| v.try_into())
2072                                                    .collect::<Result<Vec<_>, _>>()
2073                                                    .map(Self::LongArray)
2074                                                    .map_err(|_| Self::ULongArray(v)),
2075                TangoDataType::ULongArray => Ok(Self::ULongArray(v)),
2076                TangoDataType::Long64Array => Ok(Self::Long64Array(v.into_iter().map(|v| v as _).collect())),
2077                TangoDataType::ULong64Array => Ok(Self::ULong64Array(v.into_iter().map(|v| v as _).collect())),
2078                TangoDataType::FloatArray => Ok(Self::FloatArray(v.into_iter().map(|v| v as _).collect())),
2079                TangoDataType::DoubleArray => Ok(Self::DoubleArray(v.into_iter().map(|v| v as _).collect())),
2080                TangoDataType::StringArray if v.len() == 0 => Ok(Self::StringArray(vec![])),
2081                _ => Err(Self::ULongArray(v)),
2082            }
2083            Self::Long64Array(v) => match to {
2084                TangoDataType::BooleanArray if v.len() == 0 => Ok(Self::BooleanArray(vec![])),
2085                TangoDataType::CharArray => v.iter().map(|&v| v.try_into())
2086                                                    .collect::<Result<Vec<_>, _>>()
2087                                                    .map(Self::UCharArray)
2088                                                    .map_err(|_| Self::Long64Array(v)),
2089                TangoDataType::ShortArray => v.iter().map(|&v| v.try_into())
2090                                                    .collect::<Result<Vec<_>, _>>()
2091                                                    .map(Self::ShortArray)
2092                                                    .map_err(|_| Self::Long64Array(v)),
2093                TangoDataType::UShortArray => v.iter().map(|&v| v.try_into())
2094                                                    .collect::<Result<Vec<_>, _>>()
2095                                                    .map(Self::UShortArray)
2096                                                    .map_err(|_| Self::Long64Array(v)),
2097                TangoDataType::LongArray => v.iter().map(|&v| v.try_into())
2098                                                    .collect::<Result<Vec<_>, _>>()
2099                                                    .map(Self::LongArray)
2100                                                    .map_err(|_| Self::Long64Array(v)),
2101                TangoDataType::ULongArray => v.iter().map(|&v| v.try_into())
2102                                                    .collect::<Result<Vec<_>, _>>()
2103                                                    .map(Self::ULongArray)
2104                                                    .map_err(|_| Self::Long64Array(v)),
2105                TangoDataType::Long64Array => Ok(Self::Long64Array(v)),
2106                TangoDataType::ULong64Array => v.iter().map(|&v| v.try_into())
2107                                                    .collect::<Result<Vec<_>, _>>()
2108                                                    .map(Self::ULong64Array)
2109                                                    .map_err(|_| Self::Long64Array(v)),
2110                TangoDataType::FloatArray => Ok(Self::FloatArray(v.into_iter().map(|v| v as _).collect())),
2111                TangoDataType::DoubleArray => Ok(Self::DoubleArray(v.into_iter().map(|v| v as _).collect())),
2112                TangoDataType::StringArray if v.len() == 0 => Ok(Self::StringArray(vec![])),
2113                _ => Err(Self::Long64Array(v)),
2114            }
2115            Self::ULong64Array(v) => match to {
2116                TangoDataType::BooleanArray if v.len() == 0 => Ok(Self::BooleanArray(vec![])),
2117                TangoDataType::CharArray => v.iter().map(|&v| v.try_into())
2118                                                    .collect::<Result<Vec<_>, _>>()
2119                                                    .map(Self::UCharArray)
2120                                                    .map_err(|_| Self::ULong64Array(v)),
2121                TangoDataType::ShortArray => v.iter().map(|&v| v.try_into())
2122                                                    .collect::<Result<Vec<_>, _>>()
2123                                                    .map(Self::ShortArray)
2124                                                    .map_err(|_| Self::ULong64Array(v)),
2125                TangoDataType::UShortArray => v.iter().map(|&v| v.try_into())
2126                                                    .collect::<Result<Vec<_>, _>>()
2127                                                    .map(Self::UShortArray)
2128                                                    .map_err(|_| Self::ULong64Array(v)),
2129                TangoDataType::LongArray => v.iter().map(|&v| v.try_into())
2130                                                    .collect::<Result<Vec<_>, _>>()
2131                                                    .map(Self::LongArray)
2132                                                    .map_err(|_| Self::ULong64Array(v)),
2133                TangoDataType::ULongArray => v.iter().map(|&v| v.try_into())
2134                                                    .collect::<Result<Vec<_>, _>>()
2135                                                    .map(Self::ULongArray)
2136                                                    .map_err(|_| Self::ULong64Array(v)),
2137                TangoDataType::Long64Array => v.iter().map(|&v| v.try_into())
2138                                                    .collect::<Result<Vec<_>, _>>()
2139                                                    .map(Self::Long64Array)
2140                                                    .map_err(|_| Self::ULong64Array(v)),
2141                TangoDataType::ULong64Array => Ok(Self::ULong64Array(v)),
2142                TangoDataType::FloatArray => Ok(Self::FloatArray(v.into_iter().map(|v| v as _).collect())),
2143                TangoDataType::DoubleArray => Ok(Self::DoubleArray(v.into_iter().map(|v| v as _).collect())),
2144                TangoDataType::StringArray if v.len() == 0 => Ok(Self::StringArray(vec![])),
2145                _ => Err(Self::ULong64Array(v)),
2146            }
2147            Self::FloatArray(v) => match to {
2148                TangoDataType::BooleanArray if v.len() == 0 => Ok(Self::BooleanArray(vec![])),
2149                TangoDataType::CharArray if v.len() == 0 => Ok(Self::UCharArray(vec![])),
2150                TangoDataType::ShortArray if v.len() == 0 => Ok(Self::ShortArray(vec![])),
2151                TangoDataType::UShortArray if v.len() == 0 => Ok(Self::UShortArray(vec![])),
2152                TangoDataType::LongArray if v.len() == 0 => Ok(Self::LongArray(vec![])),
2153                TangoDataType::ULongArray if v.len() == 0 => Ok(Self::ULongArray(vec![])),
2154                TangoDataType::Long64Array if v.len() == 0 => Ok(Self::Long64Array(vec![])),
2155                TangoDataType::ULong64Array if v.len() == 0 => Ok(Self::ULong64Array(vec![])),
2156                TangoDataType::FloatArray => Ok(Self::FloatArray(v)),
2157                TangoDataType::DoubleArray => Ok(Self::DoubleArray(v.into_iter().map(|v| v as _).collect())),
2158                TangoDataType::StringArray if v.len() == 0 => Ok(Self::StringArray(vec![])),
2159                _ => Err(Self::FloatArray(v)),
2160            }
2161            Self::DoubleArray(v) => match to {
2162                TangoDataType::BooleanArray if v.len() == 0 => Ok(Self::BooleanArray(vec![])),
2163                TangoDataType::CharArray if v.len() == 0 => Ok(Self::UCharArray(vec![])),
2164                TangoDataType::ShortArray if v.len() == 0 => Ok(Self::ShortArray(vec![])),
2165                TangoDataType::UShortArray if v.len() == 0 => Ok(Self::UShortArray(vec![])),
2166                TangoDataType::LongArray if v.len() == 0 => Ok(Self::LongArray(vec![])),
2167                TangoDataType::ULongArray if v.len() == 0 => Ok(Self::ULongArray(vec![])),
2168                TangoDataType::Long64Array if v.len() == 0 => Ok(Self::Long64Array(vec![])),
2169                TangoDataType::ULong64Array if v.len() == 0 => Ok(Self::ULong64Array(vec![])),
2170                TangoDataType::FloatArray => Ok(Self::FloatArray(v.into_iter().map(|v| v as _).collect())),
2171                TangoDataType::DoubleArray => Ok(Self::DoubleArray(v)),
2172                TangoDataType::StringArray if v.len() == 0 => Ok(Self::StringArray(vec![])),
2173                _ => Err(Self::DoubleArray(v)),
2174            }
2175            Self::StringArray(v) => match to {
2176                TangoDataType::BooleanArray if v.len() == 0 => Ok(Self::BooleanArray(vec![])),
2177                TangoDataType::CharArray if v.len() == 0 => Ok(Self::UCharArray(vec![])),
2178                TangoDataType::ShortArray if v.len() == 0 => Ok(Self::ShortArray(vec![])),
2179                TangoDataType::UShortArray if v.len() == 0 => Ok(Self::UShortArray(vec![])),
2180                TangoDataType::LongArray if v.len() == 0 => Ok(Self::LongArray(vec![])),
2181                TangoDataType::ULongArray if v.len() == 0 => Ok(Self::ULongArray(vec![])),
2182                TangoDataType::Long64Array if v.len() == 0 => Ok(Self::Long64Array(vec![])),
2183                TangoDataType::ULong64Array if v.len() == 0 => Ok(Self::ULong64Array(vec![])),
2184                TangoDataType::FloatArray if v.len() == 0 => Ok(Self::FloatArray(vec![])),
2185                TangoDataType::DoubleArray if v.len() == 0 => Ok(Self::DoubleArray(vec![])),
2186                TangoDataType::StringArray => Ok(Self::StringArray(v)),
2187                _ => Err(Self::StringArray(v)),
2188            }
2189            Self::StateArray(_) | Self::EncodedArray(_) => Err(self)
2190        }
2191    }
2192
2193    /// Return the value if it's a bool or integral 0 or 1.  Otherwise return
2194    /// `Err(self)`.
2195    pub fn into_bool(self) -> Result<bool, Self> {
2196        match self {
2197            Self::Boolean(v) => Ok(v),
2198            Self::UChar(v) => check_bool(v as i64).map_err(|_| self),
2199            Self::Short(v) => check_bool(v as i64).map_err(|_| self),
2200            Self::UShort(v) => check_bool(v as i64).map_err(|_| self),
2201            Self::Long(v) => check_bool(v as i64).map_err(|_| self),
2202            Self::ULong(v) => check_bool(v as i64).map_err(|_| self),
2203            Self::Long64(v) => check_bool(v as i64).map_err(|_| self),
2204            Self::ULong64(v) => check_bool(v as i64).map_err(|_| self),
2205            _ => Err(self),
2206        }
2207    }
2208
2209    /// Return the value as i32 if it's an integral type and inside i32 limits.
2210    /// Otherwise return `Err(self)`.
2211    pub fn into_i32(self) -> Result<i32, Self> {
2212        match self {
2213            Self::Boolean(v) => Ok(v as i32),
2214            Self::UChar(v) => Ok(v as i32),
2215            Self::Short(v) => Ok(v as i32),
2216            Self::UShort(v) => Ok(v as i32),
2217            Self::Long(v) => Ok(v),
2218            Self::ULong(v) => v.try_into().map_err(|_| self),
2219            Self::Long64(v) => v.try_into().map_err(|_| self),
2220            Self::ULong64(v) => v.try_into().map_err(|_| self),
2221            _ => Err(self),
2222        }
2223    }
2224
2225    /// Return the value as i64 if it's a an integral type and inside i64
2226    /// limits.  Otherwise return `Err(self)`.
2227    pub fn into_i64(self) -> Result<i64, Self> {
2228        match self {
2229            Self::Boolean(v) => Ok(v as i64),
2230            Self::UChar(v) => Ok(v as i64),
2231            Self::Short(v) => Ok(v as i64),
2232            Self::UShort(v) => Ok(v as i64),
2233            Self::Long(v) => Ok(v as i64),
2234            Self::ULong(v) => Ok(v as i64),
2235            Self::Long64(v) => Ok(v),
2236            Self::ULong64(v) => v.try_into().map_err(|_| self),
2237            _ => Err(self),
2238        }
2239    }
2240
2241    /// Return the value as u32 if it's an integral type and inside u32 limits.
2242    /// Otherwise return `Err(self)`.
2243    pub fn into_u32(self) -> Result<u32, Self> {
2244        match self {
2245            Self::Boolean(v) => Ok(v as u32),
2246            Self::UChar(v) => Ok(v as u32),
2247            Self::Short(v) => Ok(v as u32),
2248            Self::UShort(v) => Ok(v as u32),
2249            Self::Long(v) => v.try_into().map_err(|_| self),
2250            Self::ULong(v) => Ok(v as u32),
2251            Self::Long64(v) => v.try_into().map_err(|_| self),
2252            Self::ULong64(v) => v.try_into().map_err(|_| self),
2253            _ => Err(self),
2254        }
2255    }
2256
2257    /// Return the value as u64 if it's an integral type and inside u64 limits.
2258    /// Otherwise return `Err(self)`.
2259    pub fn into_u64(self) -> Result<u64, Self> {
2260        match self {
2261            Self::Boolean(v) => Ok(v as u64),
2262            Self::UChar(v) => Ok(v as u64),
2263            Self::Short(v) => Ok(v as u64),
2264            Self::UShort(v) => Ok(v as u64),
2265            Self::Long(v) => Ok(v as u64),
2266            Self::ULong(v) => Ok(v as u64),
2267            Self::Long64(v) => v.try_into().map_err(|_| self),
2268            Self::ULong64(v) => Ok(v),
2269            _ => Err(self),
2270        }
2271    }
2272
2273    /// Return the value as f32 if it's a numeric type.  Otherwise return `Err(self)`.
2274    pub fn into_f32(self) -> Result<f32, Self> {
2275        match self {
2276            Self::Boolean(v) => Ok(v as i32 as f32),
2277            Self::UChar(v) => Ok(v as f32),
2278            Self::Short(v) => Ok(v as f32),
2279            Self::Long(v) => Ok(v as f32),
2280            Self::Long64(v) => Ok(v as f32),
2281            Self::UShort(v) => Ok(v as f32),
2282            Self::ULong(v) => Ok(v as f32),
2283            Self::ULong64(v) => Ok(v as f32),
2284            Self::Float(v) => Ok(v),
2285            Self::Double(v) => Ok(v as f32),
2286            _ => Err(self),
2287        }
2288    }
2289
2290    /// Return the value as f64 if it's a numeric type.  Otherwise return `Err(self)`.
2291    pub fn into_f64(self) -> Result<f64, Self> {
2292        match self {
2293            Self::Boolean(v) => Ok(v as i32 as f64),
2294            Self::UChar(v) => Ok(v as f64),
2295            Self::Short(v) => Ok(v as f64),
2296            Self::Long(v) => Ok(v as f64),
2297            Self::Long64(v) => Ok(v as f64),
2298            Self::UShort(v) => Ok(v as f64),
2299            Self::ULong(v) => Ok(v as f64),
2300            Self::ULong64(v) => Ok(v as f64),
2301            Self::Float(v) => Ok(v as f64),
2302            Self::Double(v) => Ok(v),
2303            _ => Err(self),
2304        }
2305    }
2306
2307    /// Return the value as a byte array if it's a string, DevEncoded or
2308    /// UCharArray.  Otherwise return `Err(self)`.
2309    pub fn into_bytes(self) -> Result<Vec<u8>, Self> {
2310        match self {
2311            Self::String(s) => Ok(s),
2312            Self::Encoded((_, s)) => Ok(s),
2313            Self::UCharArray(s) => Ok(s),
2314            _ => Err(self),
2315        }
2316    }
2317
2318    /// Return the value as a byte array if it's a string, DevEncoded or
2319    /// UCharArray, and decodable as UTF-8.  Otherwise return `Err(self)`.
2320    pub fn into_string(self) -> Result<String, Self> {
2321        match self {
2322            Self::String(s) => String::from_utf8(s).map_err(
2323                |e| Self::String(e.into_bytes())),
2324            Self::Encoded((f, s)) => String::from_utf8(s).map_err(
2325                |e| Self::Encoded((f, e.into_bytes()))),
2326            Self::UCharArray(s) => String::from_utf8(s).map_err(
2327                |e| Self::String(e.into_bytes())),
2328            _ => Err(self),
2329        }
2330    }
2331}
2332
2333impl fmt::Display for AttrValue {
2334    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2335        match self {
2336            Self::Boolean(v) => fmt::Display::fmt(&v, f),
2337            Self::UChar(v) => fmt::Display::fmt(&v, f),
2338            Self::Short(v) => fmt::Display::fmt(&v, f),
2339            Self::UShort(v) => fmt::Display::fmt(&v, f),
2340            Self::Long(v) => fmt::Display::fmt(&v, f),
2341            Self::ULong(v) => fmt::Display::fmt(&v, f),
2342            Self::Long64(v) => fmt::Display::fmt(&v, f),
2343            Self::ULong64(v) => fmt::Display::fmt(&v, f),
2344            Self::Float(v) => fmt::Display::fmt(&v, f),
2345            Self::Double(v) => fmt::Display::fmt(&v, f),
2346            Self::String(v) => fmt::Display::fmt(&String::from_utf8_lossy(v), f),
2347            Self::State(v) => fmt::Display::fmt(&v, f),
2348            Self::Encoded(_) => f.pad("<DevEncoded>"),
2349
2350            Self::BooleanArray(v) => slice_display(v, |x| x, f),
2351            Self::UCharArray(v) => slice_display(v, |x| x, f),
2352            Self::ShortArray(v) => slice_display(v, |x| x, f),
2353            Self::UShortArray(v) => slice_display(v, |x| x, f),
2354            Self::LongArray(v) => slice_display(v, |x| x, f),
2355            Self::ULongArray(v) => slice_display(v, |x| x, f),
2356            Self::Long64Array(v) => slice_display(v, |x| x, f),
2357            Self::ULong64Array(v) => slice_display(v, |x| x, f),
2358            Self::FloatArray(v) => slice_display(v, |x| x, f),
2359            Self::DoubleArray(v) => slice_display(v, |x| x, f),
2360            Self::StringArray(v) => slice_display(v, |x| String::from_utf8_lossy(x), f),
2361            Self::StateArray(v) => slice_display(v, |x| x, f),
2362            Self::EncodedArray(v) => slice_display(v, |_| "<DevEncoded>", f),
2363        }
2364    }
2365}
2366
2367impl fmt::LowerHex for AttrValue {
2368    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2369        match self {
2370            Self::Boolean(v) => fmt::Display::fmt(&v, f),
2371            Self::UChar(v) => fmt::LowerHex::fmt(&v, f),
2372            Self::Short(v) => fmt::LowerHex::fmt(&v, f),
2373            Self::UShort(v) => fmt::LowerHex::fmt(&v, f),
2374            Self::Long(v) => fmt::LowerHex::fmt(&v, f),
2375            Self::ULong(v) => fmt::LowerHex::fmt(&v, f),
2376            Self::Long64(v) => fmt::LowerHex::fmt(&v, f),
2377            Self::ULong64(v) => fmt::LowerHex::fmt(&v, f),
2378            Self::Float(v) => fmt::Display::fmt(&v, f),
2379            Self::Double(v) => fmt::Display::fmt(&v, f),
2380            Self::String(v) => fmt::Display::fmt(&String::from_utf8_lossy(v), f),
2381            Self::State(v) => fmt::Display::fmt(&v, f),
2382            Self::Encoded(_) => f.pad("<DevEncoded>"),
2383
2384            Self::BooleanArray(v) => slice_display(v, |x| x, f),
2385            Self::UCharArray(v) => slice_lower_hex(v, |x| x, f),
2386            Self::ShortArray(v) => slice_lower_hex(v, |x| x, f),
2387            Self::UShortArray(v) => slice_lower_hex(v, |x| x, f),
2388            Self::LongArray(v) => slice_lower_hex(v, |x| x, f),
2389            Self::ULongArray(v) => slice_lower_hex(v, |x| x, f),
2390            Self::Long64Array(v) => slice_lower_hex(v, |x| x, f),
2391            Self::ULong64Array(v) => slice_lower_hex(v, |x| x, f),
2392            Self::FloatArray(v) => slice_display(v, |x| x, f),
2393            Self::DoubleArray(v) => slice_display(v, |x| x, f),
2394            Self::StringArray(v) => slice_display(v, |x| String::from_utf8_lossy(x), f),
2395            Self::StateArray(v) => slice_display(v, |x| x, f),
2396            Self::EncodedArray(v) => slice_display(v, |_| "<DevEncoded>", f),
2397        }
2398    }
2399}
2400
2401impl fmt::UpperHex for AttrValue {
2402    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2403        match self {
2404            Self::Boolean(v) => fmt::Display::fmt(&v, f),
2405            Self::UChar(v) => fmt::UpperHex::fmt(&v, f),
2406            Self::Short(v) => fmt::UpperHex::fmt(&v, f),
2407            Self::UShort(v) => fmt::UpperHex::fmt(&v, f),
2408            Self::Long(v) => fmt::UpperHex::fmt(&v, f),
2409            Self::ULong(v) => fmt::UpperHex::fmt(&v, f),
2410            Self::Long64(v) => fmt::UpperHex::fmt(&v, f),
2411            Self::ULong64(v) => fmt::UpperHex::fmt(&v, f),
2412            Self::Float(v) => fmt::Display::fmt(&v, f),
2413            Self::Double(v) => fmt::Display::fmt(&v, f),
2414            Self::String(v) => fmt::Display::fmt(&String::from_utf8_lossy(v), f),
2415            Self::State(v) => fmt::Display::fmt(&v, f),
2416            Self::Encoded(_) => f.pad("<DevEncoded>"),
2417
2418            Self::BooleanArray(v) => slice_display(v, |x| x, f),
2419            Self::UCharArray(v) => slice_upper_hex(v, |x| x, f),
2420            Self::ShortArray(v) => slice_upper_hex(v, |x| x, f),
2421            Self::UShortArray(v) => slice_upper_hex(v, |x| x, f),
2422            Self::LongArray(v) => slice_upper_hex(v, |x| x, f),
2423            Self::ULongArray(v) => slice_upper_hex(v, |x| x, f),
2424            Self::Long64Array(v) => slice_upper_hex(v, |x| x, f),
2425            Self::ULong64Array(v) => slice_upper_hex(v, |x| x, f),
2426            Self::FloatArray(v) => slice_display(v, |x| x, f),
2427            Self::DoubleArray(v) => slice_display(v, |x| x, f),
2428            Self::StringArray(v) => slice_display(v, |x| String::from_utf8_lossy(x), f),
2429            Self::StateArray(v) => slice_display(v, |x| x, f),
2430            Self::EncodedArray(v) => slice_display(v, |_| "<DevEncoded>", f),
2431        }
2432    }
2433}
2434
2435impl fmt::LowerExp for AttrValue {
2436    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2437        match self {
2438            Self::Boolean(v) => fmt::Display::fmt(&v, f),
2439            Self::UChar(v) => fmt::Display::fmt(&v, f),
2440            Self::Short(v) => fmt::Display::fmt(&v, f),
2441            Self::UShort(v) => fmt::Display::fmt(&v, f),
2442            Self::Long(v) => fmt::Display::fmt(&v, f),
2443            Self::ULong(v) => fmt::Display::fmt(&v, f),
2444            Self::Long64(v) => fmt::Display::fmt(&v, f),
2445            Self::ULong64(v) => fmt::Display::fmt(&v, f),
2446            Self::Float(v) => fmt::LowerExp::fmt(&v, f),
2447            Self::Double(v) => fmt::LowerExp::fmt(&v, f),
2448            Self::String(v) => fmt::Display::fmt(&String::from_utf8_lossy(v), f),
2449            Self::State(v) => fmt::Display::fmt(&v, f),
2450            Self::Encoded(_) => f.pad("<DevEncoded>"),
2451
2452            Self::BooleanArray(v) => slice_display(v, |x| x, f),
2453            Self::UCharArray(v) => slice_display(v, |x| x, f),
2454            Self::ShortArray(v) => slice_display(v, |x| x, f),
2455            Self::UShortArray(v) => slice_display(v, |x| x, f),
2456            Self::LongArray(v) => slice_display(v, |x| x, f),
2457            Self::ULongArray(v) => slice_display(v, |x| x, f),
2458            Self::Long64Array(v) => slice_display(v, |x| x, f),
2459            Self::ULong64Array(v) => slice_display(v, |x| x, f),
2460            Self::FloatArray(v) => slice_lower_exp(v, |x| x, f),
2461            Self::DoubleArray(v) => slice_lower_exp(v, |x| x, f),
2462            Self::StringArray(v) => slice_display(v, |x| String::from_utf8_lossy(x), f),
2463            Self::StateArray(v) => slice_display(v, |x| x, f),
2464            Self::EncodedArray(v) => slice_display(v, |_| "<DevEncoded>", f),
2465        }
2466    }
2467}
2468
2469impl fmt::UpperExp for AttrValue {
2470    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2471        match self {
2472            Self::Boolean(v) => fmt::Display::fmt(&v, f),
2473            Self::UChar(v) => fmt::Display::fmt(&v, f),
2474            Self::Short(v) => fmt::Display::fmt(&v, f),
2475            Self::UShort(v) => fmt::Display::fmt(&v, f),
2476            Self::Long(v) => fmt::Display::fmt(&v, f),
2477            Self::ULong(v) => fmt::Display::fmt(&v, f),
2478            Self::Long64(v) => fmt::Display::fmt(&v, f),
2479            Self::ULong64(v) => fmt::Display::fmt(&v, f),
2480            Self::Float(v) => fmt::UpperExp::fmt(&v, f),
2481            Self::Double(v) => fmt::UpperExp::fmt(&v, f),
2482            Self::String(v) => fmt::Display::fmt(&String::from_utf8_lossy(v), f),
2483            Self::State(v) => fmt::Display::fmt(&v, f),
2484            Self::Encoded(_) => f.pad("<DevEncoded>"),
2485
2486            Self::BooleanArray(v) => slice_display(v, |x| x, f),
2487            Self::UCharArray(v) => slice_display(v, |x| x, f),
2488            Self::ShortArray(v) => slice_display(v, |x| x, f),
2489            Self::UShortArray(v) => slice_display(v, |x| x, f),
2490            Self::LongArray(v) => slice_display(v, |x| x, f),
2491            Self::ULongArray(v) => slice_display(v, |x| x, f),
2492            Self::Long64Array(v) => slice_display(v, |x| x, f),
2493            Self::ULong64Array(v) => slice_display(v, |x| x, f),
2494            Self::FloatArray(v) => slice_upper_exp(v, |x| x, f),
2495            Self::DoubleArray(v) => slice_upper_exp(v, |x| x, f),
2496            Self::StringArray(v) => slice_display(v, |x| String::from_utf8_lossy(x), f),
2497            Self::StateArray(v) => slice_display(v, |x| x, f),
2498            Self::EncodedArray(v) => slice_display(v, |_| "<DevEncoded>", f),
2499        }
2500    }
2501}
2502
2503
2504/// Represents a single property with name and value.
2505#[derive(Debug, Clone, PartialEq)]
2506pub struct DbDatum {
2507    pub name: String,
2508    pub data: PropertyValue,
2509    pub wrong_data_type: bool,
2510    request_type: Option<TangoDataType>,
2511}
2512
2513impl DbDatum {
2514    /// Create a datum for a given name and value.
2515    pub fn new(name: &str, data: PropertyValue) -> DbDatum {
2516        DbDatum {
2517            name: name.into(),
2518            data,
2519            wrong_data_type: false,
2520            request_type: None,
2521        }
2522    }
2523
2524    /// Create a datum for requesting a given property with a fixed data type.
2525    pub fn for_request(name: &str, typ: TangoDataType) -> DbDatum {
2526        DbDatum {
2527            name: name.into(),
2528            data: PropertyValue::Empty,
2529            wrong_data_type: false,
2530            request_type: Some(typ),
2531        }
2532    }
2533
2534    /// Create a datum for requesting a given property.
2535    pub fn name_only(name: &str) -> DbDatum {
2536        DbDatum {
2537            name: name.into(),
2538            data: PropertyValue::Empty,
2539            wrong_data_type: false,
2540            request_type: None
2541        }
2542    }
2543
2544    pub(crate) unsafe fn from_c(mut db_datum: c::DbDatum, free: bool) -> DbDatum {
2545        let data = if db_datum.is_empty {
2546            PropertyValue::Empty
2547        } else {
2548            let data = db_datum.prop_data;
2549            match TangoDataType::from_c(db_datum.data_type) {
2550                TangoDataType::Boolean => PropertyValue::Boolean(data.bool_val),
2551                TangoDataType::UChar => PropertyValue::UChar(data.char_val),
2552                TangoDataType::Short => PropertyValue::Short(data.short_val),
2553                TangoDataType::UShort => PropertyValue::UShort(data.ushort_val),
2554                TangoDataType::Long | TangoDataType::Int => PropertyValue::Long(data.long_val),
2555                TangoDataType::ULong => PropertyValue::ULong(data.ulong_val),
2556                TangoDataType::Long64 => PropertyValue::Long64(data.long64_val),
2557                TangoDataType::ULong64 => PropertyValue::ULong64(data.ulong64_val),
2558                TangoDataType::Float => PropertyValue::Float(data.float_val),
2559                TangoDataType::Double => PropertyValue::Double(data.double_val),
2560                TangoDataType::String | TangoDataType::ConstString => PropertyValue::String({
2561                    let ptr = data.string_val;
2562                    let len = libc::strlen(ptr);
2563                    Vec::from(slice::from_raw_parts(ptr as *mut u8, len))
2564                }),
2565                TangoDataType::ShortArray => PropertyValue::ShortArray({
2566                    let ptr = data.short_arr;
2567                    Vec::from(slice::from_raw_parts(ptr.sequence, ptr.length as usize))
2568                }),
2569                TangoDataType::UShortArray => PropertyValue::UShortArray({
2570                    let ptr = data.ushort_arr;
2571                    Vec::from(slice::from_raw_parts(ptr.sequence, ptr.length as usize))
2572                }),
2573                TangoDataType::LongArray => PropertyValue::LongArray({
2574                    let ptr = data.long_arr;
2575                    Vec::from(slice::from_raw_parts(ptr.sequence, ptr.length as usize))
2576                }),
2577                TangoDataType::ULongArray => PropertyValue::ULongArray({
2578                    let ptr = data.ulong_arr;
2579                    Vec::from(slice::from_raw_parts(ptr.sequence, ptr.length as usize))
2580                }),
2581                TangoDataType::Long64Array => PropertyValue::Long64Array({
2582                    let ptr = data.long64_arr;
2583                    Vec::from(slice::from_raw_parts(ptr.sequence, ptr.length as usize))
2584                }),
2585                TangoDataType::ULong64Array => PropertyValue::ULong64Array({
2586                    let ptr = data.ulong64_arr;
2587                    Vec::from(slice::from_raw_parts(ptr.sequence, ptr.length as usize))
2588                }),
2589                TangoDataType::FloatArray => PropertyValue::FloatArray({
2590                    let ptr = data.float_arr;
2591                    Vec::from(slice::from_raw_parts(ptr.sequence, ptr.length as usize))
2592                }),
2593                TangoDataType::DoubleArray => PropertyValue::DoubleArray({
2594                    let ptr = data.double_arr;
2595                    Vec::from(slice::from_raw_parts(ptr.sequence, ptr.length as usize))
2596                }),
2597                TangoDataType::StringArray => PropertyValue::StringArray({
2598                    let ptr = data.string_arr;
2599                    let mut res = Vec::with_capacity(ptr.length as usize);
2600                    for i in 0..ptr.length {
2601                        let raw = *ptr.sequence.offset(i as isize);
2602                        let len = libc::strlen(raw);
2603                        res.push(Vec::from(slice::from_raw_parts(raw as *mut u8, len)));
2604                    }
2605                    res
2606                }),
2607                _ => panic!("data type {:?} not allowed for attributes", db_datum.data_type)
2608            }
2609        };
2610        let res = DbDatum {
2611            name: string_from(db_datum.property_name),
2612            data,
2613            wrong_data_type: db_datum.wrong_data_type,
2614            request_type: None,
2615        };
2616        if free {
2617            c::tango_free_DbDatum(&mut db_datum);
2618        }
2619        res
2620    }
2621
2622    pub(crate) unsafe fn into_c(self) -> (c::DbDatum, CString) {
2623        let mut content = mem::zeroed::<c::DbDatum>();
2624
2625        // Since the property name string is sometimes overwritten, we have to store
2626        // a reference to it somewhere else to be able to free it.
2627        let name_string = cstring_from(self.name);
2628        content.property_name = name_string.as_ptr() as *mut c_char;
2629
2630        macro_rules! impl_array {
2631            ($val:ident, $alt:ident, $arr:ident, $ctype:ty) => {
2632                {
2633                    let array = &mut content.prop_data.$arr;
2634                    array.length = $val.len() as u32;
2635                    array.sequence = Box::into_raw($val.into_boxed_slice()) as *mut $ctype;
2636                    TangoDataType::$alt as u32
2637                }
2638            }
2639        }
2640
2641        if self.wrong_data_type {
2642            content.wrong_data_type = true;
2643        }
2644
2645        if let Some(typ) = self.request_type {
2646            content.data_type = typ as u32;
2647        } else {
2648            let tag = match self.data {
2649                PropertyValue::Empty => {
2650                    content.is_empty = true;
2651                    0
2652                }
2653                PropertyValue::Boolean(v) => {
2654                    content.prop_data.bool_val = v;
2655                    TangoDataType::Boolean as u32
2656                }
2657                PropertyValue::Short(v) => {
2658                    content.prop_data.short_val = v;
2659                    TangoDataType::Short as u32
2660                }
2661                PropertyValue::Long(v) => {
2662                    content.prop_data.long_val = v;
2663                    TangoDataType::Long as u32
2664                }
2665                PropertyValue::Float(v) => {
2666                    content.prop_data.float_val = v;
2667                    TangoDataType::Float as u32
2668                }
2669                PropertyValue::Double(v) => {
2670                    content.prop_data.double_val = v;
2671                    TangoDataType::Double as u32
2672                }
2673                PropertyValue::UShort(v) => {
2674                    content.prop_data.ushort_val = v;
2675                    TangoDataType::UShort as u32
2676                }
2677                PropertyValue::ULong(v) => {
2678                    content.prop_data.ulong_val = v;
2679                    TangoDataType::ULong as u32
2680                }
2681                PropertyValue::Long64(v) => {
2682                    content.prop_data.long64_val = v;
2683                    TangoDataType::Long64 as u32
2684                }
2685                PropertyValue::ULong64(v) => {
2686                    content.prop_data.ulong64_val = v;
2687                    TangoDataType::ULong64 as u32
2688                }
2689                PropertyValue::String(v) => {
2690                    let cstr = cstring_from(v);
2691                    content.prop_data.string_val = cstr.into_raw();
2692                    TangoDataType::String as u32
2693                }
2694                PropertyValue::ShortArray(v) => impl_array!(v, ShortArray, short_arr, i16),
2695                PropertyValue::UShortArray(v) => impl_array!(v, UShortArray, ushort_arr, u16),
2696                PropertyValue::LongArray(v) => impl_array!(v, LongArray, long_arr, i32),
2697                PropertyValue::ULongArray(v) => impl_array!(v, ULongArray, ulong_arr, u32),
2698                PropertyValue::Long64Array(v) => impl_array!(v, Long64Array, long64_arr, i64),
2699                PropertyValue::ULong64Array(v) => impl_array!(v, ULong64Array, ulong64_arr, u64),
2700                PropertyValue::FloatArray(v) => impl_array!(v, FloatArray, float_arr, f32),
2701                PropertyValue::DoubleArray(v) => impl_array!(v, DoubleArray, double_arr, f64),
2702                PropertyValue::StringArray(v) => {
2703                    let array = &mut content.prop_data.string_arr;
2704                    let mut vec = Vec::with_capacity(v.len());
2705                    array.length = v.len() as u32;
2706                    for s in v.into_iter() {
2707                        vec.push(cstring_from(s).into_raw());
2708                    }
2709                    array.sequence = Box::into_raw(vec.into_boxed_slice()) as *mut *mut c_char;
2710                    TangoDataType::StringArray as u32
2711                },
2712                _ => panic!("Cannot send property value of type {:?}", self.data)
2713            };
2714            content.data_type = tag;
2715        }
2716        (content, name_string)
2717    }
2718
2719    pub(crate) unsafe fn free_c_data(db_datum: c::DbDatum) {
2720        let data = db_datum.prop_data;
2721        match TangoDataType::from_c(db_datum.data_type) {
2722            TangoDataType::Void |
2723            TangoDataType::Boolean |
2724            TangoDataType::UChar |
2725            TangoDataType::Short |
2726            TangoDataType::Long |
2727            TangoDataType::Int |
2728            TangoDataType::Float |
2729            TangoDataType::Double |
2730            TangoDataType::UShort |
2731            TangoDataType::ULong |
2732            TangoDataType::Long64 |
2733            TangoDataType::ULong64 |
2734            TangoDataType::State => {}
2735            TangoDataType::String | TangoDataType::ConstString => {
2736                drop(CString::from_raw(data.string_val));
2737            }
2738            TangoDataType::ShortArray => drop(Box::from_raw(data.short_arr.sequence)),
2739            TangoDataType::UShortArray => drop(Box::from_raw(data.ushort_arr.sequence)),
2740            TangoDataType::LongArray => drop(Box::from_raw(data.long_arr.sequence)),
2741            TangoDataType::ULongArray => drop(Box::from_raw(data.ulong_arr.sequence)),
2742            TangoDataType::Long64Array => drop(Box::from_raw(data.long64_arr.sequence)),
2743            TangoDataType::ULong64Array => drop(Box::from_raw(data.ulong64_arr.sequence)),
2744            TangoDataType::FloatArray => drop(Box::from_raw(data.float_arr.sequence)),
2745            TangoDataType::DoubleArray => drop(Box::from_raw(data.double_arr.sequence)),
2746            TangoDataType::StringArray => {
2747                for i in 0..data.string_arr.length {
2748                    drop(CString::from_raw(*data.string_arr.sequence.offset(i as isize) as *mut c_char));
2749                }
2750                drop(Box::from_raw(data.string_arr.sequence));
2751            }
2752            _ => unreachable!()
2753        }
2754    }
2755}
2756
2757
2758/// Represents the value of a property.
2759///
2760/// The normal way to construct this is to use the desired variant directly.
2761#[derive(Debug, Clone, PartialEq)]
2762pub enum PropertyValue {
2763    Empty,
2764
2765    Boolean(bool),
2766    UChar(u8),
2767    Short(i16),
2768    UShort(u16),
2769    Long(i32),
2770    ULong(u32),
2771    Long64(i64),
2772    ULong64(u64),
2773
2774    Float(f32),
2775    Double(f64),
2776
2777    String(Vec<u8>),
2778
2779    ShortArray(Vec<i16>),
2780    UShortArray(Vec<u16>),
2781    LongArray(Vec<i32>),
2782    ULongArray(Vec<u32>),
2783    Long64Array(Vec<i64>),
2784    ULong64Array(Vec<u64>),
2785
2786    FloatArray(Vec<f32>),
2787    DoubleArray(Vec<f64>),
2788
2789    StringArray(Vec<Vec<u8>>),
2790}
2791
2792impl PropertyValue {
2793    /// Construct a PropertyValue from a Rust string slice.
2794    pub fn from_str(s: &str) -> Self {
2795        Self::String(s.to_owned().into_bytes())
2796    }
2797
2798    /// Return the number of data items in this value.
2799    ///
2800    /// 0 for Empty, 1 for simple data, length of the array for array data.
2801    pub fn len(&self) -> usize {
2802        match self {
2803            Self::ShortArray(a) => a.len(),
2804            Self::UShortArray(a) => a.len(),
2805            Self::LongArray(a) => a.len(),
2806            Self::ULongArray(a) => a.len(),
2807            Self::Long64Array(a) => a.len(),
2808            Self::ULong64Array(a) => a.len(),
2809            Self::FloatArray(a) => a.len(),
2810            Self::DoubleArray(a) => a.len(),
2811            Self::StringArray(a) => a.len(),
2812            Self::Empty => 0,
2813            _ => 1,
2814        }
2815    }
2816
2817    /// Try to convert this data into a different type.
2818    ///
2819    /// If the conversion fails or is impossible, `Self` is returned unchanged
2820    /// in the `Err` variant.
2821    pub fn convert(self, to: TangoDataType) -> Result<Self, Self> {
2822        match self {
2823            Self::Empty => match to {
2824                TangoDataType::Void => Ok(self),
2825                _ => Err(self),
2826            }
2827            Self::Boolean(v) => match to {
2828                TangoDataType::Boolean => Ok(self),
2829                TangoDataType::UChar => Ok(Self::UChar(v as _)),
2830                TangoDataType::Short => Ok(Self::Short(v as _)),
2831                TangoDataType::UShort => Ok(Self::UShort(v as _)),
2832                TangoDataType::Int |
2833                TangoDataType::Long => Ok(Self::Long(v as _)),
2834                TangoDataType::ULong => Ok(Self::ULong(v as _)),
2835                TangoDataType::Long64 => Ok(Self::Long64(v as _)),
2836                TangoDataType::ULong64 => Ok(Self::ULong64(v as _)),
2837                TangoDataType::Float => Ok(Self::Float(v as i32 as _)),
2838                TangoDataType::Double => Ok(Self::Double(v as i32 as _)),
2839                _ => Err(self)
2840            }
2841            Self::UChar(v) => match to {
2842                TangoDataType::Boolean => check_bool(v as i64).map(Self::Boolean).map_err(|_| self),
2843                TangoDataType::UChar => Ok(self),
2844                TangoDataType::Short => Ok(Self::Short(v as _)),
2845                TangoDataType::UShort => Ok(Self::Short(v as _)),
2846                TangoDataType::Int |
2847                TangoDataType::Long => Ok(Self::Long(v as _)),
2848                TangoDataType::ULong => Ok(Self::ULong(v as _)),
2849                TangoDataType::Long64 => Ok(Self::Long64(v as _)),
2850                TangoDataType::ULong64 => Ok(Self::ULong64(v as _)),
2851                TangoDataType::Float => Ok(Self::Float(v as _)),
2852                TangoDataType::Double => Ok(Self::Double(v as _)),
2853                _ => Err(self)
2854            }
2855            Self::Short(v) => match to {
2856                TangoDataType::Boolean => check_bool(v as i64).map(Self::Boolean).map_err(|_| self),
2857                TangoDataType::UChar => v.try_into().map(Self::UChar).map_err(|_| self),
2858                TangoDataType::Short => Ok(self),
2859                TangoDataType::UShort => v.try_into().map(Self::UShort).map_err(|_| self),
2860                TangoDataType::Int |
2861                TangoDataType::Long => Ok(Self::Long(v as _)),
2862                TangoDataType::ULong => Ok(Self::ULong(v as _)),
2863                TangoDataType::Long64 => Ok(Self::Long64(v as _)),
2864                TangoDataType::ULong64 => Ok(Self::ULong64(v as _)),
2865                TangoDataType::Float => Ok(Self::Float(v as _)),
2866                TangoDataType::Double => Ok(Self::Double(v as _)),
2867                _ => Err(self)
2868            }
2869            Self::UShort(v) => match to {
2870                TangoDataType::Boolean => check_bool(v as i64).map(Self::Boolean).map_err(|_| self),
2871                TangoDataType::UChar => v.try_into().map(Self::UChar).map_err(|_| self),
2872                TangoDataType::Short => v.try_into().map(Self::Short).map_err(|_| self),
2873                TangoDataType::UShort => Ok(self),
2874                TangoDataType::Int |
2875                TangoDataType::Long => Ok(Self::Long(v as _)),
2876                TangoDataType::ULong => Ok(Self::ULong(v as _)),
2877                TangoDataType::Long64 => Ok(Self::Long64(v as _)),
2878                TangoDataType::ULong64 => Ok(Self::ULong64(v as _)),
2879                TangoDataType::Float => Ok(Self::Float(v as _)),
2880                TangoDataType::Double => Ok(Self::Double(v as _)),
2881                _ => Err(self)
2882            }
2883            Self::Long(v) => match to {
2884                TangoDataType::Boolean => check_bool(v as i64).map(Self::Boolean).map_err(|_| self),
2885                TangoDataType::UChar => v.try_into().map(Self::UChar).map_err(|_| self),
2886                TangoDataType::Short => v.try_into().map(Self::Short).map_err(|_| self),
2887                TangoDataType::UShort => v.try_into().map(Self::UShort).map_err(|_| self),
2888                TangoDataType::Int |
2889                TangoDataType::Long => Ok(self),
2890                TangoDataType::ULong => v.try_into().map(Self::ULong).map_err(|_| self),
2891                TangoDataType::Long64 => Ok(Self::Long64(v as _)),
2892                TangoDataType::ULong64 => Ok(Self::ULong64(v as _)),
2893                TangoDataType::Float => Ok(Self::Float(v as _)),
2894                TangoDataType::Double => Ok(Self::Double(v as _)),
2895                _ => Err(self)
2896            }
2897            Self::ULong(v) => match to {
2898                TangoDataType::Boolean => check_bool(v as i64).map(Self::Boolean).map_err(|_| self),
2899                TangoDataType::UChar => v.try_into().map(Self::UChar).map_err(|_| self),
2900                TangoDataType::Short => v.try_into().map(Self::Short).map_err(|_| self),
2901                TangoDataType::UShort => v.try_into().map(Self::UShort).map_err(|_| self),
2902                TangoDataType::Int |
2903                TangoDataType::Long => v.try_into().map(Self::Long).map_err(|_| self),
2904                TangoDataType::ULong => Ok(self),
2905                TangoDataType::Long64 => Ok(Self::Long64(v as _)),
2906                TangoDataType::ULong64 => Ok(Self::ULong64(v as _)),
2907                TangoDataType::Float => Ok(Self::Float(v as _)),
2908                TangoDataType::Double => Ok(Self::Double(v as _)),
2909                _ => Err(self)
2910            }
2911            Self::Long64(v) => match to {
2912                TangoDataType::Boolean => check_bool(v as i64).map(Self::Boolean).map_err(|_| self),
2913                TangoDataType::UChar => v.try_into().map(Self::UChar).map_err(|_| self),
2914                TangoDataType::Short => v.try_into().map(Self::Short).map_err(|_| self),
2915                TangoDataType::UShort => v.try_into().map(Self::UShort).map_err(|_| self),
2916                TangoDataType::Int |
2917                TangoDataType::Long => v.try_into().map(Self::Long).map_err(|_| self),
2918                TangoDataType::ULong => v.try_into().map(Self::ULong).map_err(|_| self),
2919                TangoDataType::Long64 => Ok(self),
2920                TangoDataType::ULong64 => v.try_into().map(Self::ULong64).map_err(|_| self),
2921                TangoDataType::Float => Ok(Self::Float(v as _)),
2922                TangoDataType::Double => Ok(Self::Double(v as _)),
2923                _ => Err(self)
2924            }
2925            Self::ULong64(v) => match to {
2926                TangoDataType::Boolean => check_bool(v as i64).map(Self::Boolean).map_err(|_| self),
2927                TangoDataType::UChar => v.try_into().map(Self::UChar).map_err(|_| self),
2928                TangoDataType::Short => v.try_into().map(Self::Short).map_err(|_| self),
2929                TangoDataType::UShort => v.try_into().map(Self::UShort).map_err(|_| self),
2930                TangoDataType::Int |
2931                TangoDataType::Long => v.try_into().map(Self::Long).map_err(|_| self),
2932                TangoDataType::ULong => v.try_into().map(Self::ULong).map_err(|_| self),
2933                TangoDataType::Long64 => v.try_into().map(Self::Long64).map_err(|_| self),
2934                TangoDataType::ULong64 => Ok(self),
2935                TangoDataType::Float => Ok(Self::Float(v as _)),
2936                TangoDataType::Double => Ok(Self::Double(v as _)),
2937                _ => Err(self)
2938            }
2939            Self::Float(v) => match to {
2940                TangoDataType::Float => Ok(self),
2941                TangoDataType::Double => Ok(Self::Double(v as _)),
2942                _ => Err(self)
2943            }
2944            Self::Double(v) => match to {
2945                TangoDataType::Float => Ok(Self::Float(v as _)),
2946                TangoDataType::Double => Ok(self),
2947                _ => Err(self)
2948            }
2949            Self::String(_) => match to {
2950                TangoDataType::ConstString |
2951                TangoDataType::String => Ok(self),
2952                _ => Err(self)
2953            }
2954            Self::ShortArray(v) => match to {
2955                TangoDataType::ShortArray => Ok(Self::ShortArray(v)),
2956                TangoDataType::UShortArray => v.iter().map(|&v| v.try_into())
2957                                                    .collect::<Result<Vec<_>, _>>()
2958                                                    .map(Self::UShortArray)
2959                                                    .map_err(|_| Self::ShortArray(v)),
2960                TangoDataType::LongArray => Ok(Self::LongArray(v.into_iter().map(|v| v as _).collect())),
2961                TangoDataType::ULongArray => Ok(Self::ULongArray(v.into_iter().map(|v| v as _).collect())),
2962                TangoDataType::Long64Array => Ok(Self::Long64Array(v.into_iter().map(|v| v as _).collect())),
2963                TangoDataType::ULong64Array => Ok(Self::ULong64Array(v.into_iter().map(|v| v as _).collect())),
2964                TangoDataType::FloatArray => Ok(Self::FloatArray(v.into_iter().map(|v| v as _).collect())),
2965                TangoDataType::DoubleArray => Ok(Self::DoubleArray(v.into_iter().map(|v| v as _).collect())),
2966                TangoDataType::StringArray if v.len() == 0 => Ok(Self::StringArray(vec![])),
2967                _ => Err(Self::ShortArray(v)),
2968            }
2969            Self::UShortArray(v) => match to {
2970                TangoDataType::ShortArray => v.iter().map(|&v| v.try_into())
2971                                                    .collect::<Result<Vec<_>, _>>()
2972                                                    .map(Self::ShortArray)
2973                                                    .map_err(|_| Self::UShortArray(v)),
2974                TangoDataType::UShortArray => Ok(Self::UShortArray(v)),
2975                TangoDataType::LongArray => Ok(Self::LongArray(v.into_iter().map(|v| v as _).collect())),
2976                TangoDataType::ULongArray => Ok(Self::ULongArray(v.into_iter().map(|v| v as _).collect())),
2977                TangoDataType::Long64Array => Ok(Self::Long64Array(v.into_iter().map(|v| v as _).collect())),
2978                TangoDataType::ULong64Array => Ok(Self::ULong64Array(v.into_iter().map(|v| v as _).collect())),
2979                TangoDataType::FloatArray => Ok(Self::FloatArray(v.into_iter().map(|v| v as _).collect())),
2980                TangoDataType::DoubleArray => Ok(Self::DoubleArray(v.into_iter().map(|v| v as _).collect())),
2981                TangoDataType::StringArray if v.len() == 0 => Ok(Self::StringArray(vec![])),
2982                _ => Err(Self::UShortArray(v)),
2983            }
2984            Self::LongArray(v) => match to {
2985                TangoDataType::ShortArray => v.iter().map(|&v| v.try_into())
2986                                                    .collect::<Result<Vec<_>, _>>()
2987                                                    .map(Self::ShortArray)
2988                                                    .map_err(|_| Self::LongArray(v)),
2989                TangoDataType::UShortArray => v.iter().map(|&v| v.try_into())
2990                                                    .collect::<Result<Vec<_>, _>>()
2991                                                    .map(Self::UShortArray)
2992                                                    .map_err(|_| Self::LongArray(v)),
2993                TangoDataType::LongArray => Ok(Self::LongArray(v)),
2994                TangoDataType::ULongArray => v.iter().map(|&v| v.try_into())
2995                                                    .collect::<Result<Vec<_>, _>>()
2996                                                    .map(Self::ULongArray)
2997                                                    .map_err(|_| Self::LongArray(v)),
2998                TangoDataType::Long64Array => Ok(Self::Long64Array(v.into_iter().map(|v| v as _).collect())),
2999                TangoDataType::ULong64Array => Ok(Self::ULong64Array(v.into_iter().map(|v| v as _).collect())),
3000                TangoDataType::FloatArray => Ok(Self::FloatArray(v.into_iter().map(|v| v as _).collect())),
3001                TangoDataType::DoubleArray => Ok(Self::DoubleArray(v.into_iter().map(|v| v as _).collect())),
3002                TangoDataType::StringArray if v.len() == 0 => Ok(Self::StringArray(vec![])),
3003                _ => Err(Self::LongArray(v)),
3004            }
3005            Self::ULongArray(v) => match to {
3006                TangoDataType::ShortArray => v.iter().map(|&v| v.try_into())
3007                                                    .collect::<Result<Vec<_>, _>>()
3008                                                    .map(Self::ShortArray)
3009                                                    .map_err(|_| Self::ULongArray(v)),
3010                TangoDataType::UShortArray => v.iter().map(|&v| v.try_into())
3011                                                    .collect::<Result<Vec<_>, _>>()
3012                                                    .map(Self::UShortArray)
3013                                                    .map_err(|_| Self::ULongArray(v)),
3014                TangoDataType::LongArray => v.iter().map(|&v| v.try_into())
3015                                                    .collect::<Result<Vec<_>, _>>()
3016                                                    .map(Self::LongArray)
3017                                                    .map_err(|_| Self::ULongArray(v)),
3018                TangoDataType::ULongArray => Ok(Self::ULongArray(v)),
3019                TangoDataType::Long64Array => Ok(Self::Long64Array(v.into_iter().map(|v| v as _).collect())),
3020                TangoDataType::ULong64Array => Ok(Self::ULong64Array(v.into_iter().map(|v| v as _).collect())),
3021                TangoDataType::FloatArray => Ok(Self::FloatArray(v.into_iter().map(|v| v as _).collect())),
3022                TangoDataType::DoubleArray => Ok(Self::DoubleArray(v.into_iter().map(|v| v as _).collect())),
3023                TangoDataType::StringArray if v.len() == 0 => Ok(Self::StringArray(vec![])),
3024                _ => Err(Self::ULongArray(v)),
3025            }
3026            Self::Long64Array(v) => match to {
3027                TangoDataType::ShortArray => v.iter().map(|&v| v.try_into())
3028                                                    .collect::<Result<Vec<_>, _>>()
3029                                                    .map(Self::ShortArray)
3030                                                    .map_err(|_| Self::Long64Array(v)),
3031                TangoDataType::UShortArray => v.iter().map(|&v| v.try_into())
3032                                                    .collect::<Result<Vec<_>, _>>()
3033                                                    .map(Self::UShortArray)
3034                                                    .map_err(|_| Self::Long64Array(v)),
3035                TangoDataType::LongArray => v.iter().map(|&v| v.try_into())
3036                                                    .collect::<Result<Vec<_>, _>>()
3037                                                    .map(Self::LongArray)
3038                                                    .map_err(|_| Self::Long64Array(v)),
3039                TangoDataType::ULongArray => v.iter().map(|&v| v.try_into())
3040                                                    .collect::<Result<Vec<_>, _>>()
3041                                                    .map(Self::ULongArray)
3042                                                    .map_err(|_| Self::Long64Array(v)),
3043                TangoDataType::Long64Array => Ok(Self::Long64Array(v)),
3044                TangoDataType::ULong64Array => v.iter().map(|&v| v.try_into())
3045                                                    .collect::<Result<Vec<_>, _>>()
3046                                                    .map(Self::ULong64Array)
3047                                                    .map_err(|_| Self::Long64Array(v)),
3048                TangoDataType::FloatArray => Ok(Self::FloatArray(v.into_iter().map(|v| v as _).collect())),
3049                TangoDataType::DoubleArray => Ok(Self::DoubleArray(v.into_iter().map(|v| v as _).collect())),
3050                TangoDataType::StringArray if v.len() == 0 => Ok(Self::StringArray(vec![])),
3051                _ => Err(Self::Long64Array(v)),
3052            }
3053            Self::ULong64Array(v) => match to {
3054                TangoDataType::ShortArray => v.iter().map(|&v| v.try_into())
3055                                                    .collect::<Result<Vec<_>, _>>()
3056                                                    .map(Self::ShortArray)
3057                                                    .map_err(|_| Self::ULong64Array(v)),
3058                TangoDataType::UShortArray => v.iter().map(|&v| v.try_into())
3059                                                    .collect::<Result<Vec<_>, _>>()
3060                                                    .map(Self::UShortArray)
3061                                                    .map_err(|_| Self::ULong64Array(v)),
3062                TangoDataType::LongArray => v.iter().map(|&v| v.try_into())
3063                                                    .collect::<Result<Vec<_>, _>>()
3064                                                    .map(Self::LongArray)
3065                                                    .map_err(|_| Self::ULong64Array(v)),
3066                TangoDataType::ULongArray => v.iter().map(|&v| v.try_into())
3067                                                    .collect::<Result<Vec<_>, _>>()
3068                                                    .map(Self::ULongArray)
3069                                                    .map_err(|_| Self::ULong64Array(v)),
3070                TangoDataType::Long64Array => v.iter().map(|&v| v.try_into())
3071                                                    .collect::<Result<Vec<_>, _>>()
3072                                                    .map(Self::Long64Array)
3073                                                    .map_err(|_| Self::ULong64Array(v)),
3074                TangoDataType::ULong64Array => Ok(Self::ULong64Array(v)),
3075                TangoDataType::FloatArray => Ok(Self::FloatArray(v.into_iter().map(|v| v as _).collect())),
3076                TangoDataType::DoubleArray => Ok(Self::DoubleArray(v.into_iter().map(|v| v as _).collect())),
3077                TangoDataType::StringArray if v.len() == 0 => Ok(Self::StringArray(vec![])),
3078                _ => Err(Self::ULong64Array(v)),
3079            }
3080            Self::FloatArray(v) => match to {
3081                TangoDataType::ShortArray if v.len() == 0 => Ok(Self::ShortArray(vec![])),
3082                TangoDataType::UShortArray if v.len() == 0 => Ok(Self::UShortArray(vec![])),
3083                TangoDataType::LongArray if v.len() == 0 => Ok(Self::LongArray(vec![])),
3084                TangoDataType::ULongArray if v.len() == 0 => Ok(Self::ULongArray(vec![])),
3085                TangoDataType::Long64Array if v.len() == 0 => Ok(Self::Long64Array(vec![])),
3086                TangoDataType::ULong64Array if v.len() == 0 => Ok(Self::ULong64Array(vec![])),
3087                TangoDataType::FloatArray => Ok(Self::FloatArray(v)),
3088                TangoDataType::DoubleArray => Ok(Self::DoubleArray(v.into_iter().map(|v| v as _).collect())),
3089                TangoDataType::StringArray if v.len() == 0 => Ok(Self::StringArray(vec![])),
3090                _ => Err(Self::FloatArray(v)),
3091            }
3092            Self::DoubleArray(v) => match to {
3093                TangoDataType::ShortArray if v.len() == 0 => Ok(Self::ShortArray(vec![])),
3094                TangoDataType::UShortArray if v.len() == 0 => Ok(Self::UShortArray(vec![])),
3095                TangoDataType::LongArray if v.len() == 0 => Ok(Self::LongArray(vec![])),
3096                TangoDataType::ULongArray if v.len() == 0 => Ok(Self::ULongArray(vec![])),
3097                TangoDataType::Long64Array if v.len() == 0 => Ok(Self::Long64Array(vec![])),
3098                TangoDataType::ULong64Array if v.len() == 0 => Ok(Self::ULong64Array(vec![])),
3099                TangoDataType::FloatArray => Ok(Self::FloatArray(v.into_iter().map(|v| v as _).collect())),
3100                TangoDataType::DoubleArray => Ok(Self::DoubleArray(v)),
3101                TangoDataType::StringArray if v.len() == 0 => Ok(Self::StringArray(vec![])),
3102                _ => Err(Self::DoubleArray(v)),
3103            }
3104            Self::StringArray(v) => match to {
3105                TangoDataType::ShortArray if v.len() == 0 => Ok(Self::ShortArray(vec![])),
3106                TangoDataType::UShortArray if v.len() == 0 => Ok(Self::UShortArray(vec![])),
3107                TangoDataType::LongArray if v.len() == 0 => Ok(Self::LongArray(vec![])),
3108                TangoDataType::ULongArray if v.len() == 0 => Ok(Self::ULongArray(vec![])),
3109                TangoDataType::Long64Array if v.len() == 0 => Ok(Self::Long64Array(vec![])),
3110                TangoDataType::ULong64Array if v.len() == 0 => Ok(Self::ULong64Array(vec![])),
3111                TangoDataType::FloatArray if v.len() == 0 => Ok(Self::FloatArray(vec![])),
3112                TangoDataType::DoubleArray if v.len() == 0 => Ok(Self::DoubleArray(vec![])),
3113                TangoDataType::StringArray => Ok(Self::StringArray(v)),
3114                _ => Err(Self::StringArray(v)),
3115            }
3116        }
3117    }
3118
3119    /// Return the value if it's a bool or integral 0 or 1.  Otherwise return
3120    /// `Err(self)`.
3121    pub fn into_bool(self) -> Result<bool, Self> {
3122        match self {
3123            Self::Boolean(v) => Ok(v),
3124            Self::UChar(v) => check_bool(v as i64).map_err(|_| self),
3125            Self::Short(v) => check_bool(v as i64).map_err(|_| self),
3126            Self::UShort(v) => check_bool(v as i64).map_err(|_| self),
3127            Self::Long(v) => check_bool(v as i64).map_err(|_| self),
3128            Self::ULong(v) => check_bool(v as i64).map_err(|_| self),
3129            Self::Long64(v) => check_bool(v as i64).map_err(|_| self),
3130            Self::ULong64(v) => check_bool(v as i64).map_err(|_| self),
3131            _ => Err(self),
3132        }
3133    }
3134
3135    /// Return the value as i32 if it's an integral type and inside i32 limits.
3136    /// Otherwise return `Err(self)`.
3137    pub fn into_i32(self) -> Result<i32, Self> {
3138        match self {
3139            Self::Boolean(v) => Ok(v as i32),
3140            Self::UChar(v) => Ok(v as i32),
3141            Self::Short(v) => Ok(v as i32),
3142            Self::UShort(v) => Ok(v as i32),
3143            Self::Long(v) => Ok(v),
3144            Self::ULong(v) => v.try_into().map_err(|_| self),
3145            Self::Long64(v) => v.try_into().map_err(|_| self),
3146            Self::ULong64(v) => v.try_into().map_err(|_| self),
3147            _ => Err(self),
3148        }
3149    }
3150
3151    /// Return the value as i64 if it's a an integral type and inside i64
3152    /// limits.  Otherwise return `Err(self)`.
3153    pub fn into_i64(self) -> Result<i64, Self> {
3154        match self {
3155            Self::Boolean(v) => Ok(v as i64),
3156            Self::UChar(v) => Ok(v as i64),
3157            Self::Short(v) => Ok(v as i64),
3158            Self::UShort(v) => Ok(v as i64),
3159            Self::Long(v) => Ok(v as i64),
3160            Self::ULong(v) => Ok(v as i64),
3161            Self::Long64(v) => Ok(v),
3162            Self::ULong64(v) => v.try_into().map_err(|_| self),
3163            _ => Err(self),
3164        }
3165    }
3166
3167    /// Return the value as u32 if it's an integral type and inside u32 limits.
3168    /// Otherwise return `Err(self)`.
3169    pub fn into_u32(self) -> Result<u32, Self> {
3170        match self {
3171            Self::Boolean(v) => Ok(v as u32),
3172            Self::UChar(v) => Ok(v as u32),
3173            Self::Short(v) => Ok(v as u32),
3174            Self::UShort(v) => Ok(v as u32),
3175            Self::Long(v) => v.try_into().map_err(|_| self),
3176            Self::ULong(v) => Ok(v as u32),
3177            Self::Long64(v) => v.try_into().map_err(|_| self),
3178            Self::ULong64(v) => v.try_into().map_err(|_| self),
3179            _ => Err(self),
3180        }
3181    }
3182
3183    /// Return the value as u64 if it's an integral type and inside u64 limits.
3184    /// Otherwise return `Err(self)`.
3185    pub fn into_u64(self) -> Result<u64, Self> {
3186        match self {
3187            Self::Boolean(v) => Ok(v as u64),
3188            Self::UChar(v) => Ok(v as u64),
3189            Self::Short(v) => Ok(v as u64),
3190            Self::UShort(v) => Ok(v as u64),
3191            Self::Long(v) => Ok(v as u64),
3192            Self::ULong(v) => Ok(v as u64),
3193            Self::Long64(v) => v.try_into().map_err(|_| self),
3194            Self::ULong64(v) => Ok(v),
3195            _ => Err(self),
3196        }
3197    }
3198
3199    /// Return the value as f32 if it's a numeric type.  Otherwise return `Err(self)`.
3200    pub fn into_f32(self) -> Result<f32, Self> {
3201        match self {
3202            Self::Boolean(v) => Ok(v as i32 as f32),
3203            Self::UChar(v) => Ok(v as f32),
3204            Self::Short(v) => Ok(v as f32),
3205            Self::Long(v) => Ok(v as f32),
3206            Self::Long64(v) => Ok(v as f32),
3207            Self::UShort(v) => Ok(v as f32),
3208            Self::ULong(v) => Ok(v as f32),
3209            Self::ULong64(v) => Ok(v as f32),
3210            Self::Float(v) => Ok(v),
3211            Self::Double(v) => Ok(v as f32),
3212            _ => Err(self),
3213        }
3214    }
3215
3216    /// Return the value as f64 if it's a numeric type.  Otherwise return `Err(self)`.
3217    pub fn into_f64(self) -> Result<f64, Self> {
3218        match self {
3219            Self::Boolean(v) => Ok(v as i32 as f64),
3220            Self::UChar(v) => Ok(v as f64),
3221            Self::Short(v) => Ok(v as f64),
3222            Self::Long(v) => Ok(v as f64),
3223            Self::Long64(v) => Ok(v as f64),
3224            Self::UShort(v) => Ok(v as f64),
3225            Self::ULong(v) => Ok(v as f64),
3226            Self::ULong64(v) => Ok(v as f64),
3227            Self::Float(v) => Ok(v as f64),
3228            Self::Double(v) => Ok(v),
3229            _ => Err(self),
3230        }
3231    }
3232
3233    /// Return the value as a byte array if it's a string.  Otherwise return
3234    /// `Err(self)`.
3235    pub fn into_bytes(self) -> Result<Vec<u8>, Self> {
3236        match self {
3237            Self::String(s) => Ok(s),
3238            _ => Err(self),
3239        }
3240    }
3241
3242    /// Return the value as a string if it's a string and decodable as UTF-8.
3243    /// Otherwise return `Err(self)`.
3244    pub fn into_string(self) -> Result<String, Self> {
3245        match self {
3246            Self::String(s) => String::from_utf8(s).map_err(
3247                |e| Self::String(e.into_bytes())),
3248            _ => Err(self),
3249        }
3250    }
3251}
3252
3253impl fmt::Display for PropertyValue {
3254    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3255        match self {
3256            Self::Empty => f.pad("<Empty>"),
3257            Self::Boolean(v) => fmt::Display::fmt(&v, f),
3258            Self::UChar(v) => fmt::Display::fmt(&v, f),
3259            Self::Short(v) => fmt::Display::fmt(&v, f),
3260            Self::UShort(v) => fmt::Display::fmt(&v, f),
3261            Self::Long(v) => fmt::Display::fmt(&v, f),
3262            Self::ULong(v) => fmt::Display::fmt(&v, f),
3263            Self::Long64(v) => fmt::Display::fmt(&v, f),
3264            Self::ULong64(v) => fmt::Display::fmt(&v, f),
3265            Self::Float(v) => fmt::Display::fmt(&v, f),
3266            Self::Double(v) => fmt::Display::fmt(&v, f),
3267            Self::String(v) => fmt::Display::fmt(&String::from_utf8_lossy(v), f),
3268
3269            Self::ShortArray(v) => slice_display(v, |x| x, f),
3270            Self::UShortArray(v) => slice_display(v, |x| x, f),
3271            Self::LongArray(v) => slice_display(v, |x| x, f),
3272            Self::ULongArray(v) => slice_display(v, |x| x, f),
3273            Self::Long64Array(v) => slice_display(v, |x| x, f),
3274            Self::ULong64Array(v) => slice_display(v, |x| x, f),
3275            Self::FloatArray(v) => slice_display(v, |x| x, f),
3276            Self::DoubleArray(v) => slice_display(v, |x| x, f),
3277            Self::StringArray(v) => slice_display(v, |x| String::from_utf8_lossy(x), f),
3278        }
3279    }
3280}
3281
3282impl fmt::LowerHex for PropertyValue {
3283    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3284        match self {
3285            Self::Empty => f.pad("<Empty>"),
3286            Self::Boolean(v) => fmt::Display::fmt(&v, f),
3287            Self::UChar(v) => fmt::LowerHex::fmt(&v, f),
3288            Self::Short(v) => fmt::LowerHex::fmt(&v, f),
3289            Self::UShort(v) => fmt::LowerHex::fmt(&v, f),
3290            Self::Long(v) => fmt::LowerHex::fmt(&v, f),
3291            Self::ULong(v) => fmt::LowerHex::fmt(&v, f),
3292            Self::Long64(v) => fmt::LowerHex::fmt(&v, f),
3293            Self::ULong64(v) => fmt::LowerHex::fmt(&v, f),
3294            Self::Float(v) => fmt::Display::fmt(&v, f),
3295            Self::Double(v) => fmt::Display::fmt(&v, f),
3296            Self::String(v) => fmt::Display::fmt(&String::from_utf8_lossy(v), f),
3297
3298            Self::ShortArray(v) => slice_lower_hex(v, |x| x, f),
3299            Self::UShortArray(v) => slice_lower_hex(v, |x| x, f),
3300            Self::LongArray(v) => slice_lower_hex(v, |x| x, f),
3301            Self::ULongArray(v) => slice_lower_hex(v, |x| x, f),
3302            Self::Long64Array(v) => slice_lower_hex(v, |x| x, f),
3303            Self::ULong64Array(v) => slice_lower_hex(v, |x| x, f),
3304            Self::FloatArray(v) => slice_display(v, |x| x, f),
3305            Self::DoubleArray(v) => slice_display(v, |x| x, f),
3306            Self::StringArray(v) => slice_display(v, |x| String::from_utf8_lossy(x), f),
3307        }
3308    }
3309}
3310
3311impl fmt::UpperHex for PropertyValue {
3312    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3313        match self {
3314            Self::Empty => f.pad("<Empty>"),
3315            Self::Boolean(v) => fmt::Display::fmt(&v, f),
3316            Self::UChar(v) => fmt::UpperHex::fmt(&v, f),
3317            Self::Short(v) => fmt::UpperHex::fmt(&v, f),
3318            Self::UShort(v) => fmt::UpperHex::fmt(&v, f),
3319            Self::Long(v) => fmt::UpperHex::fmt(&v, f),
3320            Self::ULong(v) => fmt::UpperHex::fmt(&v, f),
3321            Self::Long64(v) => fmt::UpperHex::fmt(&v, f),
3322            Self::ULong64(v) => fmt::UpperHex::fmt(&v, f),
3323            Self::Float(v) => fmt::Display::fmt(&v, f),
3324            Self::Double(v) => fmt::Display::fmt(&v, f),
3325            Self::String(v) => fmt::Display::fmt(&String::from_utf8_lossy(v), f),
3326
3327            Self::ShortArray(v) => slice_upper_hex(v, |x| x, f),
3328            Self::UShortArray(v) => slice_upper_hex(v, |x| x, f),
3329            Self::LongArray(v) => slice_upper_hex(v, |x| x, f),
3330            Self::ULongArray(v) => slice_upper_hex(v, |x| x, f),
3331            Self::Long64Array(v) => slice_upper_hex(v, |x| x, f),
3332            Self::ULong64Array(v) => slice_upper_hex(v, |x| x, f),
3333            Self::FloatArray(v) => slice_display(v, |x| x, f),
3334            Self::DoubleArray(v) => slice_display(v, |x| x, f),
3335            Self::StringArray(v) => slice_display(v, |x| String::from_utf8_lossy(x), f),
3336        }
3337    }
3338}
3339
3340impl fmt::LowerExp for PropertyValue {
3341    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3342        match self {
3343            Self::Empty => f.pad("<Empty>"),
3344            Self::Boolean(v) => fmt::Display::fmt(&v, f),
3345            Self::UChar(v) => fmt::Display::fmt(&v, f),
3346            Self::Short(v) => fmt::Display::fmt(&v, f),
3347            Self::UShort(v) => fmt::Display::fmt(&v, f),
3348            Self::Long(v) => fmt::Display::fmt(&v, f),
3349            Self::ULong(v) => fmt::Display::fmt(&v, f),
3350            Self::Long64(v) => fmt::Display::fmt(&v, f),
3351            Self::ULong64(v) => fmt::Display::fmt(&v, f),
3352            Self::Float(v) => fmt::LowerExp::fmt(&v, f),
3353            Self::Double(v) => fmt::LowerExp::fmt(&v, f),
3354            Self::String(v) => fmt::Display::fmt(&String::from_utf8_lossy(v), f),
3355
3356            Self::ShortArray(v) => slice_display(v, |x| x, f),
3357            Self::UShortArray(v) => slice_display(v, |x| x, f),
3358            Self::LongArray(v) => slice_display(v, |x| x, f),
3359            Self::ULongArray(v) => slice_display(v, |x| x, f),
3360            Self::Long64Array(v) => slice_display(v, |x| x, f),
3361            Self::ULong64Array(v) => slice_display(v, |x| x, f),
3362            Self::FloatArray(v) => slice_lower_exp(v, |x| x, f),
3363            Self::DoubleArray(v) => slice_lower_exp(v, |x| x, f),
3364            Self::StringArray(v) => slice_display(v, |x| String::from_utf8_lossy(x), f),
3365        }
3366    }
3367}
3368
3369impl fmt::UpperExp for PropertyValue {
3370    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3371        match self {
3372            Self::Empty => f.pad("<Empty>"),
3373            Self::Boolean(v) => fmt::Display::fmt(&v, f),
3374            Self::UChar(v) => fmt::Display::fmt(&v, f),
3375            Self::Short(v) => fmt::Display::fmt(&v, f),
3376            Self::UShort(v) => fmt::Display::fmt(&v, f),
3377            Self::Long(v) => fmt::Display::fmt(&v, f),
3378            Self::ULong(v) => fmt::Display::fmt(&v, f),
3379            Self::Long64(v) => fmt::Display::fmt(&v, f),
3380            Self::ULong64(v) => fmt::Display::fmt(&v, f),
3381            Self::Float(v) => fmt::UpperExp::fmt(&v, f),
3382            Self::Double(v) => fmt::UpperExp::fmt(&v, f),
3383            Self::String(v) => fmt::Display::fmt(&String::from_utf8_lossy(v), f),
3384
3385            Self::ShortArray(v) => slice_display(v, |x| x, f),
3386            Self::UShortArray(v) => slice_display(v, |x| x, f),
3387            Self::LongArray(v) => slice_display(v, |x| x, f),
3388            Self::ULongArray(v) => slice_display(v, |x| x, f),
3389            Self::Long64Array(v) => slice_display(v, |x| x, f),
3390            Self::ULong64Array(v) => slice_display(v, |x| x, f),
3391            Self::FloatArray(v) => slice_upper_exp(v, |x| x, f),
3392            Self::DoubleArray(v) => slice_upper_exp(v, |x| x, f),
3393            Self::StringArray(v) => slice_display(v, |x| String::from_utf8_lossy(x), f),
3394        }
3395    }
3396}
3397
3398
3399macro_rules! impl_slice_fmter {
3400    ($fn:ident, $tn:ident) => {
3401        fn $fn<'a, T, D: fmt::$tn>(slice: &'a [T], mkdisp: impl Fn(&'a T) -> D,
3402                                   f: &mut fmt::Formatter) -> fmt::Result {
3403            write!(f, "[")?;
3404            for (i, item) in slice.iter().enumerate() {
3405                if i != 0 {
3406                    write!(f, ", ")?;
3407                }
3408                fmt::$tn::fmt(&mkdisp(item), f)?;
3409            }
3410            write!(f, "]")
3411        }
3412    }
3413}
3414
3415impl_slice_fmter!(slice_display, Display);
3416impl_slice_fmter!(slice_lower_hex, LowerHex);
3417impl_slice_fmter!(slice_upper_hex, UpperHex);
3418impl_slice_fmter!(slice_lower_exp, LowerExp);
3419impl_slice_fmter!(slice_upper_exp, UpperExp);