mod building;
mod querying;
mod writing;
use std::collections::BTreeMap;
use crate::PropertyValue;
use crate::error::TdmsError;
use crate::meta_data::{ObjectMetaData, RawDataIndex, RawDataMeta};
use crate::paths::{ChannelPath, PropertyPath};
use crate::raw_data::DataBlock;
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct DataLocation {
pub data_block: usize,
pub channel_index: usize,
pub number_of_samples: u64,
}
#[derive(Clone, PartialEq, Eq, Debug)]
pub enum DataFormat {
RawData(RawDataMeta),
}
impl DataFormat {
fn from_index(index: &RawDataIndex) -> Option<Self> {
match index {
RawDataIndex::RawData(raw_meta) => Some(DataFormat::RawData(raw_meta.clone())),
_ => None,
}
}
}
impl From<DataFormat> for RawDataIndex {
fn from(value: DataFormat) -> Self {
match value {
DataFormat::RawData(raw_meta) => RawDataIndex::RawData(raw_meta),
}
}
}
#[derive(Clone, PartialEq, Debug)]
struct ObjectData {
path: String,
properties: BTreeMap<String, PropertyValue>,
data_locations: Vec<DataLocation>,
latest_data_format: Option<DataFormat>,
}
impl ObjectData {
fn from_metadata(meta: &ObjectMetaData) -> Result<Self, TdmsError> {
let mut new = Self {
path: meta.path.clone(),
properties: BTreeMap::new(),
data_locations: vec![],
latest_data_format: None,
};
new.update(meta)?;
Ok(new)
}
fn update(&mut self, other: &ObjectMetaData) -> Result<(), TdmsError> {
for (name, value) in other.properties.iter() {
self.properties.insert(name.clone(), value.clone());
}
match (&mut self.latest_data_format, &other.raw_data_index) {
(None, RawDataIndex::MatchPrevious) => Err(TdmsError::NoPreviousType),
(latest_format, raw_index) => {
if let Some(format) = DataFormat::from_index(raw_index) {
*latest_format = Some(format);
}
Ok(())
}
}
}
fn add_data_location(&mut self, location: DataLocation) {
self.data_locations.push(location);
}
fn get_all_properties(&self) -> impl Iterator<Item = (&String, &PropertyValue)> {
self.properties.iter()
}
}
type ObjectIndex = BTreeMap<String, ObjectData>;
#[derive(Default, Debug, Clone)]
pub struct Index {
active_objects: Vec<building::ActiveObject>,
objects: ObjectIndex,
data_blocks: Vec<DataBlock>,
next_segment_start: u64,
}
impl Index {
pub fn new() -> Self {
Self::default()
}
pub fn get_object_properties(
&self,
path: &PropertyPath,
) -> Option<impl Iterator<Item = (&String, &PropertyValue)>> {
self.objects
.get(path.path())
.map(|object| object.get_all_properties())
}
pub fn get_object_property(
&self,
path: &PropertyPath,
property: &str,
) -> Result<Option<&PropertyValue>, TdmsError> {
let property = self
.objects
.get(path.path())
.ok_or_else(|| TdmsError::MissingObject(path.path().to_owned()))?
.properties
.get(property);
Ok(property)
}
pub fn get_channel_data_positions(&self, path: &ChannelPath) -> Option<&[DataLocation]> {
self.objects
.get(path.path())
.map(|object| &object.data_locations[..])
}
pub fn channel_length(&self, path: &ChannelPath) -> Option<u64> {
self.objects.get(path.path()).map(|object| {
object
.data_locations
.iter()
.map(|location| location.number_of_samples)
.sum()
})
}
pub fn get_data_block(&self, index: usize) -> Option<&DataBlock> {
self.data_blocks.get(index)
}
}
#[cfg(test)]
mod tests {}