pub mod header;
pub mod streamers;
use std::collections::HashMap;
use std::path::PathBuf;
use num_traits::FromPrimitive;
use pyo3;
use crate::errors::Error;
use crate::headers;
use crate::TTTRFile;
pub type Header = HashMap<String, PTUTag>;
#[derive(Debug)]
pub enum PTUTag {
Empty8,
Bool8(bool),
Int8(i64),
BitSet64(i64),
Color8(i64),
Float8(f64),
TDateTime(f64),
Float8Array(Vec<f64>),
AnsiString8(String),
WideString(String),
BinaryBlob(Vec<u8>),
}
impl pyo3::ToPyObject for PTUTag {
fn to_object(&self, py: pyo3::Python) -> pyo3::PyObject {
match self {
PTUTag::Empty8 => (py.None(), "Empty8").to_object(py),
PTUTag::Bool8(x) => (x, "Bool8").to_object(py),
PTUTag::Int8(x) => (x, "Int8").to_object(py),
PTUTag::BitSet64(x) => (x, "BitSet64").to_object(py),
PTUTag::Color8(x) => (x, "Color8").to_object(py),
PTUTag::Float8(x) => (x, "Float8").to_object(py),
PTUTag::TDateTime(x) => (x, "TDateTime").to_object(py),
PTUTag::Float8Array(x) => (x, "Float8Array").to_object(py),
PTUTag::AnsiString8(x) => (x, "AnsiString8").to_object(py),
PTUTag::WideString(x) => (x, "WideString").to_object(py),
PTUTag::BinaryBlob(x) => (x, "BinaryBlob").to_object(py),
}
}
}
#[derive(FromPrimitive, ToPrimitive, Debug)]
enum PTUTagType {
Empty8 = 0xFFFF0008,
Bool8 = 0x00000008,
Int8 = 0x10000008,
BitSet64 = 0x11000008,
Color8 = 0x12000008,
Float8 = 0x20000008,
TDateTime = 0x21000008,
Float8Array = 0x2001FFFF,
AnsiString8 = 0x4001FFFF,
WideString = 0x4002FFFF,
BinaryBlob = 0xFFFFFFFF,
}
#[derive(FromPrimitive, ToPrimitive, Debug)]
enum RecType {
PicoHarpT3 = 0x00010303, PicoHarpT2 = 0x00010203, HydraHarpT3 = 0x00010304, HydraHarpT2 = 0x00010204, HydraHarp2T3 = 0x01010304, HydraHarp2T2 = 0x01010204, TimeHarp260NT3 = 0x00010305, TimeHarp260NT2 = 0x00010205, TimeHarp260PT3 = 0x00010306, TimeHarp260PT2 = 0x00010206, }
const TAG_TTTR_REC_TYPE: &str = "TTResultFormat_TTTRRecType";
const TAG_NUM_RECORDS: &str = "TTResult_NumberOfRecords"; const TAG_GLOB_RES: &str = "MeasDesc_GlobalResolution"; const FILE_TAG_END: &str = "Header_End"; const _TAG_ACQUISITION_TIMETTTR: &str = "MeasDesc_AcquisitionTime";
const _TAG_RES: &str = "MeasDesc_Resolution"; pub struct PTUFile {
pub path: PathBuf,
pub header: Header,
}
impl PTUFile {
pub fn new(filename: PathBuf) -> Result<Self, Error> {
if filename.exists() {
let header = self::header::read_ptu_header(&filename)?;
Ok(Self {
path: filename,
header,
})
} else {
let filename_string = filename.display().to_string();
Err(Error::FileNotAvailable(filename_string))
}
}
}
use tttr_toolbox_proc_macros::read_ptu_tag;
impl TTTRFile for PTUFile {
fn time_resolution(&self) -> Result<f64, Error> {
let header = &self.header;
Ok(read_ptu_tag!(header[TAG_GLOB_RES] as Float8))
}
fn record_type(&self) -> Result<headers::RecordType, Error> {
let header = &self.header;
let record_type = FromPrimitive::from_i64(read_ptu_tag!(header[TAG_TTTR_REC_TYPE] as Int8));
Ok(
match record_type
.ok_or_else(|| Error::InvalidHeader(String::from("Invalid RecordType type")))?
{
RecType::PicoHarpT3 => headers::RecordType::NotImplemented,
RecType::PicoHarpT2 => headers::RecordType::PHT2,
RecType::HydraHarpT3 => headers::RecordType::NotImplemented,
RecType::HydraHarpT2 => headers::RecordType::HHT2_HH2,
RecType::HydraHarp2T3 => headers::RecordType::HHT3_HH2,
RecType::HydraHarp2T2 => headers::RecordType::HHT2_HH1,
RecType::TimeHarp260NT3 => headers::RecordType::HHT3_HH2,
RecType::TimeHarp260NT2 => headers::RecordType::HHT2_HH2,
RecType::TimeHarp260PT3 => headers::RecordType::HHT3_HH2,
RecType::TimeHarp260PT2 => headers::RecordType::HHT2_HH2,
},
)
}
}
impl std::fmt::Display for PTUFile {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
let mut string = String::from("");
for (key, value) in &self.header {
string.push_str(&format!("{:<35}: {}\n", key, value));
}
write!(f, "{}", string)
}
}