use std::{fmt::Debug, fmt::Formatter};
use std::{ptr::NonNull, sync::Arc};
use super::foreign::MaybeForeign;
use crate::ffi;
use crate::types::NativeType;
pub enum Deallocation {
Native,
Foreign(Arc<ffi::InternalArrowArray>),
}
impl Debug for Deallocation {
fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
match self {
Deallocation::Native => {
write!(f, "Deallocation::Native")
}
Deallocation::Foreign(_) => {
write!(f, "Deallocation::Foreign {{ capacity: unknown }}")
}
}
}
}
pub struct Bytes<T: NativeType> {
data: MaybeForeign<T>,
deallocation: Deallocation,
}
impl<T: NativeType> Bytes<T> {
#[inline]
pub unsafe fn from_ffi(
ptr: std::ptr::NonNull<T>,
len: usize,
deallocation: Deallocation,
) -> Self {
assert!(matches!(deallocation, Deallocation::Foreign(_)));
let data = Vec::from_raw_parts(ptr.as_ptr(), len, len);
let data = MaybeForeign::new(data);
Self { data, deallocation }
}
#[inline]
fn as_slice(&self) -> &[T] {
self
}
#[inline]
pub fn len(&self) -> usize {
self.data.len()
}
#[inline]
pub fn ptr(&self) -> NonNull<T> {
debug_assert!(!self.data.as_ptr().is_null());
unsafe { NonNull::new_unchecked(self.data.as_ptr() as *mut T) }
}
pub fn get_vec(&mut self) -> Option<&mut Vec<T>> {
match &self.deallocation {
Deallocation::Foreign(_) => None,
Deallocation::Native => Some(unsafe { self.data.mut_vec() }),
}
}
}
impl<T: NativeType> Drop for Bytes<T> {
fn drop(&mut self) {
match self.deallocation {
Deallocation::Foreign(_) => {}
Deallocation::Native => {
unsafe { self.data.drop_local() }
}
}
}
}
impl<T: NativeType> std::ops::Deref for Bytes<T> {
type Target = [T];
fn deref(&self) -> &[T] {
&self.data
}
}
impl<T: NativeType> PartialEq for Bytes<T> {
fn eq(&self, other: &Bytes<T>) -> bool {
self.as_slice() == other.as_slice()
}
}
impl<T: NativeType> Debug for Bytes<T> {
fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
write!(
f,
"Bytes {{ ptr: {:?}, len: {}, data: ",
self.data.as_ptr(),
self.len(),
)?;
f.debug_list().entries(self.iter()).finish()?;
write!(f, " }}")
}
}
impl<T: NativeType> From<Vec<T>> for Bytes<T> {
#[inline]
fn from(data: Vec<T>) -> Self {
let data = MaybeForeign::new(data);
Self {
data,
deallocation: Deallocation::Native,
}
}
}
unsafe impl<T: NativeType> Send for Bytes<T> {}
unsafe impl<T: NativeType> Sync for Bytes<T> {}