use std::ffi::CString;
use crate::ffi;
use crate::header::{encode_header, encoding_info_to_yaml};
use crate::types::EncodingInfo;
use crate::{Error, Result};
pub struct CppPointcloudEncoder {
info: EncodingInfo,
header: Vec<u8>,
yaml_header: CString,
use_threads: bool,
}
impl CppPointcloudEncoder {
pub fn new(info: EncodingInfo) -> Self {
let yaml = encoding_info_to_yaml(&info);
let header = encode_header(&info);
Self {
yaml_header: CString::new(yaml).expect("YAML header contained a null byte"),
info,
header,
use_threads: true,
}
}
pub fn with_threads(mut self, use_threads: bool) -> Self {
self.use_threads = use_threads;
self
}
pub fn encoding_info(&self) -> &EncodingInfo {
&self.info
}
pub fn header_bytes(&self) -> &[u8] {
&self.header
}
pub fn encode(&self, cloud_data: &[u8]) -> Result<Vec<u8>> {
let max_out = cloud_data.len().saturating_mul(2).max(65_536);
let mut output = vec![0u8; max_out];
let written = unsafe {
ffi::cloudini_c_encode(
self.yaml_header.as_ptr(),
cloud_data.as_ptr(),
cloud_data.len() as u32,
output.as_mut_ptr(),
max_out as u32,
self.use_threads as i32,
)
};
if written == 0 {
return Err(Error::Cpp("encode returned 0".into()));
}
output.truncate(written as usize);
Ok(output)
}
pub fn encode_chunks(&self, cloud_data: &[u8], out: &mut Vec<u8>) -> Result<()> {
let full = self.encode(cloud_data)?;
let (_, header_len) = crate::header::decode_header(&full)?;
out.extend_from_slice(&full[header_len..]);
Ok(())
}
}