use std::{cell::{BorrowError, BorrowMutError, Ref, RefCell, RefMut}, fmt::{self, Formatter}, marker::PhantomData, rc::Rc};
use std::fmt::Debug;
use crate::Id;
pub(super) fn cast_plain<'a, T>(id: Id<Floating<'a, T>>) -> Id<T> {
Id(id.0, PhantomData)
}
pub(super) fn cast_refcell<'a, T>(id: Id<T>) -> Id<Floating<'a, T>> {
Id(id.0, PhantomData)
}
pub struct Floating<'a, T>(Rc<RefCell<T>>, PhantomData<&'a ()>);
impl<'a, T> Floating<'a, T> {
pub(crate) fn new(value: T) -> Floating<'static, T> {
Floating(Rc::new(RefCell::new(value)), PhantomData)
}
pub fn replace(&self, value: T) -> T {
self.0.replace(value)
}
pub fn replace_with<F>(&self, value: F) -> T where F: FnOnce(&mut T) -> T {
self.0.replace_with(value)
}
pub fn swap(&self, other: &Floating<T>) {
self.0.swap(&other.0)
}
pub fn borrow(&self) -> Ref<'_, T> {
self.0.borrow()
}
pub fn try_borrow(&self) -> Result<Ref<'_, T>, BorrowError> {
self.0.try_borrow()
}
pub fn borrow_mut(&self) -> RefMut<'_, T> {
self.0.borrow_mut()
}
pub fn try_borrow_mut(&self) -> Result<RefMut<'_, T>, BorrowMutError> {
self.0.try_borrow_mut()
}
pub(crate) fn internal_share(&self) -> Floating<'a, T> {
let it: Rc<RefCell<T>> = self.0.clone();
return Self(it, PhantomData)
}
}
impl<T: Clone> Clone for Floating<'static, T> {
fn clone(&self) -> Self {
let ref_cell: &RefCell<T> = self.0.as_ref();
Self(Rc::new(ref_cell.clone()), PhantomData)
}
}
impl<'a, T: Debug> Debug for Floating<'a, T> {
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> {
match self.try_borrow() {
Ok(borrow) => f.debug_struct("Floating").field("value", &borrow).finish(),
Err(_) => {
struct BorrowedPlaceholder;
impl Debug for BorrowedPlaceholder {
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> {
f.write_str("<borrowed>")
}
}
f.debug_struct("RefCell").field("value", &BorrowedPlaceholder).finish()
}
}
}
}
impl<'a, T: Eq> Eq for Floating<'a, T> {
}
impl<'a, T: Ord> Ord for Floating<'a, T> {
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
let x1: &RefCell<T> = &*self.0;
let x2: &RefCell<T> = &*other.0;
x1.cmp(x2)
}
}
impl<'a, T: PartialEq> PartialEq<Floating<'a, T>> for Floating<'a, T> {
fn eq(&self, other: &Floating<T>) -> bool {
let x1: &RefCell<T> = &*self.0;
let x2: &RefCell<T> = &*other.0;
x1 == x2
}
}
impl<'a, T: PartialOrd> PartialOrd<Floating<'a, T>> for Floating<'a, T> {
fn partial_cmp(&self, other: &Floating<T>) -> Option<std::cmp::Ordering> {
let x1: &RefCell<T> = &*self.0;
let x2: &RefCell<T> = &*other.0;
x1.partial_cmp(x2)
}
}