tdms/
data_type.rs

1use crate::{Big, Endianness, General, Little, TdmsError, UnknownDataType};
2use std::io::{Read, Seek};
3
4/// Represents the potential TDMS data types. Contained value is size in bytes if applicable
5#[derive(Debug, Copy, Clone, PartialEq)]
6pub enum TdmsDataType {
7    Void,
8    I8(usize),
9    I16(usize),
10    I32(usize),
11    I64(usize),
12    U8(usize),
13    U16(usize),
14    U32(usize),
15    U64(usize),
16    SingleFloat(usize),
17    DoubleFloat(usize),
18    ExtendedFloat(usize),
19    SingleFloatWithUnit(usize),
20    DoubleFloatWithUnit(usize),
21    ExtendedFloatWithUnit(usize),
22    String,
23    Boolean(usize),
24    TimeStamp(usize),
25    FixedPoint(usize),
26    ComplexSingleFloat(usize),
27    ComplexDoubleFloat(usize),
28    DAQmxRawData,
29}
30
31impl TryFrom<i32> for TdmsDataType {
32    type Error = TdmsError;
33
34    fn try_from(v: i32) -> Result<Self, TdmsError> {
35        match v {
36            x if x == 0 => Ok(TdmsDataType::Void),
37            x if x == 1 => Ok(TdmsDataType::I8(1)),
38            x if x == 2 => Ok(TdmsDataType::I16(2)),
39            x if x == 3 => Ok(TdmsDataType::I32(4)),
40            x if x == 4 => Ok(TdmsDataType::I64(8)),
41            x if x == 5 => Ok(TdmsDataType::U8(1)),
42            x if x == 6 => Ok(TdmsDataType::U16(2)),
43            x if x == 7 => Ok(TdmsDataType::U32(4)),
44            x if x == 8 => Ok(TdmsDataType::U64(8)),
45            x if x == 9 => Ok(TdmsDataType::SingleFloat(4)),
46            x if x == 10 => Ok(TdmsDataType::DoubleFloat(8)),
47            x if x == 11 => Ok(TdmsDataType::ExtendedFloat(10)),
48            x if x == 0x19 => Ok(TdmsDataType::SingleFloatWithUnit(4)),
49            x if x == 0x1a => Ok(TdmsDataType::DoubleFloatWithUnit(8)),
50            x if x == 0x1b => Ok(TdmsDataType::ExtendedFloatWithUnit(10)),
51            x if x == 0x20 => Ok(TdmsDataType::String),
52            x if x == 0x21 => Ok(TdmsDataType::Boolean(1)),
53            x if x == 0x44 => Ok(TdmsDataType::TimeStamp(16)),
54            x if x == 0x4f => Ok(TdmsDataType::FixedPoint(10)),
55            x if x == 0x08000c => Ok(TdmsDataType::ComplexSingleFloat(4)),
56            x if x == 0x10000d => Ok(TdmsDataType::ComplexDoubleFloat(8)),
57            x if x == -1 => Ok(TdmsDataType::DAQmxRawData), // 0xFFFFFFFF equivalent
58            _ => Err(UnknownDataType()),
59        }
60    }
61}
62
63impl TdmsDataType {
64    pub fn get_size(data_type: TdmsDataType) -> usize {
65        return match data_type {
66            TdmsDataType::Void => 0,
67            TdmsDataType::I8(v) => v,
68            TdmsDataType::I16(v) => v,
69            TdmsDataType::I32(v) => v,
70            TdmsDataType::I64(v) => v,
71            TdmsDataType::U8(v) => v,
72            TdmsDataType::U16(v) => v,
73            TdmsDataType::U32(v) => v,
74            TdmsDataType::U64(v) => v,
75            TdmsDataType::SingleFloat(v) => v,
76            TdmsDataType::DoubleFloat(v) => v,
77            TdmsDataType::ExtendedFloat(v) => v,
78            TdmsDataType::SingleFloatWithUnit(v) => v,
79            TdmsDataType::DoubleFloatWithUnit(v) => v,
80            TdmsDataType::ExtendedFloatWithUnit(v) => v,
81            TdmsDataType::String => 0,
82            TdmsDataType::Boolean(v) => v,
83            TdmsDataType::TimeStamp(v) => v,
84            TdmsDataType::FixedPoint(v) => v,
85            TdmsDataType::ComplexSingleFloat(v) => v,
86            TdmsDataType::ComplexDoubleFloat(v) => v,
87            TdmsDataType::DAQmxRawData => 0,
88        };
89    }
90}
91
92#[derive(Debug, Clone)]
93/// `TDMSValue` represents a single value read from a TDMS file. This contains information on the
94/// data type and the endianness of the value if numeric. This is typically used only by segment
95/// and in the metadata properties, as using these for raw values is not good for performance.
96pub struct TDMSValue {
97    pub data_type: TdmsDataType,
98    pub endianness: Endianness,
99    pub value: Option<Vec<u8>>,
100}
101
102impl TDMSValue {
103    /// from_reader accepts an open reader and a data type and attempts to read, generating a
104    /// value struct containing the actual value
105    pub fn from_reader<R: Read + Seek>(
106        endianness: Endianness,
107        data_type: TdmsDataType,
108        r: &mut R,
109    ) -> Result<Self, TdmsError> {
110        return match data_type {
111            TdmsDataType::Void => Ok(TDMSValue {
112                data_type,
113                endianness,
114                value: None,
115            }),
116            TdmsDataType::I8(_) => {
117                let mut buf: [u8; 1] = [0; 1];
118                r.read_exact(&mut buf)?;
119
120                Ok(TDMSValue {
121                    data_type,
122                    endianness,
123                    value: Some(buf.to_vec()),
124                })
125            }
126            TdmsDataType::I16(_) => {
127                let mut buf: [u8; 2] = [0; 2];
128                r.read_exact(&mut buf)?;
129
130                Ok(TDMSValue {
131                    data_type,
132                    endianness,
133                    value: Some(buf.to_vec()),
134                })
135            }
136            TdmsDataType::I32(_) => {
137                let mut buf: [u8; 4] = [0; 4];
138                r.read_exact(&mut buf)?;
139
140                Ok(TDMSValue {
141                    data_type,
142                    endianness,
143                    value: Some(buf.to_vec()),
144                })
145            }
146            TdmsDataType::I64(_) => {
147                let mut buf: [u8; 8] = [0; 8];
148                r.read_exact(&mut buf)?;
149
150                Ok(TDMSValue {
151                    data_type,
152                    endianness,
153                    value: Some(buf.to_vec()),
154                })
155            }
156            TdmsDataType::U8(_) => {
157                let mut buf: [u8; 1] = [0; 1];
158                r.read_exact(&mut buf)?;
159
160                Ok(TDMSValue {
161                    data_type,
162                    endianness,
163                    value: Some(buf.to_vec()),
164                })
165            }
166            TdmsDataType::U16(_) => {
167                let mut buf: [u8; 2] = [0; 2];
168                r.read_exact(&mut buf)?;
169
170                Ok(TDMSValue {
171                    data_type,
172                    endianness,
173                    value: Some(buf.to_vec()),
174                })
175            }
176            TdmsDataType::U32(_) => {
177                let mut buf: [u8; 4] = [0; 4];
178                r.read_exact(&mut buf)?;
179
180                Ok(TDMSValue {
181                    data_type,
182                    endianness,
183                    value: Some(buf.to_vec()),
184                })
185            }
186            TdmsDataType::U64(_) => {
187                let mut buf: [u8; 8] = [0; 8];
188                r.read_exact(&mut buf)?;
189
190                Ok(TDMSValue {
191                    data_type,
192                    endianness,
193                    value: Some(buf.to_vec()),
194                })
195            }
196            TdmsDataType::SingleFloat(_) => {
197                let mut buf: [u8; 4] = [0; 4];
198                r.read_exact(&mut buf)?;
199
200                Ok(TDMSValue {
201                    data_type,
202                    endianness,
203                    value: Some(buf.to_vec()),
204                })
205            }
206            TdmsDataType::DoubleFloat(_) => {
207                let mut buf: [u8; 8] = [0; 8];
208                r.read_exact(&mut buf)?;
209
210                Ok(TDMSValue {
211                    data_type,
212                    endianness,
213                    value: Some(buf.to_vec()),
214                })
215            }
216            TdmsDataType::ExtendedFloat(_) => {
217                let mut buf: [u8; 10] = [0; 10];
218                r.read_exact(&mut buf)?;
219
220                Ok(TDMSValue {
221                    data_type,
222                    endianness,
223                    value: Some(buf.to_vec()),
224                })
225            }
226            TdmsDataType::SingleFloatWithUnit(_) => {
227                let mut buf: [u8; 4] = [0; 4];
228                r.read_exact(&mut buf)?;
229
230                Ok(TDMSValue {
231                    data_type,
232                    endianness,
233                    value: Some(buf.to_vec()),
234                })
235            }
236            TdmsDataType::DoubleFloatWithUnit(_) => {
237                let mut buf: [u8; 8] = [0; 8];
238                r.read_exact(&mut buf)?;
239
240                Ok(TDMSValue {
241                    data_type,
242                    endianness,
243                    value: Some(buf.to_vec()),
244                })
245            }
246            TdmsDataType::ExtendedFloatWithUnit(_) => {
247                let mut buf: [u8; 10] = [0; 10];
248                r.read_exact(&mut buf)?;
249
250                Ok(TDMSValue {
251                    data_type,
252                    endianness,
253                    value: Some(buf.to_vec()),
254                })
255            }
256            TdmsDataType::String => {
257                let mut buf: [u8; 4] = [0; 4];
258                r.read_exact(&mut buf)?;
259
260                let length: u32 = match endianness {
261                    Little => u32::from_le_bytes(buf),
262                    Big => u32::from_be_bytes(buf),
263                };
264
265                // must be a vec due to variable length
266                let length = match usize::try_from(length) {
267                    Ok(l) => l,
268                    Err(_) => {
269                        return Err(General(String::from(
270                            "error converting strength length to system size",
271                        )))
272                    }
273                };
274
275                let mut value = vec![0; length];
276                r.read_exact(&mut value)?;
277
278                Ok(TDMSValue {
279                    data_type,
280                    endianness,
281                    value: Some(value),
282                })
283            }
284            TdmsDataType::Boolean(_) => {
285                let mut buf: [u8; 1] = [0; 1];
286                r.read_exact(&mut buf)?;
287
288                Ok(TDMSValue {
289                    data_type,
290                    endianness,
291                    value: Some(buf.to_vec()),
292                })
293            }
294            TdmsDataType::TimeStamp(_) => {
295                let mut buf: [u8; 16] = [0; 16];
296                r.read_exact(&mut buf)?;
297
298                Ok(TDMSValue {
299                    data_type,
300                    endianness,
301                    value: Some(buf.to_vec()),
302                })
303            }
304            // there is little information on how to handle FixedPoint types, for
305            // now we'll store them as a 64 bit integer and hope that will be enough
306            TdmsDataType::FixedPoint(_) => {
307                let mut buf: [u8; 10] = [0; 10];
308                r.read_exact(&mut buf)?;
309
310                Ok(TDMSValue {
311                    data_type,
312                    endianness,
313                    value: Some(buf.to_vec()),
314                })
315            }
316            TdmsDataType::ComplexSingleFloat(_) => {
317                let mut buf: [u8; 8] = [0; 8];
318                r.read_exact(&mut buf)?;
319
320                Ok(TDMSValue {
321                    data_type,
322                    endianness,
323                    value: Some(buf.to_vec()),
324                })
325            }
326            TdmsDataType::ComplexDoubleFloat(_) => {
327                let mut buf: [u8; 16] = [0; 16];
328                r.read_exact(&mut buf)?;
329
330                Ok(TDMSValue {
331                    data_type,
332                    endianness,
333                    value: Some(buf.to_vec()),
334                })
335            }
336            TdmsDataType::DAQmxRawData => {
337                let mut buf: [u8; 8] = [0; 8];
338                r.read_exact(&mut buf)?;
339
340                Ok(TDMSValue {
341                    data_type,
342                    endianness,
343                    value: Some(buf.to_vec()),
344                })
345            }
346        };
347    }
348}
349
350#[derive(Clone, Debug, Copy)]
351pub struct TdmsTimestamp(pub i64, pub u64);