#[derive(Copy, Clone)]
pub enum RefState {
Unshared,
Shared(usize),
Exclusive,
}
pub struct RefCell<T> {
value: std::cell::UnsafeCell<T>,
state: crate::pointers::cell::Cell<RefState>,
}
impl<T> RefCell<T> {
pub fn new(value: T) -> Self {
Self {
value: std::cell::UnsafeCell::new(value),
state: crate::pointers::cell::Cell::new(RefState::Unshared),
}
}
pub fn borrow(&self) -> Option<Ref<'_, T>> {
match self.state.get() {
RefState::Exclusive => None,
RefState::Unshared => {
self.state.set(RefState::Shared(1));
Some(Ref { refcell: self })
}
RefState::Shared(n) => {
self.state.set(RefState::Shared(n + 1));
Some(Ref { refcell: self })
}
}
}
pub fn borrow_mut(&self) -> Option<RefMut<'_, T>> {
match self.state.get() {
RefState::Shared(_) | RefState::Exclusive => None,
RefState::Unshared => {
self.state.set(RefState::Exclusive);
Some(RefMut { refcell: self })
}
}
}
pub fn replace_with<F>(&self, f: F) -> Option<T>
where
F: FnOnce(&mut T) -> T,
{
match self.state.get() {
RefState::Unshared => {
let old = unsafe { &mut *self.value.get() };
let new = f(old);
Some(std::mem::replace(unsafe { &mut *self.value.get() }, new))
}
_ => {
None
}
}
}
pub fn replace(&self, value: T) -> Option<T> {
match self.state.get() {
RefState::Unshared => Some(std::mem::replace(unsafe { &mut *self.value.get() }, value)),
_ => {
None
}
}
}
}
pub struct Ref<'refcell, T> {
refcell: &'refcell RefCell<T>,
}
impl<T> Drop for Ref<'_, T> {
fn drop(&mut self) {
match self.refcell.state.get() {
RefState::Exclusive | RefState::Unshared => {
unreachable!("Having Exclusive state with Shared reference, this is impossible")
}
RefState::Shared(1) => self.refcell.state.set(RefState::Unshared),
RefState::Shared(n) => self.refcell.state.set(RefState::Shared(n - 1)),
}
}
}
impl<T> std::ops::Deref for Ref<'_, T> {
type Target = T;
fn deref(&self) -> &Self::Target {
unsafe { &*self.refcell.value.get() }
}
}
pub struct RefMut<'refcell, T> {
refcell: &'refcell RefCell<T>,
}
impl<T> Drop for RefMut<'_, T> {
fn drop(&mut self) {
match self.refcell.state.get() {
RefState::Shared(_) | RefState::Unshared => {
unreachable!("Having Shared state with Exclusive state is impossible")
}
RefState::Exclusive => self.refcell.state.set(RefState::Unshared),
}
}
}
impl<T> std::ops::Deref for RefMut<'_, T> {
type Target = T;
fn deref(&self) -> &Self::Target {
unsafe { &*self.refcell.value.get() }
}
}
impl<T> std::ops::DerefMut for RefMut<'_, T> {
fn deref_mut(&mut self) -> &mut Self::Target {
unsafe { &mut *self.refcell.value.get() }
}
}
#[cfg(test)]
mod tests {
#[test]
fn test_1() {
let refcell = super::RefCell::new(10);
let t = match refcell.borrow() {
Some(r) => *r, None => 1,
};
assert_eq!(t, 10)
}
#[test]
fn test_2() {
#[derive(Copy, Clone)]
struct RefCellTest {
integer: i32,
}
impl RefCellTest {
fn change_value(&mut self, value: i32) {
self.integer = value;
}
fn print_value(&self) {
println!("{}", self.integer);
}
}
let refcell = super::RefCell::new(RefCellTest { integer: 10 });
let mut cell = refcell.borrow_mut();
if let Some(ref mut c) = cell {
c.change_value(30);
c.print_value();
};
let cell = refcell.borrow();
if let Some(c) = cell {
assert_eq!(c.integer, 30)
}
let _new_cell = refcell.borrow();
let new_cell_1 = refcell.borrow_mut();
match new_cell_1 {
Some(_) => {
println!("This is clear error");
}
None => {
println!("Cool!, It is working as expected");
}
}
}
}