use std::cell::RefCell;
use std::error::Error;
use std::fmt::{self, Debug, Display};
use std::ops::{Deref, DerefMut};
use crate::context::Context;
use crate::result::{NeonResult, ResultExt};
use self::lock::{Ledger, Lock};
pub(crate) mod lock;
pub(super) mod types;
pub trait TypedArray: private::Sealed {
type Item;
fn as_slice<'a: 'b, 'b, C>(&'b self, cx: &'b C) -> &'b [Self::Item]
where
C: Context<'a>;
fn as_mut_slice<'a: 'b, 'b, C>(&'b mut self, cx: &'b mut C) -> &'b mut [Self::Item]
where
C: Context<'a>;
fn try_borrow<'a: 'b, 'b, C>(
&self,
lock: &'b Lock<'b, C>,
) -> Result<Ref<'b, Self::Item>, BorrowError>
where
C: Context<'a>;
fn try_borrow_mut<'a: 'b, 'b, C>(
&mut self,
lock: &'b Lock<'b, C>,
) -> Result<RefMut<'b, Self::Item>, BorrowError>
where
C: Context<'a>;
}
#[derive(Debug)]
pub struct Ref<'a, T> {
data: &'a [T],
ledger: &'a RefCell<Ledger>,
}
#[derive(Debug)]
pub struct RefMut<'a, T> {
data: &'a mut [T],
ledger: &'a RefCell<Ledger>,
}
impl<'a, T> Deref for Ref<'a, T> {
type Target = [T];
fn deref(&self) -> &Self::Target {
&self.data
}
}
impl<'a, T> Deref for RefMut<'a, T> {
type Target = [T];
fn deref(&self) -> &Self::Target {
&self.data
}
}
impl<'a, T> DerefMut for RefMut<'a, T> {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.data
}
}
impl<'a, T> Drop for Ref<'a, T> {
fn drop(&mut self) {
let mut ledger = self.ledger.borrow_mut();
let range = Ledger::slice_to_range(&self.data);
let i = ledger.shared.iter().rposition(|r| r == &range).unwrap();
ledger.shared.remove(i);
}
}
impl<'a, T> Drop for RefMut<'a, T> {
fn drop(&mut self) {
let mut ledger = self.ledger.borrow_mut();
let range = Ledger::slice_to_range(&self.data);
let i = ledger.owned.iter().rposition(|r| r == &range).unwrap();
ledger.owned.remove(i);
}
}
#[derive(Eq, PartialEq)]
pub struct BorrowError {
_private: (),
}
impl BorrowError {
fn new() -> Self {
BorrowError { _private: () }
}
}
impl Error for BorrowError {}
impl Display for BorrowError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
Display::fmt("Borrow overlaps with an active mutable borrow", f)
}
}
impl Debug for BorrowError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("BorrowError").finish()
}
}
impl<T> ResultExt<T> for Result<T, BorrowError> {
fn or_throw<'a, C: Context<'a>>(self, cx: &mut C) -> NeonResult<T> {
self.or_else(|_| cx.throw_error("BorrowError"))
}
}
mod private {
pub trait Sealed {}
}