fstapi/
writer.rs

1use crate::consts::{AttrType, FileType, ScopeType, VarDir, VarType, WriterPackType};
2use crate::types::Handle;
3use crate::utils::*;
4use crate::{Error, Result, capi};
5use std::os::raw;
6use std::path::Path;
7
8/// FST waveform writer.
9#[derive(Debug)]
10pub struct Writer {
11  /// Non-null context pointer.
12  ctx: *mut raw::c_void,
13}
14
15impl Writer {
16  /// Creates a new [`Writer`], writes the output waveform to the given path.
17  pub fn create<P>(path: P, use_compressed_hier: bool) -> Result<Self>
18  where
19    P: AsRef<Path>,
20  {
21    let path = path.to_str()?.into_cstring()?;
22    let ctx = unsafe { capi::fstWriterCreate(path.as_ptr(), use_compressed_hier as raw::c_int) };
23    if ctx.is_null() {
24      Err(Error::ContextCreate)
25    } else {
26      Ok(Self { ctx })
27    }
28  }
29
30  /// Sets comment.
31  pub fn comment(self, comment: &str) -> Result<Self> {
32    let comment = comment.into_cstring()?;
33    unsafe { capi::fstWriterSetComment(self.ctx, comment.as_ptr()) };
34    Ok(self)
35  }
36
37  /// Sets date.
38  pub fn date(self, date: &str) -> Result<Self> {
39    let date = date.into_cstring()?;
40    unsafe { capi::fstWriterSetDate(self.ctx, date.as_ptr()) };
41    Ok(self)
42  }
43
44  /// Sets date from the given raw C string.
45  ///
46  /// # Safety
47  ///
48  /// The memory pointed to by `date` must contain a valid nul terminator
49  /// at the end of the string.
50  pub unsafe fn date_raw(self, date: *const raw::c_char) -> Self {
51    unsafe { capi::fstWriterSetDate(self.ctx, date) };
52    self
53  }
54
55  /// Sets file type.
56  pub fn file_type(self, ty: FileType) -> Self {
57    unsafe { capi::fstWriterSetFileType(self.ctx, ty) };
58    self
59  }
60
61  /// Sets pack type.
62  pub fn pack_type(self, ty: WriterPackType) -> Self {
63    unsafe { capi::fstWriterSetPackType(self.ctx, ty) };
64    self
65  }
66
67  /// Sets parallel mode.
68  pub fn parallel_mode(self, enable: bool) -> Self {
69    unsafe { capi::fstWriterSetParallelMode(self.ctx, enable as raw::c_int) };
70    self
71  }
72
73  /// Sets repack on close.
74  pub fn repack_on_close(self, enable: bool) -> Self {
75    unsafe { capi::fstWriterSetRepackOnClose(self.ctx, enable as raw::c_int) };
76    self
77  }
78
79  /// Sets timescale.
80  pub fn timescale(self, timescale: i32) -> Self {
81    unsafe { capi::fstWriterSetTimescale(self.ctx, timescale) };
82    self
83  }
84
85  /// Sets timescale from the given string.
86  pub fn timescale_from_str(self, timescale: &str) -> Result<Self> {
87    let timescale = timescale.into_cstring()?;
88    unsafe { capi::fstWriterSetTimescaleFromString(self.ctx, timescale.as_ptr()) };
89    Ok(self)
90  }
91
92  /// Sets timezero.
93  pub fn timezero(self, timezero: i64) -> Self {
94    unsafe { capi::fstWriterSetTimezero(self.ctx, timezero) };
95    self
96  }
97
98  /// Sets version.
99  pub fn version(self, version: &str) -> Result<Self> {
100    let version = version.into_cstring()?;
101    unsafe { capi::fstWriterSetVersion(self.ctx, version.as_ptr()) };
102    Ok(self)
103  }
104
105  /// Sets version from the given raw C string.
106  ///
107  /// # Safety
108  ///
109  /// The memory pointed to by `version` must contain a valid nul terminator
110  /// at the end of the string.
111  pub unsafe fn version_raw(self, version: *const raw::c_char) -> Self {
112    unsafe { capi::fstWriterSetVersion(self.ctx, version) };
113    self
114  }
115
116  /// Sets attribute begin.
117  pub fn set_attr_begin(&mut self, ty: AttrType, sub_ty: u32, name: &str, arg: u64) -> Result<()> {
118    let name = name.into_cstring()?;
119    unsafe { capi::fstWriterSetAttrBegin(self.ctx, ty, sub_ty as _, name.as_ptr(), arg) };
120    Ok(())
121  }
122
123  /// Sets attribute end.
124  pub fn set_attr_end(&mut self) {
125    unsafe { capi::fstWriterSetAttrEnd(self.ctx) }
126  }
127
128  /// Sets scope.
129  pub fn set_scope(&mut self, ty: ScopeType, name: &str, component: &str) -> Result<()> {
130    let name = name.into_cstring()?;
131    let component = component.into_cstring()?;
132    unsafe { capi::fstWriterSetScope(self.ctx, ty, name.as_ptr(), component.as_ptr()) };
133    Ok(())
134  }
135
136  /// Sets upscope.
137  pub fn set_upscope(&mut self) {
138    unsafe { capi::fstWriterSetUpscope(self.ctx) }
139  }
140
141  /// Creates a new variable.
142  pub fn create_var(
143    &mut self,
144    ty: VarType,
145    dir: VarDir,
146    len: u32,
147    name: &str,
148    alias: Option<Handle>,
149  ) -> Result<Handle> {
150    let name = name.into_cstring()?;
151    Handle::new(unsafe {
152      capi::fstWriterCreateVar(self.ctx, ty, dir, len, name.as_ptr(), alias.into_handle())
153    })
154    .ok_or(Error::InvalidOperation)
155  }
156
157  /// Emits value change for the given handle.
158  pub fn emit_value_change(&mut self, handle: Handle, value: &[u8]) -> Result<()> {
159    let ret = unsafe {
160      capi::fstWriterEmitValueChange(
161        self.ctx,
162        handle.into(),
163        value.as_ptr() as *const raw::c_void,
164        value.len() as u32,
165      )
166    };
167    match ret {
168      0 => Ok(()),
169      _ => Err(Error::InvalidOperation),
170    }
171  }
172
173  /// Emits vairable-length value change for the given handle.
174  pub fn emit_var_len_value_change(&mut self, handle: Handle, value: &[u8]) -> Result<()> {
175    let ret = unsafe {
176      capi::fstWriterEmitVariableLengthValueChange(
177        self.ctx,
178        handle.into(),
179        value.as_ptr() as *const raw::c_void,
180        value.len() as u32,
181      )
182    };
183    match ret {
184      0 => Ok(()),
185      _ => Err(Error::InvalidOperation),
186    }
187  }
188
189  /// Emits time change.
190  pub fn emit_time_change(&mut self, time: u64) -> Result<()> {
191    match unsafe { capi::fstWriterEmitTimeChange(self.ctx, time) } {
192      0 => Ok(()),
193      _ => Err(Error::InvalidOperation),
194    }
195  }
196
197  /// Flushes the content of the current writer to file.
198  pub fn flush(&mut self) {
199    unsafe { capi::fstWriterFlushContext(self.ctx) }
200  }
201}
202
203impl Drop for Writer {
204  fn drop(&mut self) {
205    unsafe { capi::fstWriterClose(self.ctx) }
206  }
207}