#![cfg_attr(feature = "std", doc = "```no_run")]
#![cfg_attr(
feature = "std",
doc = "use mdf4_rs::{MdfWriter, DataType, DecodedValue, Result};"
)]
#![cfg_attr(feature = "std", doc = "")]
#![cfg_attr(feature = "std", doc = "fn write_sensor_data() -> Result<()> {")]
#![cfg_attr(
feature = "std",
doc = " let mut writer = MdfWriter::new(\"sensor_data.mf4\")?;"
)]
#![cfg_attr(feature = "std", doc = " writer.init_mdf_file()?;")]
#![cfg_attr(feature = "std", doc = "")]
#![cfg_attr(
feature = "std",
doc = " // Create a channel group for sensor readings"
)]
#![cfg_attr(
feature = "std",
doc = " let sensors = writer.add_channel_group(None, |cg| {"
)]
#![cfg_attr(feature = "std", doc = " // Configure channel group if needed")]
#![cfg_attr(feature = "std", doc = " })?;")]
#![cfg_attr(feature = "std", doc = "")]
#![cfg_attr(feature = "std", doc = " // Add a time channel (master channel)")]
#![cfg_attr(
feature = "std",
doc = " let time_ch = writer.add_channel(&sensors, None, |ch| {"
)]
#![cfg_attr(feature = "std", doc = " ch.data_type = DataType::FloatLE;")]
#![cfg_attr(feature = "std", doc = " ch.name = Some(\"Time\".into());")]
#![cfg_attr(feature = "std", doc = " ch.bit_count = 64;")]
#![cfg_attr(feature = "std", doc = " })?;")]
#![cfg_attr(feature = "std", doc = " writer.set_time_channel(&time_ch)?;")]
#![cfg_attr(feature = "std", doc = "")]
#![cfg_attr(
feature = "std",
doc = " // Add a temperature channel linked after time"
)]
#![cfg_attr(
feature = "std",
doc = " let temp_ch = writer.add_channel(&sensors, Some(&time_ch), |ch| {"
)]
#![cfg_attr(feature = "std", doc = " ch.data_type = DataType::FloatLE;")]
#![cfg_attr(
feature = "std",
doc = " ch.name = Some(\"Temperature\".into());"
)]
#![cfg_attr(feature = "std", doc = " ch.bit_count = 64;")]
#![cfg_attr(feature = "std", doc = " })?;")]
#![cfg_attr(feature = "std", doc = "")]
#![cfg_attr(feature = "std", doc = " // Write measurement data")]
#![cfg_attr(
feature = "std",
doc = " writer.start_data_block_for_cg(&sensors, 0)?;"
)]
#![cfg_attr(feature = "std", doc = "")]
#![cfg_attr(feature = "std", doc = " writer.write_record(&sensors, &[")]
#![cfg_attr(feature = "std", doc = " DecodedValue::Float(0.0), // Time")]
#![cfg_attr(
feature = "std",
doc = " DecodedValue::Float(25.5), // Temperature"
)]
#![cfg_attr(feature = "std", doc = " ])?;")]
#![cfg_attr(feature = "std", doc = "")]
#![cfg_attr(feature = "std", doc = " writer.finish_data_block(&sensors)?;")]
#![cfg_attr(feature = "std", doc = " writer.finalize()?;")]
#![cfg_attr(feature = "std", doc = "")]
#![cfg_attr(feature = "std", doc = " Ok(())")]
#![cfg_attr(feature = "std", doc = "}")]
#![cfg_attr(feature = "std", doc = "```")]
mod open_data_block;
use alloc::collections::BTreeMap;
use alloc::string::String;
use alloc::vec::Vec;
pub(crate) use open_data_block::OpenDataBlock;
use crate::blocks::ChannelBlock;
mod data;
mod init;
mod io;
mod streaming;
mod traits;
use streaming::FlushState;
pub use streaming::{FlushPolicy, StreamingConfig};
pub use traits::{MdfWrite, VecWriter};
#[cfg(feature = "std")]
pub use traits::FileWriter;
pub struct MdfWriter<W: MdfWrite = VecWriter> {
writer: W,
offset: u64,
block_positions: BTreeMap<String, u64>,
open_dts: BTreeMap<String, OpenDataBlock>,
dt_counter: usize,
last_dg: Option<String>,
cg_to_dg: BTreeMap<String, String>,
cg_offsets: BTreeMap<String, usize>,
cg_channels: BTreeMap<String, Vec<ChannelBlock>>,
channel_map: BTreeMap<String, (String, usize)>,
streaming_config: StreamingConfig,
flush_state: FlushState,
}
impl<W: MdfWrite> MdfWriter<W> {
pub fn from_writer(writer: W) -> Self {
MdfWriter {
writer,
offset: 0,
block_positions: BTreeMap::new(),
open_dts: BTreeMap::new(),
dt_counter: 0,
last_dg: None,
cg_to_dg: BTreeMap::new(),
cg_offsets: BTreeMap::new(),
cg_channels: BTreeMap::new(),
channel_map: BTreeMap::new(),
streaming_config: StreamingConfig::default(),
flush_state: FlushState::default(),
}
}
pub fn with_flush_policy(mut self, policy: FlushPolicy) -> Self {
self.streaming_config.policy = policy;
self
}
pub fn set_flush_policy(&mut self, policy: FlushPolicy) {
self.streaming_config.policy = policy;
}
pub fn flush_policy(&self) -> &FlushPolicy {
&self.streaming_config.policy
}
pub fn streaming_stats(&self) -> (u64, u64, u64) {
(
self.flush_state.total_records,
self.flush_state.total_bytes,
self.flush_state.flush_count,
)
}
pub fn into_inner(self) -> W {
self.writer
}
pub fn writer(&self) -> &W {
&self.writer
}
pub fn writer_mut(&mut self) -> &mut W {
&mut self.writer
}
}
impl MdfWriter<VecWriter> {
pub fn in_memory() -> Self {
Self::from_writer(VecWriter::new())
}
pub fn in_memory_with_capacity(capacity: usize) -> Self {
Self::from_writer(VecWriter::with_capacity(capacity))
}
}