#![allow(unsafe_code)]
use std::ops::Deref;
use std::sync::Arc;
#[derive(Clone, Debug)]
pub struct F64Buffer {
inner: F64BufferInner,
}
#[derive(Clone, Debug)]
enum F64BufferInner {
Owned(Arc<[f64]>),
Foreign(ForeignF64Buffer),
}
#[derive(Clone, Debug)]
pub struct ForeignF64Buffer {
owner: Arc<dyn ForeignBufferOwner>,
ptr: *const f64,
len: usize,
}
impl Drop for ForeignF64Buffer {
fn drop(&mut self) {
let _ = Arc::as_ptr(&self.owner);
}
}
pub trait ForeignBufferOwner: Send + Sync + std::fmt::Debug {}
impl<T: Send + Sync + std::fmt::Debug + 'static> ForeignBufferOwner for T {}
unsafe impl Send for ForeignF64Buffer {}
unsafe impl Sync for ForeignF64Buffer {}
impl ForeignF64Buffer {
#[must_use]
pub unsafe fn new(owner: Arc<dyn ForeignBufferOwner>, ptr: *const f64, len: usize) -> Self {
Self { owner, ptr, len }
}
#[must_use]
pub fn as_slice(&self) -> &[f64] {
if self.len == 0 {
return &[];
}
unsafe { std::slice::from_raw_parts(self.ptr, self.len) }
}
#[must_use]
pub const fn len(&self) -> usize {
self.len
}
#[must_use]
pub const fn is_empty(&self) -> bool {
self.len == 0
}
}
impl F64Buffer {
#[must_use]
pub fn owned(values: impl Into<Arc<[f64]>>) -> Self {
Self { inner: F64BufferInner::Owned(values.into()) }
}
#[must_use]
pub fn foreign(buf: ForeignF64Buffer) -> Self {
Self { inner: F64BufferInner::Foreign(buf) }
}
#[must_use]
pub const fn is_foreign(&self) -> bool {
matches!(self.inner, F64BufferInner::Foreign(_))
}
#[must_use]
pub fn nbytes(&self) -> u64 {
(self.len() * core::mem::size_of::<f64>()) as u64
}
#[must_use]
pub fn as_slice(&self) -> &[f64] {
match &self.inner {
F64BufferInner::Owned(v) => v.as_ref(),
F64BufferInner::Foreign(f) => f.as_slice(),
}
}
#[must_use]
pub fn len(&self) -> usize {
match &self.inner {
F64BufferInner::Owned(v) => v.len(),
F64BufferInner::Foreign(f) => f.len(),
}
}
#[must_use]
pub fn is_empty(&self) -> bool {
self.len() == 0
}
}
impl Deref for F64Buffer {
type Target = [f64];
fn deref(&self) -> &[f64] {
self.as_slice()
}
}
impl From<Arc<[f64]>> for F64Buffer {
fn from(value: Arc<[f64]>) -> Self {
Self::owned(value)
}
}
impl From<Vec<f64>> for F64Buffer {
fn from(value: Vec<f64>) -> Self {
Self::owned(Arc::<[f64]>::from(value))
}
}
impl PartialEq for F64Buffer {
fn eq(&self, other: &Self) -> bool {
self.as_slice() == other.as_slice()
}
}