pub struct HeapCell<T> {
inner: *mut T,
}
impl<T> Clone for HeapCell<T> {
fn clone(&self) -> Self {
Self {
inner: self.inner.clone(),
}
}
}
impl<T> HeapCell<T> {
pub fn new(val: T) -> Self {
Self {
inner: Box::leak(Box::new(val)) as *mut T,
}
}
pub unsafe fn as_mut(&self) -> &mut T {
&mut *self.inner
}
pub unsafe fn as_ref(&self) -> &T {
&*self.inner
}
pub unsafe fn take(&self) -> T {
std::ptr::read(self.inner)
}
pub unsafe fn drop_n_dealloc(&self) {
let ptr = self.inner;
std::ptr::drop_in_place(ptr);
std::alloc::dealloc(ptr as *mut u8, std::alloc::Layout::new::<T>());
}
pub fn clone_inner(&self) -> HeapCell<T>
where
T: Clone,
{
let clone = unsafe { self.inner.as_ref().unwrap() }.clone();
HeapCell::new(clone)
}
pub unsafe fn replace(&self, mut val: T) -> T {
std::mem::swap(unsafe { self.as_mut() }, &mut val);
val
}
#[inline]
pub unsafe fn drop(&self) {
std::ptr::drop_in_place(self.inner);
}
#[inline]
pub unsafe fn dealloc(&self) {
std::alloc::dealloc(self.inner as *mut u8, std::alloc::Layout::new::<T>());
}
}
#[repr(transparent)]
pub struct BorrowFlag {
inner: std::cell::UnsafeCell<isize>,
}
impl BorrowFlag {
pub fn new() -> Self {
Self {
inner: std::cell::UnsafeCell::new(0),
}
}
pub fn can_borrow(&self) -> bool {
unsafe { *self.inner.get() >= 0 }
}
pub fn can_borrow_mut(&self) -> bool {
unsafe { *self.inner.get() == 0 }
}
pub fn can_own(&self) -> bool {
self.can_borrow_mut()
}
pub fn borrow(&self) {
unsafe { std::ptr::write(self.inner.get(), *self.inner.get() + 1) }
}
pub fn drop_borrow(&self) {
unsafe { std::ptr::write(self.inner.get(), *self.inner.get() - 1) }
}
pub fn borrow_mut(&self) {
unsafe { std::ptr::write(self.inner.get(), -1) }
}
pub fn drop_borrow_mut(&self) {
unsafe { std::ptr::write(self.inner.get(), 0) }
}
}
pub struct Ref<'a, T> {
val: &'a mut Inner<T>,
}
impl<'a, T> Drop for Ref<'a, T> {
#[inline]
fn drop(&mut self) {
self.val.flag -= 1;
}
}
impl<'a, T> std::ops::Deref for Ref<'a, T> {
type Target = T;
#[inline]
fn deref(&self) -> &Self::Target {
&self.val.val
}
}
impl<'a, T> AsRef<T> for Ref<'a, T> {
fn as_ref(&self) -> &T {
std::ops::Deref::deref(self)
}
}
pub struct RefMut<'a, T> {
val: &'a mut Inner<T>,
}
impl<'a, T> RefMut<'a, T> {
pub fn replace(&mut self, val: T) -> T {
std::mem::replace(&mut self.val.val, val)
}
}
impl<'a, T> std::ops::Deref for RefMut<'a, T> {
type Target = T;
#[inline]
fn deref(&self) -> &Self::Target {
&self.val.val
}
}
impl<'a, T> AsRef<T> for RefMut<'a, T> {
fn as_ref(&self) -> &T {
std::ops::Deref::deref(self)
}
}
impl<'a, T> std::ops::DerefMut for RefMut<'a, T> {
#[inline]
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.val.val
}
}
impl<'a, T> AsMut<T> for RefMut<'a, T> {
fn as_mut(&mut self) -> &mut T {
std::ops::DerefMut::deref_mut(self)
}
}
impl<'a, T> Drop for RefMut<'a, T> {
#[inline]
fn drop(&mut self) {
self.val.flag = 0;
}
}
pub struct RefCell<T> {
inner: std::cell::UnsafeCell<Inner<T>>,
}
impl<T> RefCell<T> {
pub fn new(val: T) -> Self {
Self {
inner: std::cell::UnsafeCell::new(Inner::new(val)),
}
}
pub fn borrow<'a>(&'a self) -> Ref<'a, T> {
self.try_borrow()
.expect("T cannot be borrowed immutably while T is borrowed mutably")
}
pub fn try_borrow<'a>(&'a self) -> Option<Ref<'a, T>> {
unsafe {
if (*self.inner.get()).flag == 0 {
(&mut *self.inner.get()).flag += 1;
Some(Ref {
val: &mut *self.inner.get(),
})
} else {
None
}
}
}
pub fn borrow_mut<'a>(&'a self) -> RefMut<'a, T> {
self.try_borrow_mut()
.expect("T cannot be borrowed mutably while T is borrowed mutably or immutably")
}
pub fn try_borrow_mut<'a>(&'a self) -> Option<RefMut<'a, T>> {
unsafe {
if (*self.inner.get()).flag == 0 {
(&mut *self.inner.get()).flag = -1;
Some(RefMut {
val: &mut *self.inner.get(),
})
} else {
None
}
}
}
pub fn take(mut self) -> T {
if self.inner.get_mut().flag == 0 {
let Inner { val, flag: _ } = self.inner.into_inner();
val
} else {
panic!("T cannot be moved while T is borrowed mutably or immutably")
}
}
pub fn replace(&self, val: T) -> T {
self.borrow_mut().replace(val)
}
}
impl<T: Clone> Clone for RefCell<T> {
fn clone(&self) -> Self {
unsafe { RefCell::new((*self.inner.get()).val.clone()) }
}
}
struct Inner<T> {
val: T,
flag: isize,
}
impl<T> Inner<T> {
fn new(val: T) -> Self {
Self { val, flag: 0 }
}
}
unsafe impl<T: Send> Send for RefCell<T> {}
pub struct RcCell<T> {
inner: std::rc::Rc<std::cell::RefCell<T>>,
}
impl<T> RcCell<T> {
pub fn new(value: T) -> RcCell<T> {
Self {
inner: std::rc::Rc::new(std::cell::RefCell::new(value)),
}
}
}
impl<T> Clone for RcCell<T> {
fn clone(&self) -> Self {
Self {
inner: self.inner.clone(),
}
}
}
impl<T> std::ops::Deref for RcCell<T> {
type Target = std::cell::RefCell<T>;
fn deref(&self) -> &Self::Target {
std::ops::Deref::deref(&self.inner)
}
}
pub struct SharedCell<T> {
value: std::cell::UnsafeCell<T>,
}
impl<T> SharedCell<T> {
pub fn new(value: T) -> SharedCell<T> {
Self {
value: std::cell::UnsafeCell::new(value),
}
}
pub unsafe fn get_mut(&self) -> &mut T {
&mut *self.value.get()
}
#[inline(always)]
pub unsafe fn get_ref(&self) -> &T {
&*self.value.get()
}
}
impl<T> !Sync for SharedCell<T> {}
unsafe impl<T: Send> Send for SharedCell<T> {}
#[cfg(test)]
mod tests {
use serde::{Deserialize, Serialize};
use crate::Borrow;
#[derive(Debug, Serialize, Deserialize, PartialEq)]
struct Data {
item: String,
value: f64,
}
impl Data {
fn new(item: &str, value: f64) -> Data {
Data {
item: item.to_string(),
value,
}
}
}
#[test]
fn test_1() {
let value = Data::new("Rust Weeklies", 98.1);
let data = Borrow::new(value);
println!("Old value: {:?}", data);
let val = serde_json::to_string(&data).unwrap();
println!("Serialized string = {}", val);
let obj = serde_json::from_str::<Borrow<Data>>(&val).unwrap();
println!("New value: {:?}", obj);
assert_eq!(data, obj)
}
#[test]
fn test_2() {
let vec = Borrow::new(vec![1, 2, 3]);
let clone = vec.clone();
let mut shared_ref_1 = vec.clone();
let mut shared_ref_2 = clone.clone();
assert_eq!(*shared_ref_1, vec![1, 2, 3]);
assert_eq!(*shared_ref_2, vec![1, 2, 3]);
shared_ref_1.push(4);
assert_eq!(*shared_ref_2, vec![1, 2, 3, 4]);
shared_ref_2.push(5);
assert_eq!(*shared_ref_1, vec![1, 2, 3, 4, 5]);
}
#[test]
fn test_3() {
#[derive(Debug, PartialEq, Eq)]
struct Data(String, usize, bool, Vec<Self>);
let data = Data(String::from("Hello, World"), 100, false, vec![]);
let mut data_ref = Borrow::new(data);
let mut clone = Borrow::clone(&data_ref);
data_ref.0.push('!');
clone.1 += 55;
data_ref.2 = true;
clone.3.push(Data("".into(), 0, false, Vec::new()));
println!("{:?}", clone);
println!("{:?}", data_ref);
assert_eq!(
*data_ref,
Data(
String::from("Hello, World!"),
155,
true,
vec![Data("".into(), 0, false, vec![])]
)
);
assert_eq!(
*clone,
Data(
String::from("Hello, World!"),
155,
true,
vec![Data("".into(), 0, false, vec![])]
)
);
do_something(&data_ref);
fn do_something(_data: &Data) {
}
}
}