netcdf3/
data_vector.rs

1mod tests;
2
3use crate::DataType;
4
5/// Wraps the six NetCDF-3 data types.
6///
7/// It allows to load variable data from files easily through the methods:
8/// - [FileReader::read_all_vars](struct.FileReader.html#method.read_all_vars).
9/// - [FileReader::read_var](struct.FileReader.html#method.read_var).
10///
11/// # Example
12///
13/// ```
14/// use std::collections::HashMap;
15/// use netcdf3::{FileReader, DataVector, DataType};
16///
17/// const LATITUDE_VAR_NAME: &str = "latitude";
18/// const LATITUDE_VAR_DATA: [f32; 3] = [0.0, 0.5, 1.0];
19/// const NUM_VARS: usize = 9;
20///
21/// // ...
22/// # use copy_to_tmp_file::{
23/// #     copy_bytes_to_tmp_file,
24/// #     NC3_CLASSIC_FILE_NAME, NC3_CLASSIC_FILE_BYTES,
25/// # };
26/// #
27/// # // Copy bytes to an temporary file
28/// # let (tmp_dir, input_file_path) = copy_bytes_to_tmp_file(NC3_CLASSIC_FILE_BYTES, NC3_CLASSIC_FILE_NAME);
29///
30/// // Read variable data from the file
31/// // ---------------------------------
32/// let mut file_reader: FileReader = FileReader::open(input_file_path).unwrap();
33/// assert_eq!(NUM_VARS,                        file_reader.data_set().num_vars());
34/// assert_eq!(true,                            file_reader.data_set().has_var(LATITUDE_VAR_NAME));
35/// assert_eq!(DataType::F32,                   file_reader.data_set().var_data_type(LATITUDE_VAR_NAME).unwrap());
36///
37/// let mut data: HashMap<String, DataVector> = file_reader.read_all_vars().unwrap();
38/// file_reader.close();
39///
40/// assert_eq!(NUM_VARS,                        data.len());
41/// assert_eq!(true,                            data.contains_key(LATITUDE_VAR_NAME));
42/// 
43/// let latitude: DataVector = data.remove(LATITUDE_VAR_NAME).unwrap();
44/// assert_eq!(DataType::F32,                   latitude.data_type());
45/// let latitude: Vec<f32> = latitude.get_f32_into().unwrap();
46/// assert_eq!(LATITUDE_VAR_DATA.to_vec(),      latitude);
47/// ```
48#[derive(Debug, Clone, PartialEq)]
49pub enum DataVector {
50    I8(Vec<i8>),
51    U8(Vec<u8>),
52    I16(Vec<i16>),
53    I32(Vec<i32>),
54    F32(Vec<f32>),
55    F64(Vec<f64>),
56}
57
58impl DataVector {
59
60    pub(crate) fn new(data_type: DataType, length: usize) -> Self {
61        match data_type {
62            DataType::I8 => DataVector::I8(vec![0; length]),
63            DataType::U8 => DataVector::U8(vec![0; length]),
64            DataType::I16 => DataVector::I16(vec![0; length]),
65            DataType::I32 => DataVector::I32(vec![0; length]),
66            DataType::F32 => DataVector::F32(vec![0.0; length]),
67            DataType::F64 => DataVector::F64(vec![0.0; length]),
68        }
69    }
70
71    /// Return the NetCDF-3 data type.
72    pub fn data_type(&self) -> DataType {
73        match self {
74            DataVector::I8(_) => DataType::I8,
75            DataVector::U8(_) => DataType::U8,
76            DataVector::I16(_) => DataType::I16,
77            DataVector::I32(_) => DataType::I32,
78            DataVector::F32(_) => DataType::F32,
79            DataVector::F64(_) => DataType::F64,
80        }
81    }
82
83    /// Return the length (the number of elements) of the vector.
84    pub fn len(&self) -> usize {
85        match self {
86            DataVector::I8(data) => data.len(),
87            DataVector::U8(data) => data.len(),
88            DataVector::I16(data) => data.len(),
89            DataVector::I32(data) => data.len(),
90            DataVector::F32(data) => data.len(),
91            DataVector::F64(data) => data.len(),
92        }
93    }
94
95    /// Returns a slice to the internal `Vec<i8>`.
96    ///
97    /// # Example
98    ///
99    /// ```
100    /// use netcdf3::{DataVector, DataType};
101    ///
102    /// let data_vec = DataVector::I8(vec![1_i8, 2, 3]);
103    ///
104    /// assert_eq!(DataType::I8,                data_vec.data_type());
105    ///
106    /// assert_eq!(Some(&[1_i8, 2, 3][..]),     data_vec.get_i8());
107    /// assert_eq!(None,                        data_vec.get_u8());
108    /// assert_eq!(None,                        data_vec.get_i16());
109    /// assert_eq!(None,                        data_vec.get_i32());
110    /// assert_eq!(None,                        data_vec.get_f32());
111    /// assert_eq!(None,                        data_vec.get_f64());
112    /// ```
113    pub fn get_i8(&self) -> Option<&[i8]> {
114        return match self {
115            DataVector::I8(data) => Some(data),
116            DataVector::U8(_) => None,
117            DataVector::I16(_) => None,
118            DataVector::I32(_) => None,
119            DataVector::F32(_) => None,
120            DataVector::F64(_) => None,
121        };
122    }
123
124    /// Returns a slice to the internal `Vec<u8>`.
125    ///
126    /// Also see the method [get_i8](enum.DataVector.html#method.get_i8).
127    pub fn get_u8(&self) -> Option<&[u8]> {
128        return match self {
129            DataVector::I8(_) => None,
130            DataVector::U8(data) => Some(data),
131            DataVector::I16(_) => None,
132            DataVector::I32(_) => None,
133            DataVector::F32(_) => None,
134            DataVector::F64(_) => None,
135        };
136    }
137
138    pub(crate) fn get_as_string(&self) -> Option<String> {
139        return match self {
140            DataVector::I8(_) => None,
141            DataVector::U8(data) => String::from_utf8(data.to_vec()).ok(),
142            DataVector::I16(_) => None,
143            DataVector::I32(_) => None,
144            DataVector::F32(_) => None,
145            DataVector::F64(_) => None,
146        };
147    }
148
149    /// Returns a slice to the internal `Vec<i16>`.
150    ///
151    /// Also see the method [get_i8](enum.DataVector.html#method.get_i8).
152    pub fn get_i16(&self) -> Option<&[i16]> {
153        return match self {
154            DataVector::I8(_) => None,
155            DataVector::U8(_) => None,
156            DataVector::I16(data) => Some(data),
157            DataVector::I32(_) => None,
158            DataVector::F32(_) => None,
159            DataVector::F64(_) => None,
160        };
161    }
162
163    /// Returns a slice to the internal `Vec<i32>`.
164    ///
165    /// Also see the method [get_i8](enum.DataVector.html#method.get_i8).
166    pub fn get_i32(&self) -> Option<&[i32]> {
167        return match self {
168            DataVector::I8(_) => None,
169            DataVector::U8(_) => None,
170            DataVector::I16(_) => None,
171            DataVector::I32(data) => Some(data),
172            DataVector::F32(_) => None,
173            DataVector::F64(_) => None,
174        };
175    }
176
177    /// Returns a slice to the internal `Vec<f32>`.
178    ///
179    /// Also see the method [get_i8](enum.DataVector.html#method.get_i8).
180    pub fn get_f32(&self) -> Option<&[f32]> {
181        return match self {
182            DataVector::I8(_) => None,
183            DataVector::U8(_) => None,
184            DataVector::I16(_) => None,
185            DataVector::I32(_) => None,
186            DataVector::F32(data) => Some(data),
187            DataVector::F64(_) => None,
188        };
189    }
190
191    /// Returns a slice to the internal `Vec<f64>`.
192    ///
193    /// Also see the method [get_i8](enum.DataVector.html#method.get_i8).
194    pub fn get_f64(&self) -> Option<&[f64]> {
195        return match self {
196            DataVector::I8(_) => None,
197            DataVector::U8(_) => None,
198            DataVector::I16(_) => None,
199            DataVector::I32(_) => None,
200            DataVector::F32(_) => None,
201            DataVector::F64(data) => Some(data),
202        };
203    }
204
205    /// Returns the internal `Vec<i8>` if the `DataVector` contains one.
206    ///
207    /// Otherwise the instance of the `DataVector` is returned as an errror.
208    ///
209    /// # Example
210    ///
211    /// ```
212    /// use netcdf3::{DataVector, DataType};
213    ///
214    /// let data_1: Vec<i8> = vec![1, 2 ,3];
215    /// let ptr_1 : *const i8 = data_1.as_ptr();
216    ///
217    /// // Frirst create a `DataVector::I8`
218    /// let data_vec: DataVector = DataVector::I8(data_1);
219    /// assert_eq!(DataType::I8,               data_vec.data_type());
220    ///
221    /// // Try to extract the internal vector with the wrong data types
222    /// let data_vec: DataVector = data_vec.get_u8_into().unwrap_err();
223    /// let data_vec: DataVector = data_vec.get_i16_into().unwrap_err();
224    /// let data_vec: DataVector = data_vec.get_i32_into().unwrap_err();
225    /// let data_vec: DataVector = data_vec.get_f32_into().unwrap_err();
226    /// let data_vec: DataVector = data_vec.get_f64_into().unwrap_err();
227    ///
228    /// // Extract the internal vector with the good data type
229    /// let data_2: Vec<i8> = data_vec.get_i8_into().unwrap();
230    /// let ptr_2 : *const i8 = data_2.as_ptr();
231    ///
232    /// assert_eq!(vec![1, 2, 3],           data_2);
233    ///
234    /// // No copy of the buffer has been done
235    /// assert_eq!(ptr_1,                   ptr_2);
236    /// ```
237    pub fn get_i8_into(self) -> Result<Vec<i8>, DataVector> {
238        if let DataVector::I8(data) = self {
239            return Ok(data);
240        }
241        return Err(self);
242    }
243
244    pub fn get_u8_into(self) -> Result<Vec<u8>, DataVector> {
245        if let DataVector::U8(data) = self {
246            return Ok(data);
247        }
248        return Err(self);
249    }
250
251    pub fn get_i16_into(self) -> Result<Vec<i16>, DataVector> {
252        if let DataVector::I16(data) = self {
253            return Ok(data);
254        }
255        return Err(self);
256    }
257
258    pub fn get_i32_into(self) -> Result<Vec<i32>, DataVector> {
259        if let DataVector::I32(data) = self {
260            return Ok(data);
261        }
262        return Err(self);
263    }
264
265    pub fn get_f32_into(self) -> Result<Vec<f32>, DataVector> {
266        if let DataVector::F32(data) = self {
267            return Ok(data);
268        }
269        return Err(self);
270    }
271
272    pub fn get_f64_into(self) -> Result<Vec<f64>, DataVector> {
273        if let DataVector::F64(data) = self {
274            return Ok(data);
275        }
276        return Err(self);
277    }
278}