Skip to main content

dmap/
types.rs

1//! Low-level data types within DMAP records.
2use crate::error::DmapError;
3use indexmap::IndexMap;
4use ndarray::ArrayD;
5use paste::paste;
6use std::cmp::PartialEq;
7use std::fmt::{Display, Formatter};
8use zerocopy::{AsBytes, ByteOrder, FromBytes, LittleEndian};
9
10type Result<T> = std::result::Result<T, DmapError>;
11
12/// Defines the fields of a record and their [`Type`].
13pub struct Fields<'a> {
14    /// The names of all fields of the record type
15    pub all_fields: Vec<&'a str>,
16    /// The name and Type of each required scalar field
17    pub scalars_required: Vec<(&'a str, Type)>,
18    /// The name and Type of each optional scalar field
19    pub scalars_optional: Vec<(&'a str, Type)>,
20    /// The name and Type of each required vector field
21    pub vectors_required: Vec<(&'a str, Type)>,
22    /// The name and Type of each optional vector field
23    pub vectors_optional: Vec<(&'a str, Type)>,
24    /// Groups of vector fields which must have identical dimensions
25    pub vector_dim_groups: Vec<Vec<&'a str>>,
26    /// The name of each field which is a data (as opposed to metadata) field
27    pub data_fields: Vec<&'a str>,
28}
29
30/// The possible data types that a scalar or vector field may have.
31///
32/// **Note**: `String` type is not supported for vector fields.
33#[derive(Debug, PartialEq, Clone)]
34pub enum Type {
35    Char,
36    Short,
37    Int,
38    Long,
39    Uchar,
40    Ushort,
41    Uint,
42    Ulong,
43    Float,
44    Double,
45    String,
46}
47impl Display for Type {
48    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
49        match self {
50            Self::Char => write!(f, "CHAR"),
51            Self::Short => write!(f, "SHORT"),
52            Self::Int => write!(f, "INT"),
53            Self::Float => write!(f, "FLOAT"),
54            Self::Double => write!(f, "DOUBLE"),
55            Self::String => write!(f, "STRING"),
56            Self::Long => write!(f, "LONG"),
57            Self::Uchar => write!(f, "UCHAR"),
58            Self::Ushort => write!(f, "USHORT"),
59            Self::Uint => write!(f, "UINT"),
60            Self::Ulong => write!(f, "ULONG"),
61        }
62    }
63}
64impl Type {
65    /// Converts from DMAP key to corresponding `Type` (see [here](https://github.com/SuperDARN/rst/blob/main/codebase/general/src.lib/dmap.1.25/include/dmap.h)).
66    /// Returns the `Type` if the key is supported, otherwise raises `DmapError`
67    pub(crate) fn from_key(key: i8) -> Result<Self> {
68        let data = match key {
69            1 => Self::Char,
70            2 => Self::Short,
71            3 => Self::Int,
72            10 => Self::Long,
73            16 => Self::Uchar,
74            17 => Self::Ushort,
75            18 => Self::Uint,
76            19 => Self::Ulong,
77            4 => Self::Float,
78            8 => Self::Double,
79            9 => Self::String,
80            x => Err(DmapError::InvalidKey(x))?,
81        };
82        Ok(data)
83    }
84    /// Returns the corresponding key for the `Type` variant.
85    pub(crate) fn key(&self) -> i8 {
86        match self {
87            Self::Char => 1,
88            Self::Short => 2,
89            Self::Int => 3,
90            Self::Long => 10,
91            Self::Uchar => 16,
92            Self::Ushort => 17,
93            Self::Uint => 18,
94            Self::Ulong => 19,
95            Self::Float => 4,
96            Self::Double => 8,
97            Self::String => 9,
98        }
99    }
100    /// The size in bytes of the data for `Type`
101    pub fn size(&self) -> usize {
102        match self {
103            Self::Char => 1,
104            Self::Short => 2,
105            Self::Int => 4,
106            Self::Long => 8,
107            Self::Uchar => 1,
108            Self::Ushort => 2,
109            Self::Uint => 4,
110            Self::Ulong => 8,
111            Self::Float => 4,
112            Self::Double => 8,
113            Self::String => 0,
114        }
115    }
116}
117
118/// A scalar field in a DMAP record.
119//#[derive(Debug, Clone, PartialEq, FromPyObject, IntoPyObject)]
120#[derive(Debug, Clone, PartialEq)]
121#[repr(C)]
122pub enum DmapScalar {
123    Char(i8),
124    Short(i16),
125    Int(i32),
126    Long(i64),
127    Uchar(u8),
128    Ushort(u16),
129    Uint(u32),
130    Ulong(u64),
131    Float(f32),
132    Double(f64),
133    String(String),
134}
135impl DmapScalar {
136    /// Gets the corresponding `Type`
137    pub(crate) fn get_type(&self) -> Type {
138        match self {
139            Self::Char(_) => Type::Char,
140            Self::Short(_) => Type::Short,
141            Self::Int(_) => Type::Int,
142            Self::Long(_) => Type::Long,
143            Self::Uchar(_) => Type::Uchar,
144            Self::Ushort(_) => Type::Ushort,
145            Self::Uint(_) => Type::Uint,
146            Self::Ulong(_) => Type::Ulong,
147            Self::Float(_) => Type::Float,
148            Self::Double(_) => Type::Double,
149            Self::String(_) => Type::String,
150        }
151    }
152
153    /// Converts `self` into a new `Type`, if possible.
154    pub(crate) fn cast_as(&self, new_type: &Type) -> Result<Self> {
155        match new_type {
156            Type::Char => Ok(Self::Char(i8::try_from(self.clone())?)),
157            Type::Short => Ok(Self::Short(i16::try_from(self.clone())?)),
158            Type::Int => Ok(Self::Int(i32::try_from(self.clone())?)),
159            Type::Long => Ok(Self::Long(i64::try_from(self.clone())?)),
160            Type::Uchar => Ok(Self::Uchar(u8::try_from(self.clone())?)),
161            Type::Ushort => Ok(Self::Ushort(u16::try_from(self.clone())?)),
162            Type::Uint => Ok(Self::Uint(u32::try_from(self.clone())?)),
163            Type::Ulong => Ok(Self::Ulong(u64::try_from(self.clone())?)),
164            Type::Float => Ok(Self::Float(f32::try_from(self.clone())?)),
165            Type::Double => Ok(Self::Double(f64::try_from(self.clone())?)),
166            Type::String => Err(DmapError::InvalidScalar(
167                "Unable to cast value to String".to_string(),
168            )),
169        }
170    }
171    /// Copies the data and metadata (`Type` key) to raw bytes
172    pub(crate) fn as_bytes(&self) -> Vec<u8> {
173        let mut bytes: Vec<u8> = DmapType::as_bytes(&self.get_type().key()).to_vec();
174        let mut data_bytes: Vec<u8> = match self {
175            Self::Char(x) => DmapType::as_bytes(x),
176            Self::Short(x) => DmapType::as_bytes(x),
177            Self::Int(x) => DmapType::as_bytes(x),
178            Self::Long(x) => DmapType::as_bytes(x),
179            Self::Uchar(x) => DmapType::as_bytes(x),
180            Self::Ushort(x) => DmapType::as_bytes(x),
181            Self::Uint(x) => DmapType::as_bytes(x),
182            Self::Ulong(x) => DmapType::as_bytes(x),
183            Self::Float(x) => DmapType::as_bytes(x),
184            Self::Double(x) => DmapType::as_bytes(x),
185            Self::String(x) => DmapType::as_bytes(x),
186        };
187        bytes.append(&mut data_bytes);
188        bytes
189    }
190}
191impl Display for DmapScalar {
192    fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
193        match self {
194            Self::Char(x) => write!(f, "CHAR {x}"),
195            Self::Short(x) => write!(f, "SHORT {x}"),
196            Self::Int(x) => write!(f, "INT {x}"),
197            Self::Float(x) => write!(f, "FLOAT {x}"),
198            Self::Double(x) => write!(f, "DOUBLE {x}"),
199            Self::String(x) => write!(f, "STRING {x}"),
200            Self::Long(x) => write!(f, "LONG {x}"),
201            Self::Uchar(x) => write!(f, "UCHAR {x}"),
202            Self::Ushort(x) => write!(f, "USHORT {x}"),
203            Self::Uint(x) => write!(f, "UINT {x}"),
204            Self::Ulong(x) => write!(f, "ULONG {x}"),
205        }
206    }
207}
208
209macro_rules! vec_to_bytes {
210    ($bytes:ident, $x:ident) => {{
211        $bytes.extend(($x.ndim() as i32).to_le_bytes());
212        for &dim in $x.shape().iter().rev() {
213            $bytes.extend((dim as i32).to_le_bytes());
214        }
215        for y in $x.iter() {
216            $bytes.append(&mut DmapType::as_bytes(y).to_vec());
217        }
218    }};
219}
220
221/// A vector field in a DMAP record.
222#[derive(Clone, Debug, PartialEq)]
223pub enum DmapVec {
224    Char(ArrayD<i8>),
225    Short(ArrayD<i16>),
226    Int(ArrayD<i32>),
227    Long(ArrayD<i64>),
228    Uchar(ArrayD<u8>),
229    Ushort(ArrayD<u16>),
230    Uint(ArrayD<u32>),
231    Ulong(ArrayD<u64>),
232    Float(ArrayD<f32>),
233    Double(ArrayD<f64>),
234}
235impl DmapVec {
236    /// Gets the corresponding [`Type`] of the vector.
237    #[inline]
238    pub(crate) fn get_type(&self) -> Type {
239        match self {
240            DmapVec::Char(_) => Type::Char,
241            DmapVec::Short(_) => Type::Short,
242            DmapVec::Int(_) => Type::Int,
243            DmapVec::Long(_) => Type::Long,
244            DmapVec::Uchar(_) => Type::Uchar,
245            DmapVec::Ushort(_) => Type::Ushort,
246            DmapVec::Uint(_) => Type::Uint,
247            DmapVec::Ulong(_) => Type::Ulong,
248            DmapVec::Float(_) => Type::Float,
249            DmapVec::Double(_) => Type::Double,
250        }
251    }
252    /// Copies the data and metadata (dimensions, [`Type`] key) to raw bytes
253    #[inline]
254    pub(crate) fn as_bytes(&self) -> Vec<u8> {
255        let mut bytes: Vec<u8> = DmapType::as_bytes(&self.get_type().key()).to_vec();
256        match self {
257            DmapVec::Char(x) => vec_to_bytes!(bytes, x),
258            DmapVec::Short(x) => vec_to_bytes!(bytes, x),
259            DmapVec::Int(x) => vec_to_bytes!(bytes, x),
260            DmapVec::Long(x) => vec_to_bytes!(bytes, x),
261            DmapVec::Uchar(x) => vec_to_bytes!(bytes, x),
262            DmapVec::Ushort(x) => vec_to_bytes!(bytes, x),
263            DmapVec::Uint(x) => vec_to_bytes!(bytes, x),
264            DmapVec::Ulong(x) => vec_to_bytes!(bytes, x),
265            DmapVec::Float(x) => vec_to_bytes!(bytes, x),
266            DmapVec::Double(x) => vec_to_bytes!(bytes, x),
267        };
268        bytes
269    }
270
271    /// Gets the dimensions of the vector, in row-major order.
272    /// ## Example
273    /// ```
274    /// use ndarray::array;
275    /// use dmap::types::DmapVec;
276    ///
277    /// let arr = DmapVec::Char(array![0, 1, 2, 3, 4].into_dyn());
278    /// assert_eq!(arr.shape(), &[5]);
279    ///
280    /// let arr = DmapVec::Uint(array![[0, 1, 2], [3, 4, 5]].into_dyn());
281    /// assert_eq!(arr.shape(), &[2, 3]);
282    /// ```
283    #[must_use]
284    pub fn shape(&self) -> &[usize] {
285        match self {
286            DmapVec::Char(x) => x.shape(),
287            DmapVec::Short(x) => x.shape(),
288            DmapVec::Int(x) => x.shape(),
289            DmapVec::Long(x) => x.shape(),
290            DmapVec::Uchar(x) => x.shape(),
291            DmapVec::Ushort(x) => x.shape(),
292            DmapVec::Uint(x) => x.shape(),
293            DmapVec::Ulong(x) => x.shape(),
294            DmapVec::Float(x) => x.shape(),
295            DmapVec::Double(x) => x.shape(),
296        }
297    }
298}
299
300/// Generates trait implementations for infallible conversion into [`DmapVec`] and fallible conversion
301/// back.
302///
303/// Example: `vec_impls!(ArrayD<i8>, DmapVec::Char)` will generate `impl From<ArrayD<i8>> for
304/// DmapVec` and `impl TryFrom<DmapVec> for ArrayD<i8>` code blocks.
305macro_rules! vec_impls {
306    ($type:ty, $enum_var:path) => {
307        impl From<$type> for DmapVec {
308            #[inline]
309            fn from(value: $type) -> Self {
310                $enum_var(value)
311            }
312        }
313
314        impl TryFrom<DmapVec> for $type {
315            type Error = DmapError;
316
317            fn try_from(value: DmapVec) -> std::result::Result<Self, Self::Error> {
318                if let $enum_var(x) = value {
319                    Ok(x)
320                } else {
321                    Err(DmapError::InvalidVector(format!(
322                        "Cannot convert to {}",
323                        stringify!($type)
324                    )))
325                }
326            }
327        }
328
329        impl From<$type> for DmapField {
330            #[inline]
331            fn from(value: $type) -> Self {
332                DmapField::Vector($enum_var(value))
333            }
334        }
335
336        impl TryFrom<DmapField> for $type {
337            type Error = DmapError;
338
339            fn try_from(value: DmapField) -> std::result::Result<Self, Self::Error> {
340                match value {
341                    DmapField::Vector(x) => x.try_into(),
342                    _ => Err(Self::Error::InvalidVector(format!(
343                        "Cannot interpret as {}",
344                        stringify!($type)
345                    ))),
346                }
347            }
348        }
349    };
350}
351
352vec_impls!(ArrayD<i8>, DmapVec::Char);
353vec_impls!(ArrayD<i16>, DmapVec::Short);
354vec_impls!(ArrayD<i32>, DmapVec::Int);
355vec_impls!(ArrayD<i64>, DmapVec::Long);
356vec_impls!(ArrayD<u8>, DmapVec::Uchar);
357vec_impls!(ArrayD<u16>, DmapVec::Ushort);
358vec_impls!(ArrayD<u32>, DmapVec::Uint);
359vec_impls!(ArrayD<u64>, DmapVec::Ulong);
360vec_impls!(ArrayD<f32>, DmapVec::Float);
361vec_impls!(ArrayD<f64>, DmapVec::Double);
362
363/// A generic field of a DMAP record.
364///
365/// This is the type that is stored in a DMAP record, representing either a scalar or
366/// vector field.
367#[derive(Debug, Clone, PartialEq)]
368#[repr(C)]
369pub enum DmapField {
370    Vector(DmapVec),
371    Scalar(DmapScalar),
372}
373impl DmapField {
374    /// Converts the field and metadata (`Type` key and dimensions if applicable) to raw bytes.
375    #[inline]
376    #[must_use]
377    pub fn as_bytes(&self) -> Vec<u8> {
378        match self {
379            Self::Scalar(x) => x.as_bytes(),
380            Self::Vector(x) => x.as_bytes(),
381        }
382    }
383}
384
385/// Macro for implementing conversion traits between primitives and [`DmapField`], [`DmapScalar`]
386/// types.
387///
388/// Example: `scalar_impls(i8, DmapScalar::Char)` will implement:
389///   `From<i8> for DmapField`
390///   `TryFrom<DmapField> for i8`
391macro_rules! scalar_impls {
392    ($type:ty, $enum_var:path, $type_var:path) => {
393        impl From<$type> for DmapField {
394            fn from(value: $type) -> Self {
395                DmapField::Scalar($enum_var(value))
396            }
397        }
398        impl TryFrom<DmapField> for $type {
399            type Error = DmapError;
400
401            fn try_from(value: DmapField) -> std::result::Result<Self, Self::Error> {
402                match value {
403                    DmapField::Scalar(x) => x.try_into(),
404                    _ => Err(Self::Error::InvalidScalar(format!(
405                        "Cannot interpret {value:?} as {}",
406                        stringify!($type)
407                    ))),
408                }
409            }
410        }
411    };
412}
413
414scalar_impls!(i8, DmapScalar::Char, Type::Char);
415scalar_impls!(i16, DmapScalar::Short, Type::Short);
416scalar_impls!(i32, DmapScalar::Int, Type::Int);
417scalar_impls!(i64, DmapScalar::Long, Type::Long);
418scalar_impls!(u8, DmapScalar::Uchar, Type::Uchar);
419scalar_impls!(u16, DmapScalar::Ushort, Type::Ushort);
420scalar_impls!(u32, DmapScalar::Uint, Type::Uint);
421scalar_impls!(u64, DmapScalar::Ulong, Type::Ulong);
422scalar_impls!(f32, DmapScalar::Float, Type::Float);
423scalar_impls!(f64, DmapScalar::Double, Type::Double);
424scalar_impls!(String, DmapScalar::String, Type::String);
425
426/// Trait for raw types that can be stored in DMAP files.
427pub trait DmapType: std::fmt::Debug {
428    /// Size in bytes of the type.
429    fn size() -> usize
430    where
431        Self: Sized;
432    /// Create a copy of the data as raw bytes.
433    fn as_bytes(&self) -> Vec<u8>;
434    /// Convert raw bytes to `Self`
435    ///
436    /// # Errors
437    /// If the bytes are not a valid DMAP record of type `Self`.
438    fn from_bytes(bytes: &[u8]) -> Result<Self>
439    where
440        Self: Sized;
441    /// Get the `Type` variant that represents `self`
442    fn dmap_type() -> Type;
443}
444
445/// Macro for implementing [`DmapType`] trait for primitive types.
446/// Example: `type_impls!(i8, Type::Char, 1)`
447macro_rules! type_impls {
448    // This variant captures single-byte types
449    ($type:ty, $enum_var:path, 1) => {
450        impl DmapType for $type {
451            #[inline]
452            fn size() -> usize { 1 }
453
454            #[inline]
455            fn as_bytes(&self) -> Vec<u8> {
456                AsBytes::as_bytes(self).to_vec()
457            }
458
459            #[inline]
460            fn from_bytes(bytes: &[u8]) -> Result<Self>
461            where
462                Self: Sized,
463            {
464                Self::read_from(bytes).ok_or(DmapError::CorruptStream("Unable to interpret bytes"))
465            }
466
467            #[inline]
468            fn dmap_type() -> Type { $enum_var }
469        }
470    };
471    // This variant captures multi-byte primitive types
472    ($type:ty, $enum_var:path, $num_bytes:expr) => {
473        paste! {
474            impl DmapType for $type {
475                #[inline]
476                fn size() -> usize { $num_bytes }
477
478                #[inline]
479                fn as_bytes(&self) -> Vec<u8> {
480                    let mut bytes = [0; $num_bytes];
481                    LittleEndian::[< write_ $type >](&mut bytes, *self);
482                    bytes.to_vec()
483                }
484
485                #[inline]
486                fn from_bytes(bytes: &[u8]) -> Result<Self>
487                where
488                    Self: Sized,
489                {
490                    Self::read_from(bytes).ok_or(DmapError::CorruptStream("Unable to interpret bytes"))
491                }
492
493                #[inline]
494                fn dmap_type() -> Type { $enum_var }
495            }
496        }
497    }
498}
499
500type_impls!(i8, Type::Char, 1);
501type_impls!(i16, Type::Short, 2);
502type_impls!(i32, Type::Int, 4);
503type_impls!(i64, Type::Long, 8);
504type_impls!(u8, Type::Uchar, 1);
505type_impls!(u16, Type::Ushort, 2);
506type_impls!(u32, Type::Uint, 4);
507type_impls!(u64, Type::Ulong, 8);
508type_impls!(f32, Type::Float, 4);
509type_impls!(f64, Type::Double, 8);
510
511// This implementation differs significantly from the others, so it doesn't use the macro
512impl DmapType for String {
513    #[inline]
514    fn size() -> usize {
515        0
516    }
517
518    #[inline]
519    fn as_bytes(&self) -> Vec<u8> {
520        let mut bytes = self.as_bytes().to_vec();
521        bytes.push(0); // null-terminate
522        bytes
523    }
524
525    #[inline]
526    fn from_bytes(bytes: &[u8]) -> Result<Self> {
527        let data = String::from_utf8(bytes.to_owned())
528            .map_err(|_| DmapError::InvalidScalar("Cannot convert bytes to String".to_string()))?;
529        Ok(data.trim_end_matches(char::from(0)).to_string())
530    }
531
532    #[inline]
533    fn dmap_type() -> Type {
534        Type::String
535    }
536}
537
538impl TryFrom<DmapScalar> for u8 {
539    type Error = DmapError;
540    fn try_from(value: DmapScalar) -> std::result::Result<Self, Self::Error> {
541        match value {
542            DmapScalar::Char(x) => Ok(u8::try_from(x)?),
543            DmapScalar::Short(x) => Ok(u8::try_from(x)?),
544            DmapScalar::Int(x) => Ok(u8::try_from(x)?),
545            DmapScalar::Long(x) => Ok(u8::try_from(x)?),
546            DmapScalar::Uchar(x) => Ok(x),
547            DmapScalar::Ushort(x) => Ok(u8::try_from(x)?),
548            DmapScalar::Uint(x) => Ok(u8::try_from(x)?),
549            DmapScalar::Ulong(x) => Ok(u8::try_from(x)?),
550            DmapScalar::Float(x) => Err(DmapError::InvalidScalar(format!(
551                "Unable to convert {x}_f32 to u8"
552            ))),
553            DmapScalar::Double(x) => Err(DmapError::InvalidScalar(format!(
554                "Unable to convert {x}_f64 to u8"
555            ))),
556            DmapScalar::String(x) => Err(DmapError::InvalidScalar(format!(
557                "Unable to convert {x} to u8"
558            ))),
559        }
560    }
561}
562impl TryFrom<DmapScalar> for u16 {
563    type Error = DmapError;
564    fn try_from(value: DmapScalar) -> std::result::Result<Self, Self::Error> {
565        match value {
566            DmapScalar::Char(x) => Ok(u16::try_from(x)?),
567            DmapScalar::Short(x) => Ok(u16::try_from(x)?),
568            DmapScalar::Int(x) => Ok(u16::try_from(x)?),
569            DmapScalar::Long(x) => Ok(u16::try_from(x)?),
570            DmapScalar::Uchar(x) => Ok(x as u16),
571            DmapScalar::Ushort(x) => Ok(x),
572            DmapScalar::Uint(x) => Ok(u16::try_from(x)?),
573            DmapScalar::Ulong(x) => Ok(u16::try_from(x)?),
574            DmapScalar::Float(x) => Err(DmapError::InvalidScalar(format!(
575                "Unable to convert {x}_f32 to u16"
576            ))),
577            DmapScalar::Double(x) => Err(DmapError::InvalidScalar(format!(
578                "Unable to convert {x}_f64 to u16"
579            ))),
580            DmapScalar::String(x) => Err(DmapError::InvalidScalar(format!(
581                "Unable to convert {x} to u16"
582            ))),
583        }
584    }
585}
586impl TryFrom<DmapScalar> for u32 {
587    type Error = DmapError;
588    fn try_from(value: DmapScalar) -> std::result::Result<Self, Self::Error> {
589        match value {
590            DmapScalar::Char(x) => Ok(u32::try_from(x)?),
591            DmapScalar::Short(x) => Ok(u32::try_from(x)?),
592            DmapScalar::Int(x) => Ok(u32::try_from(x)?),
593            DmapScalar::Long(x) => Ok(u32::try_from(x)?),
594            DmapScalar::Uchar(x) => Ok(x as u32),
595            DmapScalar::Ushort(x) => Ok(x as u32),
596            DmapScalar::Uint(x) => Ok(x),
597            DmapScalar::Ulong(x) => Ok(u32::try_from(x)?),
598            DmapScalar::Float(x) => Err(DmapError::InvalidScalar(format!(
599                "Unable to convert {x}_f32 to u32"
600            ))),
601            DmapScalar::Double(x) => Err(DmapError::InvalidScalar(format!(
602                "Unable to convert {x}_f64 to u32"
603            ))),
604            DmapScalar::String(x) => Err(DmapError::InvalidScalar(format!(
605                "Unable to convert {x} to u32"
606            ))),
607        }
608    }
609}
610impl TryFrom<DmapScalar> for u64 {
611    type Error = DmapError;
612    fn try_from(value: DmapScalar) -> std::result::Result<Self, Self::Error> {
613        match value {
614            DmapScalar::Char(x) => Ok(u64::try_from(x)?),
615            DmapScalar::Short(x) => Ok(u64::try_from(x)?),
616            DmapScalar::Int(x) => Ok(u64::try_from(x)?),
617            DmapScalar::Long(x) => Ok(u64::try_from(x)?),
618            DmapScalar::Uchar(x) => Ok(x as u64),
619            DmapScalar::Ushort(x) => Ok(x as u64),
620            DmapScalar::Uint(x) => Ok(x as u64),
621            DmapScalar::Ulong(x) => Ok(x),
622            DmapScalar::Float(x) => Err(DmapError::InvalidScalar(format!(
623                "Unable to convert {x}_f32 to u64"
624            ))),
625            DmapScalar::Double(x) => Err(DmapError::InvalidScalar(format!(
626                "Unable to convert {x}_f64 to u64"
627            ))),
628            DmapScalar::String(x) => Err(DmapError::InvalidScalar(format!(
629                "Unable to convert {x} to u64"
630            ))),
631        }
632    }
633}
634impl TryFrom<DmapScalar> for i8 {
635    type Error = DmapError;
636    fn try_from(value: DmapScalar) -> std::result::Result<Self, Self::Error> {
637        match value {
638            DmapScalar::Char(x) => Ok(x),
639            DmapScalar::Short(x) => Ok(i8::try_from(x)?),
640            DmapScalar::Int(x) => Ok(i8::try_from(x)?),
641            DmapScalar::Long(x) => Ok(i8::try_from(x)?),
642            DmapScalar::Uchar(x) => Ok(i8::try_from(x)?),
643            DmapScalar::Ushort(x) => Ok(i8::try_from(x)?),
644            DmapScalar::Uint(x) => Ok(i8::try_from(x)?),
645            DmapScalar::Ulong(x) => Ok(i8::try_from(x)?),
646            DmapScalar::Float(x) => Err(DmapError::InvalidScalar(format!(
647                "Unable to convert {x}_f32 to i8"
648            ))),
649            DmapScalar::Double(x) => Err(DmapError::InvalidScalar(format!(
650                "Unable to convert {x}_f64 to i8"
651            ))),
652            DmapScalar::String(x) => Err(DmapError::InvalidScalar(format!(
653                "Unable to convert {x} to i8"
654            ))),
655        }
656    }
657}
658impl TryFrom<DmapScalar> for i16 {
659    type Error = DmapError;
660    fn try_from(value: DmapScalar) -> std::result::Result<Self, Self::Error> {
661        match value {
662            DmapScalar::Char(x) => Ok(x as i16),
663            DmapScalar::Short(x) => Ok(x),
664            DmapScalar::Int(x) => Ok(i16::try_from(x)?),
665            DmapScalar::Long(x) => Ok(i16::try_from(x)?),
666            DmapScalar::Uchar(x) => Ok(x as i16),
667            DmapScalar::Ushort(x) => Ok(i16::try_from(x)?),
668            DmapScalar::Uint(x) => Ok(i16::try_from(x)?),
669            DmapScalar::Ulong(x) => Ok(i16::try_from(x)?),
670            DmapScalar::Float(x) => Err(DmapError::InvalidScalar(format!(
671                "Unable to convert {x}_f32 to i16"
672            ))),
673            DmapScalar::Double(x) => Err(DmapError::InvalidScalar(format!(
674                "Unable to convert {x}_f64 to i16"
675            ))),
676            DmapScalar::String(x) => Err(DmapError::InvalidScalar(format!(
677                "Unable to convert {x} to i16"
678            ))),
679        }
680    }
681}
682impl TryFrom<DmapScalar> for i32 {
683    type Error = DmapError;
684    fn try_from(value: DmapScalar) -> std::result::Result<Self, Self::Error> {
685        match value {
686            DmapScalar::Char(x) => Ok(x as i32),
687            DmapScalar::Short(x) => Ok(x as i32),
688            DmapScalar::Int(x) => Ok(x),
689            DmapScalar::Long(x) => Ok(i32::try_from(x)?),
690            DmapScalar::Uchar(x) => Ok(x as i32),
691            DmapScalar::Ushort(x) => Ok(x as i32),
692            DmapScalar::Uint(x) => Ok(i32::try_from(x)?),
693            DmapScalar::Ulong(x) => Ok(i32::try_from(x)?),
694            DmapScalar::Float(x) => Err(DmapError::InvalidScalar(format!(
695                "Unable to convert {x}_f32 to i32"
696            ))),
697            DmapScalar::Double(x) => Err(DmapError::InvalidScalar(format!(
698                "Unable to convert {x}_f64 to i32"
699            ))),
700            DmapScalar::String(x) => Err(DmapError::InvalidScalar(format!(
701                "Unable to convert {x} to i32"
702            ))),
703        }
704    }
705}
706impl TryFrom<DmapScalar> for i64 {
707    type Error = DmapError;
708    fn try_from(value: DmapScalar) -> std::result::Result<Self, Self::Error> {
709        match value {
710            DmapScalar::Char(x) => Ok(x as i64),
711            DmapScalar::Short(x) => Ok(x as i64),
712            DmapScalar::Int(x) => Ok(x as i64),
713            DmapScalar::Long(x) => Ok(x),
714            DmapScalar::Uchar(x) => Ok(x as i64),
715            DmapScalar::Ushort(x) => Ok(x as i64),
716            DmapScalar::Uint(x) => Ok(x as i64),
717            DmapScalar::Ulong(x) => Ok(i64::try_from(x)?),
718            DmapScalar::Float(x) => Err(DmapError::InvalidScalar(format!(
719                "Unable to convert {x}_f32 to i64"
720            ))),
721            DmapScalar::Double(x) => Err(DmapError::InvalidScalar(format!(
722                "Unable to convert {x}_f64 to i64"
723            ))),
724            DmapScalar::String(x) => Err(DmapError::InvalidScalar(format!(
725                "Unable to convert {x} to i64"
726            ))),
727        }
728    }
729}
730impl TryFrom<DmapScalar> for f32 {
731    type Error = DmapError;
732    fn try_from(value: DmapScalar) -> std::result::Result<Self, Self::Error> {
733        match value {
734            DmapScalar::Char(x) => Ok(x as f32),
735            DmapScalar::Short(x) => Ok(x as f32),
736            DmapScalar::Int(x) => Ok(x as f32),
737            DmapScalar::Long(x) => Ok(x as f32),
738            DmapScalar::Uchar(x) => Ok(x as f32),
739            DmapScalar::Ushort(x) => Ok(x as f32),
740            DmapScalar::Uint(x) => Ok(x as f32),
741            DmapScalar::Ulong(x) => Ok(x as f32),
742            DmapScalar::Float(x) => Ok(x),
743            DmapScalar::Double(x) => Ok(x as f32),
744            DmapScalar::String(x) => Err(DmapError::InvalidScalar(format!(
745                "Unable to convert {x} to f32"
746            ))),
747        }
748    }
749}
750impl TryFrom<DmapScalar> for f64 {
751    type Error = DmapError;
752    fn try_from(value: DmapScalar) -> std::result::Result<Self, Self::Error> {
753        match value {
754            DmapScalar::Char(x) => Ok(x as f64),
755            DmapScalar::Short(x) => Ok(x as f64),
756            DmapScalar::Int(x) => Ok(x as f64),
757            DmapScalar::Long(x) => Ok(x as f64),
758            DmapScalar::Uchar(x) => Ok(x as f64),
759            DmapScalar::Ushort(x) => Ok(x as f64),
760            DmapScalar::Uint(x) => Ok(x as f64),
761            DmapScalar::Ulong(x) => Ok(x as f64),
762            DmapScalar::Float(x) => Ok(f64::from(x)),
763            DmapScalar::Double(x) => Ok(x),
764            DmapScalar::String(x) => Err(DmapError::InvalidScalar(format!(
765                "Unable to convert {x} to f64"
766            ))),
767        }
768    }
769}
770impl TryFrom<DmapScalar> for String {
771    type Error = DmapError;
772    fn try_from(value: DmapScalar) -> std::result::Result<Self, Self::Error> {
773        match value {
774            DmapScalar::String(x) => Ok(x),
775            x => Err(DmapError::InvalidScalar(format!(
776                "Unable to convert {x} to String"
777            ))),
778        }
779    }
780}
781
782/// Verify that `name` exists in `fields` and is of the correct [`Type`].
783///
784/// # Errors
785/// If `name` is not in `fields`.
786///
787/// If `name` is in `fields`, but is not a [`DmapField::Scalar`] of `expected_type`.
788pub fn check_scalar(
789    fields: &IndexMap<String, DmapField>,
790    name: &str,
791    expected_type: &Type,
792) -> Result<()> {
793    match fields.get(name) {
794        Some(DmapField::Scalar(data)) if data.get_type() == *expected_type => Ok(()),
795        Some(DmapField::Scalar(data)) => Err(DmapError::InvalidScalar(format!(
796            "{name} is of type {}, expected {}",
797            data.get_type(),
798            expected_type
799        ))),
800        Some(_) => Err(DmapError::InvalidScalar(format!(
801            "{name} is a vector field"
802        ))),
803        None => Err(DmapError::InvalidScalar(format!("{name} is not in record"))),
804    }
805}
806
807/// If `name` is in `fields`, verify that it is of the correct [`Type`].
808///
809/// # Errors
810/// If `name` is in `fields`, but is not a [`DmapField::Scalar`] of `expected_type`.
811pub fn check_scalar_opt(
812    fields: &IndexMap<String, DmapField>,
813    name: &str,
814    expected_type: &Type,
815) -> Result<()> {
816    match fields.get(name) {
817        Some(DmapField::Scalar(data)) if data.get_type() == *expected_type => Ok(()),
818        Some(DmapField::Scalar(data)) => Err(DmapError::InvalidScalar(format!(
819            "{name} is of type {}, expected {}",
820            data.get_type(),
821            expected_type
822        ))),
823        Some(_) => Err(DmapError::InvalidScalar(format!(
824            "{name} is a vector field"
825        ))),
826        None => Ok(()),
827    }
828}
829
830/// Verify that `name` exists in `fields` and is of the correct [`Type`].
831///
832/// # Errors
833/// If `name` is not in `fields`.
834///
835/// If `name` is in `fields`, but is not a [`DmapField::Vector`] of `expected_type`.
836pub fn check_vector(
837    fields: &IndexMap<String, DmapField>,
838    name: &str,
839    expected_type: &Type,
840) -> Result<()> {
841    match fields.get(name) {
842        Some(DmapField::Vector(data)) if data.get_type() != *expected_type => {
843            Err(DmapError::InvalidVector(format!(
844                "{name} is of type {}, expected {}",
845                data.get_type(),
846                expected_type
847            )))
848        }
849        Some(DmapField::Scalar(_)) => Err(DmapError::InvalidVector(format!(
850            "{name} is a scalar field"
851        ))),
852        None => Err(DmapError::InvalidVector(format!("{name} not in record"))),
853        _ => Ok(()),
854    }
855}
856
857/// If `name` is in `fields`, verify that it is of the correct [`Type`].
858///
859/// # Errors
860/// If `name` is in `fields`, but is not a [`DmapField::Vector`] of `expected_type`.
861pub fn check_vector_opt(
862    fields: &IndexMap<String, DmapField>,
863    name: &str,
864    expected_type: &Type,
865) -> Result<()> {
866    match fields.get(name) {
867        Some(DmapField::Vector(data)) if data.get_type() != *expected_type => {
868            Err(DmapError::InvalidVector(format!(
869                "{name} is of type {}, expected {}",
870                data.get_type(),
871                expected_type
872            )))
873        }
874        Some(DmapField::Scalar(_)) => Err(DmapError::InvalidVector(format!(
875            "{name} is a scalar field"
876        ))),
877        _ => Ok(()),
878    }
879}
880
881#[cfg(test)]
882mod tests {
883    use super::*;
884    use ndarray::array;
885
886    #[test]
887    fn dmaptype() -> Result<()> {
888        assert_eq!(i8::size(), 1);
889        assert_eq!(u8::size(), 1);
890        assert_eq!(i16::size(), 2);
891        assert_eq!(u16::size(), 2);
892        assert_eq!(i32::size(), 4);
893        assert_eq!(u32::size(), 4);
894        assert_eq!(f32::size(), 4);
895        assert_eq!(i64::size(), 8);
896        assert_eq!(u64::size(), 8);
897        assert_eq!(f64::size(), 8);
898
899        assert_eq!(i8::dmap_type(), Type::Char);
900        assert_eq!(u8::dmap_type(), Type::Uchar);
901        assert_eq!(i16::dmap_type(), Type::Short);
902        assert_eq!(u16::dmap_type(), Type::Ushort);
903        assert_eq!(i32::dmap_type(), Type::Int);
904        assert_eq!(u32::dmap_type(), Type::Uint);
905        assert_eq!(f32::dmap_type(), Type::Float);
906        assert_eq!(i64::dmap_type(), Type::Long);
907        assert_eq!(u64::dmap_type(), Type::Ulong);
908        assert_eq!(f64::dmap_type(), Type::Double);
909
910        assert_eq!(vec![1], DmapType::as_bytes(&i8::from_bytes(&[1])?));
911        assert_eq!(vec![1], DmapType::as_bytes(&u8::from_bytes(&[1])?));
912        assert_eq!(vec![1, 0], DmapType::as_bytes(&i16::from_bytes(&[1, 0])?));
913        assert_eq!(vec![1, 0], DmapType::as_bytes(&u16::from_bytes(&[1, 0])?));
914        assert_eq!(
915            vec![1, 0, 0, 0],
916            DmapType::as_bytes(&i32::from_bytes(&[1, 0, 0, 0])?)
917        );
918        assert_eq!(
919            vec![1, 2, 3, 4],
920            DmapType::as_bytes(&u32::from_bytes(&[1, 2, 3, 4])?)
921        );
922        assert_eq!(
923            vec![1, 0, 0, 0],
924            DmapType::as_bytes(&f32::from_bytes(&[1, 0, 0, 0])?)
925        );
926        assert_eq!(
927            vec![1, 2, 3, 4, 5, 6, 7, 8],
928            DmapType::as_bytes(&u64::from_bytes(&[1, 2, 3, 4, 5, 6, 7, 8])?)
929        );
930        assert_eq!(
931            vec![1, 0, 0, 0, 1, 2, 3, 4],
932            DmapType::as_bytes(&i64::from_bytes(&[1, 0, 0, 0, 1, 2, 3, 4])?)
933        );
934        assert_eq!(
935            vec![1, 2, 3, 4, 4, 32, 2, 1],
936            DmapType::as_bytes(&f64::from_bytes(&[1, 2, 3, 4, 4, 32, 2, 1])?)
937        );
938        Ok(())
939    }
940
941    #[test]
942    fn types() -> Result<()> {
943        assert_eq!(Type::from_key(1)?, Type::Char);
944        assert_eq!(Type::from_key(2)?, Type::Short);
945        assert_eq!(Type::from_key(3)?, Type::Int);
946        assert_eq!(Type::from_key(10)?, Type::Long);
947        assert_eq!(Type::from_key(16)?, Type::Uchar);
948        assert_eq!(Type::from_key(17)?, Type::Ushort);
949        assert_eq!(Type::from_key(18)?, Type::Uint);
950        assert_eq!(Type::from_key(19)?, Type::Ulong);
951        assert_eq!(Type::from_key(4)?, Type::Float);
952        assert_eq!(Type::from_key(8)?, Type::Double);
953        assert_eq!(Type::from_key(9)?, Type::String);
954        assert!(Type::from_key(-1).is_err());
955        assert!(Type::from_key(15).is_err());
956        assert!(Type::from_key(0).is_err());
957
958        assert_eq!(Type::Char.key(), 1);
959        assert_eq!(Type::Short.key(), 2);
960        assert_eq!(Type::Int.key(), 3);
961        assert_eq!(Type::Long.key(), 10);
962        assert_eq!(Type::Uchar.key(), 16);
963        assert_eq!(Type::Ushort.key(), 17);
964        assert_eq!(Type::Uint.key(), 18);
965        assert_eq!(Type::Ulong.key(), 19);
966        assert_eq!(Type::Float.key(), 4);
967        assert_eq!(Type::Double.key(), 8);
968        assert_eq!(Type::String.key(), 9);
969
970        assert_eq!(Type::Char.size(), 1);
971        assert_eq!(Type::Short.size(), 2);
972        assert_eq!(Type::Int.size(), 4);
973        assert_eq!(Type::Long.size(), 8);
974        assert_eq!(Type::Uchar.size(), 1);
975        assert_eq!(Type::Ushort.size(), 2);
976        assert_eq!(Type::Uint.size(), 4);
977        assert_eq!(Type::Ulong.size(), 8);
978        assert_eq!(Type::Float.size(), 4);
979        assert_eq!(Type::Double.size(), 8);
980        assert_eq!(Type::String.size(), 0);
981
982        Ok(())
983    }
984
985    #[test]
986    fn dmapscalar() -> Result<()> {
987        assert_eq!(DmapScalar::Char(0).get_type(), Type::Char);
988        assert_eq!(DmapScalar::Short(0).get_type(), Type::Short);
989        assert_eq!(DmapScalar::Int(0).get_type(), Type::Int);
990        assert_eq!(DmapScalar::Long(0).get_type(), Type::Long);
991        assert_eq!(DmapScalar::Uchar(0).get_type(), Type::Uchar);
992        assert_eq!(DmapScalar::Ushort(0).get_type(), Type::Ushort);
993        assert_eq!(DmapScalar::Uint(0).get_type(), Type::Uint);
994        assert_eq!(DmapScalar::Ulong(0).get_type(), Type::Ulong);
995        assert_eq!(DmapScalar::Float(0.0).get_type(), Type::Float);
996        assert_eq!(DmapScalar::Double(0.0).get_type(), Type::Double);
997        assert_eq!(
998            DmapScalar::String("test".to_string()).get_type(),
999            Type::String
1000        );
1001
1002        let x = DmapScalar::Char(-1);
1003        assert_eq!(x.cast_as(&Type::Short)?, DmapScalar::Short(-1));
1004        assert!(x.cast_as(&Type::Float).is_ok());
1005        assert!(x.cast_as(&Type::Uchar).is_err());
1006        assert!(x.cast_as(&Type::String).is_err());
1007
1008        let x = DmapScalar::Uchar(255);
1009        assert_eq!(x.cast_as(&Type::Short)?, DmapScalar::Short(255));
1010        assert!(x.cast_as(&Type::Char).is_err());
1011        assert!(x.cast_as(&Type::Float).is_ok());
1012        assert!(x.cast_as(&Type::Uchar).is_ok());
1013        assert!(x.cast_as(&Type::String).is_err());
1014
1015        let x = DmapScalar::Short(256);
1016        assert_eq!(x.cast_as(&Type::Short)?, DmapScalar::Short(256));
1017        assert!(x.cast_as(&Type::Char).is_err());
1018        assert_eq!(x.cast_as(&Type::Ushort)?, DmapScalar::Ushort(256));
1019        assert!(x.cast_as(&Type::Uchar).is_err());
1020        assert!(x.cast_as(&Type::Float).is_ok());
1021        assert!(x.cast_as(&Type::String).is_err());
1022
1023        let x = DmapScalar::Float(1.0);
1024        assert!(x.cast_as(&Type::Double).is_ok());
1025        assert!(x.cast_as(&Type::Char).is_err());
1026        assert!(x.cast_as(&Type::Uchar).is_err());
1027        assert!(x.cast_as(&Type::Float).is_ok());
1028        assert!(x.cast_as(&Type::String).is_err());
1029
1030        let x = DmapScalar::String("test".to_string());
1031        assert!(x.cast_as(&Type::Char).is_err());
1032        assert!(x.cast_as(&Type::Short).is_err());
1033        assert!(x.cast_as(&Type::Int).is_err());
1034        assert!(x.cast_as(&Type::Long).is_err());
1035        assert!(x.cast_as(&Type::Uchar).is_err());
1036        assert!(x.cast_as(&Type::Ushort).is_err());
1037        assert!(x.cast_as(&Type::Uint).is_err());
1038        assert!(x.cast_as(&Type::Ulong).is_err());
1039        assert!(x.cast_as(&Type::Float).is_err());
1040        assert!(x.cast_as(&Type::Double).is_err());
1041
1042        assert_eq!(
1043            DmapScalar::Char(8).as_bytes(),
1044            vec![Type::Char.key() as u8, 8]
1045        );
1046        assert_eq!(
1047            DmapScalar::Short(256).as_bytes(),
1048            vec![Type::Short.key() as u8, 0, 1]
1049        );
1050        assert_eq!(
1051            DmapScalar::Int(256).as_bytes(),
1052            vec![Type::Int.key() as u8, 0, 1, 0, 0]
1053        );
1054        assert_eq!(
1055            DmapScalar::Long(512).as_bytes(),
1056            vec![Type::Long.key() as u8, 0, 2, 0, 0, 0, 0, 0, 0]
1057        );
1058        assert_eq!(
1059            DmapScalar::Uchar(8).as_bytes(),
1060            vec![Type::Uchar.key() as u8, 8]
1061        );
1062        assert_eq!(
1063            DmapScalar::Ushort(256).as_bytes(),
1064            vec![Type::Ushort.key() as u8, 0, 1]
1065        );
1066        assert_eq!(
1067            DmapScalar::Uint(256).as_bytes(),
1068            vec![Type::Uint.key() as u8, 0, 1, 0, 0]
1069        );
1070        assert_eq!(
1071            DmapScalar::Ulong(512).as_bytes(),
1072            vec![Type::Ulong.key() as u8, 0, 2, 0, 0, 0, 0, 0, 0]
1073        );
1074        assert_eq!(
1075            DmapScalar::Float(0.0).as_bytes(),
1076            vec![Type::Float.key() as u8, 0, 0, 0, 0]
1077        );
1078        assert_eq!(
1079            DmapScalar::Double(0.0).as_bytes(),
1080            vec![Type::Double.key() as u8, 0, 0, 0, 0, 0, 0, 0, 0]
1081        );
1082        assert_eq!(
1083            DmapScalar::String("test".to_string()).as_bytes(),
1084            vec![Type::String.key() as u8, 116, 101, 115, 116, 0]
1085        );
1086
1087        Ok(())
1088    }
1089
1090    #[test]
1091    fn dmapvec() -> Result<()> {
1092        let arr = DmapVec::Char(array![0, 1, 2, 3, 4].into_dyn());
1093        assert_eq!(arr.get_type(), Type::Char);
1094        let arr = DmapVec::Uchar(array![0, 1, 2, 3, 4].into_dyn());
1095        assert_eq!(arr.get_type(), Type::Uchar);
1096        let arr = DmapVec::Short(array![0, 1, 2, 3, 4].into_dyn());
1097        assert_eq!(arr.get_type(), Type::Short);
1098        let arr = DmapVec::Ushort(array![0, 1, 2, 3, 4].into_dyn());
1099        assert_eq!(arr.get_type(), Type::Ushort);
1100        let arr = DmapVec::Int(array![0, 1, 2, 3, 4].into_dyn());
1101        assert_eq!(arr.get_type(), Type::Int);
1102        let arr = DmapVec::Uint(array![[0, 1, 2], [3, 4, 5]].into_dyn());
1103        assert_eq!(arr.get_type(), Type::Uint);
1104        let arr = DmapVec::Long(array![0, 1, 2, 3, 4].into_dyn());
1105        assert_eq!(arr.get_type(), Type::Long);
1106        let arr = DmapVec::Ulong(array![0, 1, 2, 3, 4].into_dyn());
1107        assert_eq!(arr.get_type(), Type::Ulong);
1108        let arr = DmapVec::Float(array![0.0, 1.0, 2.0, 3.0, 4.0].into_dyn());
1109        assert_eq!(arr.get_type(), Type::Float);
1110        let arr = DmapVec::Double(array![0.0, 1.0, 2.0, 3.0, 4.0].into_dyn());
1111        assert_eq!(arr.get_type(), Type::Double);
1112
1113        Ok(())
1114    }
1115
1116    #[test]
1117    fn check_fields_in_indexmap() -> Result<()> {
1118        use ndarray::array;
1119
1120        let mut rec = IndexMap::<String, DmapField>::new();
1121        let res = check_scalar(&rec, "test", &Type::Char);
1122        assert!(res.is_err());
1123        let res = check_scalar_opt(&rec, "test", &Type::Char);
1124        assert!(res.is_ok());
1125        let res = check_vector(&rec, "test", &Type::Char);
1126        assert!(res.is_err());
1127        let res = check_vector_opt(&rec, "test", &Type::Char);
1128        assert!(res.is_ok());
1129
1130        let res = rec.insert("test".to_string(), DmapField::from(1i32));
1131        assert!(res.is_none());
1132        let res = check_scalar(&rec, "test", &Type::Int);
1133        assert!(res.is_ok());
1134        let res = check_scalar_opt(&rec, "test", &Type::Char);
1135        assert!(res.is_err());
1136        let res = check_scalar_opt(&rec, "test", &Type::Int);
1137        assert!(res.is_ok());
1138        let res = check_vector(&rec, "test", &Type::Char);
1139        assert!(res.is_err());
1140        let res = check_vector_opt(&rec, "test", &Type::Char);
1141        assert!(res.is_err());
1142
1143        let test_vec = array![1.0f32, 2.0f32].into_dyn();
1144        let res = rec.insert("test_vec".to_string(), test_vec.into());
1145        assert!(res.is_none());
1146        let res = check_scalar(&rec, "test_vec", &Type::Float);
1147        assert!(res.is_err());
1148        let res = check_scalar_opt(&rec, "test_vec", &Type::Float);
1149        assert!(res.is_err());
1150        let res = check_vector(&rec, "test_vec", &Type::Float);
1151        assert!(res.is_ok());
1152        let res = check_vector(&rec, "test_vec", &Type::Double);
1153        assert!(res.is_err());
1154        let res = check_vector_opt(&rec, "test_vec", &Type::Float);
1155        assert!(res.is_ok());
1156        let res = check_vector_opt(&rec, "test_vec", &Type::Int);
1157        assert!(res.is_err());
1158
1159        Ok(())
1160    }
1161}