pub struct RecordingWriter { /* private fields */ }Expand description
Writes a new plain recording (dataset and metadata) without replacing existing files.
Frames passed to write_frames are encoded into a
hidden temporary file next to the final dataset. finish
computes the dataset’s SHA-512 digest, stores it in core:sha512, and
publishes the dataset and then the metadata. Each file appears under its
final name atomically and only if that name is unused, but the pair is not
published atomically: if the process is interrupted between the two steps an
orphan dataset can remain, but metadata is never published for a dataset
that was not. Dropping the writer without calling finish removes the
temporary data.
§Examples
use num_complex::Complex;
use sigmf::datatype::Datatype;
use sigmf::global::Global;
use sigmf::meta::Metadata;
use sigmf::recording_file::{Recording, RecordingWriter};
use sigmf::utils::data::SampleValue;
use std::str::FromStr;
let unique = std::time::SystemTime::now().duration_since(std::time::UNIX_EPOCH)?.as_nanos();
let dir = std::env::temp_dir().join(format!("sigmf-doc-{}-{unique}", std::process::id()));
std::fs::create_dir_all(&dir)?;
let metadata_path = dir.join("example.sigmf-meta");
let mut global = Global::new("1.2.6", Datatype::from_str("cf32_le")?);
global.sample_rate = Some(1e6);
global.num_channels = Some(2);
let metadata = Metadata::new(global, Vec::new(), Vec::new());
// The dataset is written to `example.sigmf-data` in the same directory.
let mut writer = RecordingWriter::new(&metadata_path, metadata)?;
writer.write_frames(&[
SampleValue::ComplexF32(Complex::new(1.0, 0.0)), // frame 0, channel 0
SampleValue::ComplexF32(Complex::new(0.0, 1.0)), // frame 0, channel 1
SampleValue::ComplexF32(Complex::new(-1.0, 0.0)), // frame 1, channel 0
SampleValue::ComplexF32(Complex::new(0.0, -1.0)), // frame 1, channel 1
])?;
let digest = writer.finish()?;
let mut recording = Recording::open(&metadata_path)?;
assert_eq!(recording.metadata().global().sha512.as_deref(), Some(digest.as_str()));
assert_eq!(recording.dataset_path(), Some(dir.join("example.sigmf-data").as_path()));
recording.verify_dataset_digest()?;
assert_eq!(recording.frame_count()?, 2);
assert_eq!(
recording.read_frames(1, 1)?,
[
SampleValue::ComplexF32(Complex::new(-1.0, 0.0)),
SampleValue::ComplexF32(Complex::new(0.0, -1.0)),
]
);
std::fs::remove_dir_all(&dir)?;Implementations§
Source§impl RecordingWriter
impl RecordingWriter
Sourcepub fn new(
metadata_path: impl AsRef<Path>,
metadata: Metadata,
) -> Result<Self, SigmfError>
pub fn new( metadata_path: impl AsRef<Path>, metadata: Metadata, ) -> Result<Self, SigmfError>
Creates a writer for a new recording whose metadata will be written to
metadata_path.
metadata_path must end in .sigmf-meta and its parent directory must
exist. The dataset is written next to it, named by core:dataset when
set, or otherwise by replacing the .sigmf-meta suffix with
.sigmf-data. Neither file may exist yet. core:sha512 is filled in by
finish; NCD capture headers and trailing bytes are not
synthesized.
§Errors
SigmfError::InvalidMetadataifmetadata_pathdoes not end in.sigmf-meta, the metadata failsInteroperabilityvalidation,core:datasetis not a safe filename, either destination file already exists, orcore:num_channelsis zero or does not fit in ausize.SigmfError::UnsupportedLayoutif the metadata iscore:metadata_onlyor declarescore:header_bytesorcore:trailing_bytes.SigmfError::IoorSigmfError::ResourceLimitif the temporary dataset file cannot be created.
Sourcepub fn write_frames(
&mut self,
samples: &[SampleValue],
) -> Result<(), SigmfError>
pub fn write_frames( &mut self, samples: &[SampleValue], ) -> Result<(), SigmfError>
Encodes and appends one block of complete frames.
samples holds one SampleValue per channel per frame, in on-disk
order, using the variant that matches core:datatype.
§Errors
Returns an error if the samples do not form complete frames or do not
match the datatype (see data::encode), or SigmfError::Io if
writing the temporary dataset fails.
Sourcepub fn finish(self) -> Result<String, SigmfError>
pub fn finish(self) -> Result<String, SigmfError>
Flushes and publishes both files, returning the dataset’s SHA-512 digest.
The temporary dataset and metadata files are synced to disk and then published by hard-linking them to their final names, so the destination file system must support hard links. If the metadata cannot be published, the already published dataset is removed again.
§Errors
SigmfError::InvalidMetadataif the metadata fails validation aftercore:sha512is set.SigmfError::ResourceLimitif the serialized metadata exceeds the 1,000,000-byte metadata size limit.SigmfError::Ioif flushing, hashing, or publishing fails, including when a destination file was created by someone else in the meantime.
Trait Implementations§
Source§impl Drop for RecordingWriter
impl Drop for RecordingWriter
Auto Trait Implementations§
impl Freeze for RecordingWriter
impl RefUnwindSafe for RecordingWriter
impl Send for RecordingWriter
impl Sync for RecordingWriter
impl Unpin for RecordingWriter
impl UnsafeUnpin for RecordingWriter
impl UnwindSafe for RecordingWriter
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
§impl<T> Instrument for T
impl<T> Instrument for T
§fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more