use crate::workbook::{buffer_to_vec, check, check_abi_version};
use crate::writer::format_from_path;
use crate::{
Date, Error, Time, Timestamp, WriteOptions, XlBuffer, XlWriterHandle, XL_T_BOOL, XL_T_DATE,
XL_T_F64, XL_T_I64, XL_T_TIME, XL_T_TIMESTAMP,
};
pub struct WriterHandle {
handle: *mut XlWriterHandle,
}
impl WriterHandle {
pub fn open(path: &str, options: Option<&WriteOptions>) -> Result<Self, Error> {
Self::open_with(path, format_from_path(path), options)
}
pub fn open_with(
path: &str,
format: i32,
options: Option<&WriteOptions>,
) -> Result<Self, Error> {
check_abi_version()?;
let raw = options.map(WriteOptions::to_raw);
let raw_ptr = crate::options::ptr_or_null(&raw);
let mut handle: *mut XlWriterHandle = std::ptr::null_mut();
let status = unsafe {
crate::xl_open_write_handle(
path.as_ptr(),
path.len() as i32,
format,
raw_ptr,
&mut handle,
)
};
check(status)?;
Ok(WriterHandle { handle })
}
pub fn open_memory(format: i32, options: Option<&WriteOptions>) -> Result<Self, Error> {
check_abi_version()?;
let raw = options.map(WriteOptions::to_raw);
let raw_ptr = crate::options::ptr_or_null(&raw);
let mut handle: *mut XlWriterHandle = std::ptr::null_mut();
let status = unsafe { crate::xl_open_write_handle_to_memory(format, raw_ptr, &mut handle) };
check(status)?;
Ok(WriterHandle { handle })
}
pub fn start_sheet(&mut self, name: &str) -> Result<(), Error> {
check(unsafe { crate::xl_start_sheet(self.handle, name.as_ptr(), name.len() as i32) })
}
pub fn start_row(&mut self) -> Result<(), Error> {
check(unsafe { crate::xl_start_row(self.handle) })
}
pub fn write_str(&mut self, value: Option<&str>) -> Result<(), Error> {
let (ptr, len) = value.map_or((std::ptr::null(), 0), |text| {
(text.as_ptr(), text.len() as i32)
});
check(unsafe { crate::xl_write_string(self.handle, ptr, len) })
}
pub fn write_i64(&mut self, value: Option<i64>) -> Result<(), Error> {
match value {
Some(v) => check(unsafe { crate::xl_write_int64(self.handle, v) }),
None => self.write_null(XL_T_I64),
}
}
pub fn write_f64(&mut self, value: Option<f64>) -> Result<(), Error> {
match value {
Some(v) => check(unsafe { crate::xl_write_float64(self.handle, v) }),
None => self.write_null(XL_T_F64),
}
}
pub fn write_bool(&mut self, value: Option<bool>) -> Result<(), Error> {
match value {
Some(v) => check(unsafe { crate::xl_write_bool(self.handle, i32::from(v)) }),
None => self.write_null(XL_T_BOOL),
}
}
pub fn write_date(&mut self, value: Option<Date>) -> Result<(), Error> {
match value {
Some(v) => check(unsafe { crate::xl_write_date(self.handle, v.days_since_epoch) }),
None => self.write_null(XL_T_DATE),
}
}
pub fn write_time(&mut self, value: Option<Time>) -> Result<(), Error> {
match value {
Some(v) => check(unsafe { crate::xl_write_time(self.handle, v.micros_since_midnight) }),
None => self.write_null(XL_T_TIME),
}
}
pub fn write_timestamp(&mut self, value: Option<Timestamp>) -> Result<(), Error> {
match value {
Some(v) => {
check(unsafe { crate::xl_write_timestamp(self.handle, v.micros_since_epoch) })
}
None => self.write_null(XL_T_TIMESTAMP),
}
}
pub fn write_null(&mut self, xl_type: i32) -> Result<(), Error> {
check(unsafe { crate::xl_write_null(self.handle, xl_type) })
}
pub fn end_row(&mut self) -> Result<(), Error> {
check(unsafe { crate::xl_end_row(self.handle) })
}
pub fn end_sheet(&mut self) -> Result<(), Error> {
check(unsafe { crate::xl_end_sheet(self.handle) })
}
pub fn bytes(&mut self) -> Result<Vec<u8>, Error> {
let mut buffer = XlBuffer {
data: std::ptr::null_mut(),
len: 0,
};
let status = unsafe { crate::xl_write_handle_bytes(self.handle, &mut buffer) };
check(status)?;
Ok(buffer_to_vec(buffer))
}
}
impl Drop for WriterHandle {
fn drop(&mut self) {
if self.handle.is_null() {
return;
}
unsafe {
crate::xl_close_write_handle(self.handle);
}
self.handle = std::ptr::null_mut();
}
}
impl std::fmt::Debug for WriterHandle {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("WriterHandle").finish_non_exhaustive()
}
}