use std::slice;
use std::ptr;
use std::sync::Arc;
use std::{ffi::*, io::Cursor};
use crate::*;
use crate::types::*;
#[repr(C)]
pub struct ManagedBuffer {
buffer: *mut u8,
len: usize
}
impl ManagedBuffer {
pub fn new<A: AsRef<[u8]>>(item: A) -> Arc<Self> {
let boxed = item.as_ref().to_vec().into_boxed_slice();
let len = boxed.len();
let buffer = Box::into_raw(boxed).cast();
Arc::new( Self { buffer, len })
}
#[must_use]
pub fn as_raw(self: Arc<Self>) -> *const Self {
Arc::into_raw(self)
}
}
impl Drop for ManagedBuffer {
fn drop(&mut self) {
unsafe {
drop(Box::from_raw(slice::from_raw_parts_mut(self.buffer, self.len)))
}
}
}
#[no_mangle]
pub unsafe extern "C" fn free_managed_buffer(buffer: *const ManagedBuffer) {
if buffer.is_null() {return;}
drop(Arc::from_raw(buffer))
}
#[no_mangle]
pub unsafe extern "C" fn bcsv_to_csv(data: *const u8, len: usize, hash_path: *const i8, is_signed: bool, endian: u8, delim: u8) -> *const ManagedBuffer {
let slice = slice::from_raw_parts(data, len);
let mut reader = Cursor::new(slice);
let mut bcsv = BCSV::new();
let endian = match endian {
0 => Endian::Big,
1 => Endian::Little,
_ => Endian::NATIVE
};
if let Ok(_) = bcsv.read(&mut reader, endian) {
let hash_path = CStr::from_ptr(hash_path).to_string_lossy().into_owned();
let hashes = hash::read_hashes(hash_path).unwrap_or_default();
bcsv.hash_table = hashes;
let csv = bcsv.convert_to_csv(is_signed, delim as char);
let buffer = ManagedBuffer::new(csv);
buffer.as_raw()
} else {
ptr::null()
}
}
#[no_mangle]
pub unsafe extern "C" fn bcsv_to_xlsx(hash_path: *const i8, output_path: *const i8, data: *const u8, len: usize, is_signed: bool, endian: u8) {
let buffer = std::slice::from_raw_parts(data, len).to_vec();
let endian = match endian {
0 => Endian::Big,
1 => Endian::Little,
_ => Endian::NATIVE
};
let mut reader = Cursor::new(buffer);
let mut bcsv = types::BCSV::new();
bcsv.read(&mut reader, endian).unwrap_or_default();
let hash_path = CStr::from_ptr(hash_path).to_string_lossy().into_owned();
let hashes = hash::read_hashes(hash_path).unwrap_or_default();
bcsv.hash_table = hashes;
bcsv.convert_to_xlsx(CStr::from_ptr(output_path).to_string_lossy(), is_signed).unwrap_or_default();
}
#[no_mangle]
pub unsafe extern "C" fn csv_to_bcsv(path: *const i8, endian: u8, delim: u8) -> *const ManagedBuffer {
let endian = match endian {
0 => Endian::Big,
1 => Endian::Little,
_ => Endian::NATIVE
};
let path = CStr::from_ptr(path).to_string_lossy().to_string();
let bcsv = csv_parse::CSV::from_path(path, delim as char).unwrap_or_default();
let data = bcsv.to_bytes(endian).unwrap_or_default();
let buffer = ManagedBuffer::new(data);
Arc::into_raw(buffer)
}