#![deny(unsafe_op_in_unsafe_fn)]
use crate::src::c_box::CBox;
use crate::src::error::Rav1dResult;
#[cfg(feature = "c-ffi")]
use std::marker::PhantomData;
use std::ops::Deref;
#[cfg(feature = "c-ffi")]
use std::pin::Pin;
#[cfg(feature = "c-ffi")]
use std::ptr::NonNull;
use std::sync::Arc;
#[cfg(feature = "c-ffi")]
pub fn arc_into_raw<T: ?Sized>(arc: Arc<T>) -> NonNull<T> {
let raw = Arc::into_raw(arc).cast_mut();
unsafe { NonNull::new_unchecked(raw) }
}
#[cfg(not(feature = "c-ffi"))]
#[derive(Debug)]
pub struct CArc<T: ?Sized> {
owner: Arc<Box<T>>,
view: Option<(usize, usize)>,
}
#[cfg(feature = "c-ffi")]
#[derive(Debug)]
pub struct CArc<T: ?Sized> {
owner: Arc<Pin<CBox<T>>>,
#[cfg(debug_assertions)]
base_stable_ref: StableRef<T>,
stable_ref: StableRef<T>,
}
#[cfg(feature = "c-ffi")]
#[derive(Debug)]
struct StableRef<T: ?Sized>(NonNull<T>);
#[cfg(feature = "c-ffi")]
impl<T: ?Sized> Clone for StableRef<T> {
fn clone(&self) -> Self {
*self
}
}
#[cfg(feature = "c-ffi")]
impl<T: ?Sized> Copy for StableRef<T> {}
#[cfg(feature = "c-ffi")]
#[allow(unsafe_code)]
unsafe impl<T: Send + ?Sized> Send for StableRef<T> {}
#[cfg(feature = "c-ffi")]
#[allow(unsafe_code)]
unsafe impl<T: Send + ?Sized> Sync for StableRef<T> {}
#[cfg(feature = "c-ffi")]
impl<T: ?Sized> AsRef<T> for CArc<T> {
#[allow(unsafe_code)]
fn as_ref(&self) -> &T {
#[cfg(debug_assertions)]
{
use std::mem;
use std::ptr;
use to_method::To;
let real_ref = (*self.owner).as_ref().get_ref();
assert_eq!(real_ref.to::<NonNull<T>>(), self.base_stable_ref.0);
let real_ptr = ptr::from_ref(real_ref);
let stable_ptr = self.stable_ref.0.as_ptr().cast_const();
let [real_address, stable_address] =
[real_ptr, stable_ptr].map(|ptr| ptr.cast::<()>() as isize);
let offset = stable_address - real_address;
let len = mem::size_of_val(real_ref);
if offset < 0 || offset > len as isize {
panic!(
"CArc::stable_ref is out of bounds:
real_ref: {real_ptr:?}
stable_ref: {stable_ptr:?}
offset: {offset}
len: {len}"
);
}
}
unsafe { self.stable_ref.0.as_ref() }
}
}
#[cfg(feature = "c-ffi")]
impl<T: ?Sized> Deref for CArc<T> {
type Target = T;
fn deref(&self) -> &Self::Target {
self.as_ref()
}
}
#[cfg(not(feature = "c-ffi"))]
impl Deref for CArc<u8> {
type Target = u8;
fn deref(&self) -> &u8 {
&self.owner
}
}
#[cfg(not(feature = "c-ffi"))]
impl<T> Deref for CArc<[T]> {
type Target = [T];
fn deref(&self) -> &[T] {
let full: &[T] = &self.owner;
match self.view {
None => full,
Some((start, end)) => &full[start..end],
}
}
}
#[cfg(not(feature = "c-ffi"))]
impl<T: ?Sized> Clone for CArc<T> {
fn clone(&self) -> Self {
Self {
owner: self.owner.clone(),
view: self.view,
}
}
}
#[cfg(feature = "c-ffi")]
impl<T: ?Sized> Clone for CArc<T> {
fn clone(&self) -> Self {
let Self {
owner,
#[cfg(debug_assertions)]
base_stable_ref,
stable_ref,
} = self;
Self {
owner: owner.clone(),
#[cfg(debug_assertions)]
base_stable_ref: base_stable_ref.clone(),
stable_ref: stable_ref.clone(),
}
}
}
#[cfg(not(feature = "c-ffi"))]
impl<T: ?Sized> CArc<T> {
pub fn wrap(owner: CBox<T>) -> Rav1dResult<Self> {
let CBox::Rust(boxed) = owner;
Ok(Self {
owner: Arc::new(boxed), view: None,
})
}
}
#[cfg(feature = "c-ffi")]
impl<T: ?Sized> From<Arc<Pin<CBox<T>>>> for CArc<T> {
fn from(owner: Arc<Pin<CBox<T>>>) -> Self {
let stable_ref = StableRef((*owner).as_ref().get_ref().into());
Self {
owner,
#[cfg(debug_assertions)]
base_stable_ref: stable_ref,
stable_ref,
}
}
}
#[cfg(feature = "c-ffi")]
impl<T: ?Sized> CArc<T> {
pub fn wrap(owner: CBox<T>) -> Rav1dResult<Self> {
let owner = Arc::new(owner.into_pin()); Ok(owner.into())
}
}
#[cfg(feature = "c-ffi")]
#[repr(transparent)]
pub struct RawArc<T>(NonNull<PhantomData<T>>);
#[cfg(feature = "c-ffi")]
impl<T> Clone for RawArc<T> {
fn clone(&self) -> Self {
*self
}
}
#[cfg(feature = "c-ffi")]
impl<T> Copy for RawArc<T> {}
#[cfg(feature = "c-ffi")]
impl<T> RawArc<T> {
pub fn from_arc(arc: Arc<T>) -> Self {
Self(arc_into_raw(arc).cast())
}
pub unsafe fn as_ref(&self) -> &T {
unsafe { self.0.cast().as_ref() }
}
pub unsafe fn into_arc(self) -> Arc<T> {
let raw = self.0.cast().as_ptr();
unsafe { Arc::from_raw(raw) }
}
}
#[cfg(feature = "c-ffi")]
#[repr(transparent)]
pub struct RawCArc<T: ?Sized>(RawArc<Pin<CBox<T>>>);
#[cfg(feature = "c-ffi")]
impl<T: ?Sized> CArc<T> {
pub fn into_raw(self) -> RawCArc<T> {
RawCArc(RawArc::from_arc(self.owner))
}
pub unsafe fn from_raw(raw: RawCArc<T>) -> Self {
let owner = unsafe { raw.0.into_arc() };
owner.into()
}
}
#[cfg(not(feature = "c-ffi"))]
impl<T> CArc<[T]> {
pub fn slice_in_place<I>(&mut self, range: I)
where
I: std::slice::SliceIndex<[T], Output = [T]>,
{
let full: &[T] = &self.owner;
let (cur_start, cur_end) = self.view.unwrap_or((0, full.len()));
let current = &full[cur_start..cur_end];
let sub = ¤t[range];
let byte_offset = sub.as_ptr() as usize - current.as_ptr() as usize;
let elem_offset = byte_offset / std::mem::size_of::<T>();
let new_start = cur_start + elem_offset;
let new_end = new_start + sub.len();
self.view = Some((new_start, new_end));
}
pub fn split_at(this: Self, mid: usize) -> (Self, Self) {
let mut first = this.clone();
let mut second = this;
first.slice_in_place(..mid);
second.slice_in_place(mid..);
(first, second)
}
}
#[cfg(feature = "c-ffi")]
impl<T> CArc<[T]> {
pub fn slice_in_place<I>(&mut self, range: I)
where
I: std::slice::SliceIndex<[T], Output = [T]>,
{
self.stable_ref = StableRef(self.as_ref()[range].into());
}
pub fn split_at(this: Self, mid: usize) -> (Self, Self) {
let mut first = this.clone();
let mut second = this;
first.slice_in_place(..mid);
second.slice_in_place(mid..);
(first, second)
}
}
impl<T> CArc<[T]>
where
T: Default + 'static,
{
#[cfg(feature = "c-ffi")]
pub fn zeroed_slice(size: usize) -> Rav1dResult<Self> {
let owned_slice = (0..size).map(|_| Default::default()).collect::<Box<[_]>>(); Self::wrap(CBox::from_box(owned_slice))
}
}