use std::{
mem::swap,
rc::{
Rc,
Weak,
},
cell::{
RefCell,
Ref,
},
ops::Deref,
};
use crate::{
core::{
Id,
ValueTrait,
ProcessingContext,
Cleanup,
Link_,
Value,
IntoValue,
},
Link,
};
pub struct PrimMut_<T> {
value: T,
first_change: bool,
next: Vec<Weak<Link_>>,
}
impl<T: 'static> PrimMut_<T> {
pub fn get(&self) -> &T {
return &self.value;
}
}
pub(crate) struct Prim_<T> {
mut_: RefCell<PrimMut_<T>>,
}
impl<T> ValueTrait for Prim_<T> {
fn next_links(&self) -> Vec<crate::Link> {
let mut out = vec![];
let mut self2 = self.mut_.borrow_mut();
out.reserve(self2.next.len());
self2.next.retain_mut(|e| {
match e.upgrade() {
Some(e) => {
out.push(Link(e.clone()));
return true;
},
None => {
return false;
},
}
});
return out;
}
}
impl<T> Cleanup for Prim_<T> {
fn clean(&self) {
self.mut_.borrow_mut().first_change = true;
}
}
#[derive(Clone)]
pub struct Prim<T>(pub(crate) Rc<Prim_<T>>);
#[derive(Clone)]
pub struct WeakPrim<T>(Weak<Prim_<T>>);
impl<T: 'static> Prim<T> {
pub fn new(initial: T) -> Self {
return Prim(Rc::new(Prim_ { mut_: RefCell::new(PrimMut_ {
value: initial,
first_change: true,
next: vec![],
}) }));
}
pub fn add_next(&self, link: &Link) {
self.0.mut_.borrow_mut().next.push(Rc::downgrade(&link.0));
}
pub fn weak(&self) -> WeakPrim<T> {
return WeakPrim(Rc::downgrade(&self.0));
}
pub fn set(&self, pc: &mut ProcessingContext, value: T) {
let first_change;
{
let mut self2 = self.0.mut_.borrow_mut();
first_change = self2.first_change;
self2.first_change = false;
self2.value = value;
}
if first_change {
pc.1.cleanup.push(self.0.clone());
if !pc.1.processing {
for l in self.0.next_links() {
pc.1.step1_stacked_links.push((true, l));
}
}
}
}
pub fn borrow<'a>(&'a self) -> ValueRef<'a, T> {
return ValueRef(self.0.mut_.borrow());
}
}
impl<T: 'static> IntoValue for Prim<T> {
fn into_value(&self) -> Value {
return Value(self.0.clone());
}
}
impl<T: 'static> WeakPrim<T> {
pub fn upgrade(&self) -> Option<Prim<T>> {
return Some(Prim(self.0.upgrade()?));
}
}
pub struct ValueRef<'a, T: 'static>(Ref<'a, PrimMut_<T>>);
impl<'a, T: 'static> Deref for ValueRef<'a, T> {
type Target = T;
fn deref(&self) -> &Self::Target {
return &self.0.value;
}
}
pub struct HistPrimMut_<T: PartialEq + Clone> {
value: T,
previous_value: Option<T>,
next: Vec<Weak<Link_>>,
}
impl<T: PartialEq + Clone + 'static> HistPrimMut_<T> {
pub fn get(&self) -> &T {
return &self.value;
}
}
pub(crate) struct HistPrim_<T: PartialEq + Clone> {
pub(crate) id: Id,
mut_: RefCell<HistPrimMut_<T>>,
}
impl<T: PartialEq + Clone> ValueTrait for HistPrim_<T> {
fn next_links(&self) -> Vec<crate::Link> {
let mut out = vec![];
let mut self2 = self.mut_.borrow_mut();
out.reserve(self2.next.len());
self2.next.retain_mut(|e| {
match e.upgrade() {
Some(e) => {
out.push(Link(e.clone()));
return true;
},
None => {
return false;
},
}
});
return out;
}
}
impl<T: PartialEq + Clone> Cleanup for HistPrim_<T> {
fn clean(&self) {
self.mut_.borrow_mut().previous_value = None;
}
}
#[derive(Clone)]
pub struct HistPrim<T: PartialEq + Clone>(pub(crate) Rc<HistPrim_<T>>);
#[derive(Clone)]
pub struct WeakHistPrim<T: PartialEq + Clone>(Weak<HistPrim_<T>>);
impl<T: PartialEq + Clone + 'static> HistPrim<T> {
pub fn new(pc: &mut ProcessingContext, initial: T) -> Self {
let id = pc.1.take_id();
return HistPrim(Rc::new(HistPrim_ {
id: id,
mut_: RefCell::new(HistPrimMut_ {
value: initial,
previous_value: None,
next: vec![],
}),
}));
}
pub fn add_next(&self, link: &Link) {
self.0.mut_.borrow_mut().next.push(Rc::downgrade(&link.0));
}
pub fn weak(&self) -> WeakHistPrim<T> {
return WeakHistPrim(Rc::downgrade(&self.0));
}
pub fn set(&self, pc: &mut ProcessingContext, mut value: T) {
let first_change;
{
let mut self2 = self.0.mut_.borrow_mut();
if self2.value == value {
return;
}
swap(&mut self2.value, &mut value);
first_change = self2.previous_value.is_none();
self2.previous_value = Some(value);
}
if first_change {
pc.1.cleanup.push(self.0.clone());
if !pc.1.processing {
for l in self.0.next_links() {
pc.1.step1_stacked_links.push((true, l));
}
}
}
}
pub fn borrow<'a>(&'a self) -> HistValueRef<'a, T> {
return HistValueRef(self.0.mut_.borrow());
}
pub fn get(&self) -> T {
return self.0.mut_.borrow().value.clone();
}
pub fn get_old(&self) -> T {
let m = self.0.mut_.borrow();
return m.previous_value.as_ref().unwrap_or_else(|| &m.value).clone();
}
}
impl<T: PartialEq + Clone + 'static> IntoValue for HistPrim<T> {
fn into_value(&self) -> Value {
return Value(self.0.clone());
}
}
impl<T: PartialEq + Clone + 'static> WeakHistPrim<T> {
pub fn upgrade(&self) -> Option<HistPrim<T>> {
return Some(HistPrim(self.0.upgrade()?));
}
}
pub struct HistValueRef<'a, T: PartialEq + Clone + 'static>(Ref<'a, HistPrimMut_<T>>);
impl<'a, T: PartialEq + Clone + 'static> Deref for HistValueRef<'a, T> {
type Target = T;
fn deref(&self) -> &Self::Target {
return &self.0.value;
}
}