netcdf_reader/nc4/
types.rs1use hdf5_reader::messages::datatype::Datatype;
28
29use crate::error::{Error, Result};
30use crate::types::{NcCompoundField, NcType};
31
32pub fn hdf5_to_nc_type(dtype: &Datatype) -> Result<NcType> {
34 match dtype {
35 Datatype::FixedPoint { size, signed, .. } => match (size, signed) {
36 (1, true) => Ok(NcType::Byte),
37 (1, false) => Ok(NcType::UByte),
38 (2, true) => Ok(NcType::Short),
39 (2, false) => Ok(NcType::UShort),
40 (4, true) => Ok(NcType::Int),
41 (4, false) => Ok(NcType::UInt),
42 (8, true) => Ok(NcType::Int64),
43 (8, false) => Ok(NcType::UInt64),
44 _ => Err(Error::InvalidData(format!(
45 "unsupported HDF5 integer size {} for NetCDF-4",
46 size
47 ))),
48 },
49 Datatype::FloatingPoint { size, .. } => match size {
50 4 => Ok(NcType::Float),
51 8 => Ok(NcType::Double),
52 _ => Err(Error::InvalidData(format!(
53 "unsupported HDF5 float size {} for NetCDF-4",
54 size
55 ))),
56 },
57 Datatype::String { .. } => Ok(NcType::String),
58 Datatype::Enum { base, .. } => {
59 hdf5_to_nc_type(base)
61 }
62 Datatype::Compound { size, fields } => {
63 let mut nc_fields = Vec::with_capacity(fields.len());
64 for f in fields {
65 nc_fields.push(NcCompoundField {
66 name: f.name.clone(),
67 offset: f.byte_offset as u64,
68 dtype: hdf5_to_nc_type(&f.datatype)?,
69 });
70 }
71 Ok(NcType::Compound {
72 size: *size,
73 fields: nc_fields,
74 })
75 }
76 Datatype::Opaque { size, tag } => Ok(NcType::Opaque {
77 size: *size,
78 tag: tag.clone(),
79 }),
80 Datatype::Array { base, dims } => {
81 let base_nc = hdf5_to_nc_type(base)?;
82 Ok(NcType::Array {
83 base: Box::new(base_nc),
84 dims: dims.clone(),
85 })
86 }
87 Datatype::VarLen { base } => {
88 let base_nc = hdf5_to_nc_type(base)?;
89 Ok(NcType::VLen {
90 base: Box::new(base_nc),
91 })
92 }
93 _ => Err(Error::InvalidData(format!(
94 "HDF5 datatype {:?} has no NetCDF-4 equivalent",
95 dtype
96 ))),
97 }
98}
99
100#[cfg(test)]
101mod tests {
102 use super::*;
103 use hdf5_reader::error::ByteOrder;
104
105 #[test]
106 fn test_integer_types() {
107 let bo = ByteOrder::LittleEndian;
108 assert_eq!(
109 hdf5_to_nc_type(&Datatype::FixedPoint {
110 size: 1,
111 signed: true,
112 byte_order: bo
113 })
114 .unwrap(),
115 NcType::Byte
116 );
117 assert_eq!(
118 hdf5_to_nc_type(&Datatype::FixedPoint {
119 size: 1,
120 signed: false,
121 byte_order: bo
122 })
123 .unwrap(),
124 NcType::UByte
125 );
126 assert_eq!(
127 hdf5_to_nc_type(&Datatype::FixedPoint {
128 size: 4,
129 signed: true,
130 byte_order: bo
131 })
132 .unwrap(),
133 NcType::Int
134 );
135 assert_eq!(
136 hdf5_to_nc_type(&Datatype::FixedPoint {
137 size: 8,
138 signed: false,
139 byte_order: bo
140 })
141 .unwrap(),
142 NcType::UInt64
143 );
144 }
145
146 #[test]
147 fn test_float_types() {
148 let bo = ByteOrder::LittleEndian;
149 assert_eq!(
150 hdf5_to_nc_type(&Datatype::FloatingPoint {
151 size: 4,
152 byte_order: bo
153 })
154 .unwrap(),
155 NcType::Float
156 );
157 assert_eq!(
158 hdf5_to_nc_type(&Datatype::FloatingPoint {
159 size: 8,
160 byte_order: bo
161 })
162 .unwrap(),
163 NcType::Double
164 );
165 }
166}