use crate::{Big, Endianness, General, Little, TdmsError, UnknownDataType};
use std::io::{Read, Seek};
#[derive(Debug, Copy, Clone, PartialEq)]
pub enum TdmsDataType {
Void,
I8(usize),
I16(usize),
I32(usize),
I64(usize),
U8(usize),
U16(usize),
U32(usize),
U64(usize),
SingleFloat(usize),
DoubleFloat(usize),
ExtendedFloat(usize),
SingleFloatWithUnit(usize),
DoubleFloatWithUnit(usize),
ExtendedFloatWithUnit(usize),
String,
Boolean(usize),
TimeStamp(usize),
FixedPoint(usize),
ComplexSingleFloat(usize),
ComplexDoubleFloat(usize),
DAQmxRawData,
}
impl TryFrom<i32> for TdmsDataType {
type Error = TdmsError;
fn try_from(v: i32) -> Result<Self, TdmsError> {
match v {
x if x == 0 => Ok(TdmsDataType::Void),
x if x == 1 => Ok(TdmsDataType::I8(1)),
x if x == 2 => Ok(TdmsDataType::I16(2)),
x if x == 3 => Ok(TdmsDataType::I32(4)),
x if x == 4 => Ok(TdmsDataType::I64(8)),
x if x == 5 => Ok(TdmsDataType::U8(1)),
x if x == 6 => Ok(TdmsDataType::U16(2)),
x if x == 7 => Ok(TdmsDataType::U32(4)),
x if x == 8 => Ok(TdmsDataType::U64(8)),
x if x == 9 => Ok(TdmsDataType::SingleFloat(4)),
x if x == 10 => Ok(TdmsDataType::DoubleFloat(8)),
x if x == 11 => Ok(TdmsDataType::ExtendedFloat(10)),
x if x == 0x19 => Ok(TdmsDataType::SingleFloatWithUnit(4)),
x if x == 0x1a => Ok(TdmsDataType::DoubleFloatWithUnit(8)),
x if x == 0x1b => Ok(TdmsDataType::ExtendedFloatWithUnit(10)),
x if x == 0x20 => Ok(TdmsDataType::String),
x if x == 0x21 => Ok(TdmsDataType::Boolean(1)),
x if x == 0x44 => Ok(TdmsDataType::TimeStamp(16)),
x if x == 0x4f => Ok(TdmsDataType::FixedPoint(10)),
x if x == 0x08000c => Ok(TdmsDataType::ComplexSingleFloat(4)),
x if x == 0x10000d => Ok(TdmsDataType::ComplexDoubleFloat(8)),
x if x == -1 => Ok(TdmsDataType::DAQmxRawData), _ => Err(UnknownDataType()),
}
}
}
impl TdmsDataType {
pub fn get_size(data_type: TdmsDataType) -> usize {
return match data_type {
TdmsDataType::Void => 0,
TdmsDataType::I8(v) => v,
TdmsDataType::I16(v) => v,
TdmsDataType::I32(v) => v,
TdmsDataType::I64(v) => v,
TdmsDataType::U8(v) => v,
TdmsDataType::U16(v) => v,
TdmsDataType::U32(v) => v,
TdmsDataType::U64(v) => v,
TdmsDataType::SingleFloat(v) => v,
TdmsDataType::DoubleFloat(v) => v,
TdmsDataType::ExtendedFloat(v) => v,
TdmsDataType::SingleFloatWithUnit(v) => v,
TdmsDataType::DoubleFloatWithUnit(v) => v,
TdmsDataType::ExtendedFloatWithUnit(v) => v,
TdmsDataType::String => 0,
TdmsDataType::Boolean(v) => v,
TdmsDataType::TimeStamp(v) => v,
TdmsDataType::FixedPoint(v) => v,
TdmsDataType::ComplexSingleFloat(v) => v,
TdmsDataType::ComplexDoubleFloat(v) => v,
TdmsDataType::DAQmxRawData => 0,
};
}
}
#[derive(Debug, Clone)]
pub struct TDMSValue {
pub data_type: TdmsDataType,
pub endianness: Endianness,
pub value: Option<Vec<u8>>,
}
impl TDMSValue {
pub fn from_reader<R: Read + Seek>(
endianness: Endianness,
data_type: TdmsDataType,
r: &mut R,
) -> Result<Self, TdmsError> {
return match data_type {
TdmsDataType::Void => Ok(TDMSValue {
data_type,
endianness,
value: None,
}),
TdmsDataType::I8(_) => {
let mut buf: [u8; 1] = [0; 1];
r.read_exact(&mut buf)?;
Ok(TDMSValue {
data_type,
endianness,
value: Some(buf.to_vec()),
})
}
TdmsDataType::I16(_) => {
let mut buf: [u8; 2] = [0; 2];
r.read_exact(&mut buf)?;
Ok(TDMSValue {
data_type,
endianness,
value: Some(buf.to_vec()),
})
}
TdmsDataType::I32(_) => {
let mut buf: [u8; 4] = [0; 4];
r.read_exact(&mut buf)?;
Ok(TDMSValue {
data_type,
endianness,
value: Some(buf.to_vec()),
})
}
TdmsDataType::I64(_) => {
let mut buf: [u8; 8] = [0; 8];
r.read_exact(&mut buf)?;
Ok(TDMSValue {
data_type,
endianness,
value: Some(buf.to_vec()),
})
}
TdmsDataType::U8(_) => {
let mut buf: [u8; 1] = [0; 1];
r.read_exact(&mut buf)?;
Ok(TDMSValue {
data_type,
endianness,
value: Some(buf.to_vec()),
})
}
TdmsDataType::U16(_) => {
let mut buf: [u8; 2] = [0; 2];
r.read_exact(&mut buf)?;
Ok(TDMSValue {
data_type,
endianness,
value: Some(buf.to_vec()),
})
}
TdmsDataType::U32(_) => {
let mut buf: [u8; 4] = [0; 4];
r.read_exact(&mut buf)?;
Ok(TDMSValue {
data_type,
endianness,
value: Some(buf.to_vec()),
})
}
TdmsDataType::U64(_) => {
let mut buf: [u8; 8] = [0; 8];
r.read_exact(&mut buf)?;
Ok(TDMSValue {
data_type,
endianness,
value: Some(buf.to_vec()),
})
}
TdmsDataType::SingleFloat(_) => {
let mut buf: [u8; 4] = [0; 4];
r.read_exact(&mut buf)?;
Ok(TDMSValue {
data_type,
endianness,
value: Some(buf.to_vec()),
})
}
TdmsDataType::DoubleFloat(_) => {
let mut buf: [u8; 8] = [0; 8];
r.read_exact(&mut buf)?;
Ok(TDMSValue {
data_type,
endianness,
value: Some(buf.to_vec()),
})
}
TdmsDataType::ExtendedFloat(_) => {
let mut buf: [u8; 10] = [0; 10];
r.read_exact(&mut buf)?;
Ok(TDMSValue {
data_type,
endianness,
value: Some(buf.to_vec()),
})
}
TdmsDataType::SingleFloatWithUnit(_) => {
let mut buf: [u8; 4] = [0; 4];
r.read_exact(&mut buf)?;
Ok(TDMSValue {
data_type,
endianness,
value: Some(buf.to_vec()),
})
}
TdmsDataType::DoubleFloatWithUnit(_) => {
let mut buf: [u8; 8] = [0; 8];
r.read_exact(&mut buf)?;
Ok(TDMSValue {
data_type,
endianness,
value: Some(buf.to_vec()),
})
}
TdmsDataType::ExtendedFloatWithUnit(_) => {
let mut buf: [u8; 10] = [0; 10];
r.read_exact(&mut buf)?;
Ok(TDMSValue {
data_type,
endianness,
value: Some(buf.to_vec()),
})
}
TdmsDataType::String => {
let mut buf: [u8; 4] = [0; 4];
r.read_exact(&mut buf)?;
let length: u32 = match endianness {
Little => u32::from_le_bytes(buf),
Big => u32::from_be_bytes(buf),
};
let length = match usize::try_from(length) {
Ok(l) => l,
Err(_) => {
return Err(General(String::from(
"error converting strength length to system size",
)))
}
};
let mut value = vec![0; length];
r.read_exact(&mut value)?;
Ok(TDMSValue {
data_type,
endianness,
value: Some(value),
})
}
TdmsDataType::Boolean(_) => {
let mut buf: [u8; 1] = [0; 1];
r.read_exact(&mut buf)?;
Ok(TDMSValue {
data_type,
endianness,
value: Some(buf.to_vec()),
})
}
TdmsDataType::TimeStamp(_) => {
let mut buf: [u8; 16] = [0; 16];
r.read_exact(&mut buf)?;
Ok(TDMSValue {
data_type,
endianness,
value: Some(buf.to_vec()),
})
}
TdmsDataType::FixedPoint(_) => {
let mut buf: [u8; 10] = [0; 10];
r.read_exact(&mut buf)?;
Ok(TDMSValue {
data_type,
endianness,
value: Some(buf.to_vec()),
})
}
TdmsDataType::ComplexSingleFloat(_) => {
let mut buf: [u8; 8] = [0; 8];
r.read_exact(&mut buf)?;
Ok(TDMSValue {
data_type,
endianness,
value: Some(buf.to_vec()),
})
}
TdmsDataType::ComplexDoubleFloat(_) => {
let mut buf: [u8; 16] = [0; 16];
r.read_exact(&mut buf)?;
Ok(TDMSValue {
data_type,
endianness,
value: Some(buf.to_vec()),
})
}
TdmsDataType::DAQmxRawData => {
let mut buf: [u8; 8] = [0; 8];
r.read_exact(&mut buf)?;
Ok(TDMSValue {
data_type,
endianness,
value: Some(buf.to_vec()),
})
}
};
}
}
#[derive(Clone, Debug, Copy)]
pub struct TdmsTimestamp(pub i64, pub u64);