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}