use crate::lib::*; pub struct MemRes { pub changed: bool, pub val: T, } pub trait MemoizedArgs { fn take(&self) -> A; fn equal(&self, r: &A) -> bool; } pub struct Memoized { last_args: Cell, func: fn(&A) -> T, val: Cell>, } impl Memoized { pub fn zero(func: fn(&A) -> T) -> Self { Self { last_args: Cell(Def()), func, val: Cell(None) } } } impl Memoized { pub fn new(func: fn(&A) -> T, a: impl Into) -> Self { Self { last_args: Cell(a.into()), func, val: Cell(None) } } pub fn apply(&self, a: impl MemoizedArgs) -> MemRes<&T> { let Self { last_args, func, val } = self; let changed = if unsafe { &*val.as_ptr() }.is_none() || *self != a { let a = a.take(); val.set(Some(func(&a))); last_args.set(a); true } else { false }; MemRes { changed, val: unsafe { &*val.as_ptr() }.as_ref().valid() } } pub fn get_mut(&mut self) -> &mut T { let Self { last_args, func, val } = self; if unsafe { &*val.as_ptr() }.is_none() { let v = func(unsafe { &*last_args.as_ptr() }); val.set(Some(v)); } unsafe { &mut *val.as_ptr() }.as_mut().valid() } pub fn get_args(&self) -> &A { unsafe { &*self.last_args.as_ptr() } } pub fn get(&self) -> &T { let Self { last_args, func, val } = self; if unsafe { &*val.as_ptr() }.is_none() { let v = func(unsafe { &*last_args.as_ptr() }); val.set(Some(v)); } unsafe { &*val.as_ptr() }.as_ref().valid() } pub fn take(&self) -> T { self.get(); unsafe { &mut *self.val.as_ptr() }.take().valid() } pub fn reset(&self) { unsafe { &mut *self.val.as_ptr() }.take(); } pub fn finalize_deserialization(self, func: fn(&A) -> T) -> Self { Self { func, ..self } } } impl AsRef for Memoized { fn as_ref(&self) -> &T { self.get() } } impl Borrow for Memoized { fn borrow(&self) -> &T { self.get() } } impl ops::Deref for Memoized { type Target = T; fn deref(&self) -> &T { self.get() } } impl Default for Memoized { fn default() -> Self { let func = |_: &A| ERROR!("Memoized<{},{}>::default() has undefined contents", type_name::(), type_name::()); let (val, last_args) = Def(); Self { last_args, func, val } } } impl Clone for Memoized { fn clone(&self) -> Self { let Self { last_args: a, func, .. } = self; Self { last_args: Cell(unsafe { &*a.as_ptr() }.clone()), func: *func, val: Def(), } } } impl Debug for Memoized { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "{:?}", self.get()) } } impl fmt::Display for Memoized { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "{}", self.get()) } } impl> PartialEq for Memoized { fn eq(&self, r: &R) -> bool { r.equal(self.get_args()) } } impl Eq for Memoized {} impl MemoizedArgs for Memoized { fn take(&self) -> A { self.get_args().clone() } fn equal(&self, r: &A) -> bool { self.get_args() == r } } #[cfg(feature = "adv_fs")] mod serde { use {super::*, crate::ser::*}; impl Serialize for Memoized { fn serialize(&self, s: S) -> Result { unsafe { &*self.last_args.as_ptr() }.serialize(s) } } impl<'de, T, A: PC + Deserialize<'de>> Deserialize<'de> for Memoized { fn deserialize>(d: D) -> Result { let func = |_: &A| { ERROR!( "Deserialization of Memoized<{},{}> requires you to insert appropriate function via .finalize_deserialization()", type_name::(), type_name::() ) }; let last_args = Cell(A::deserialize(d)?); Ok(Self { last_args, func, val: Def() }) } } } impl MemoizedArgs for A { fn take(&self) -> A { self.clone() } fn equal(&self, r: &A) -> bool { self.eq(r) } } impl MemoizedArgs<(A1, A2)> for &(A1, A2) { fn take(&self) -> (A1, A2) { (*self).clone() } fn equal(&self, r: &(A1, A2)) -> bool { self.eq(&r) } } impl MemoizedArgs<(A1, A2)> for (&A1, &A2) { fn take(&self) -> (A1, A2) { let (a, b) = self; ((*a).clone(), (*b).clone()) } fn equal(&self, (r1, r2): &(A1, A2)) -> bool { let (a, b) = self; a.eq(&r1) && b.eq(&r2) } } impl MemoizedArgs<(A1, A2, A3)> for &(A1, A2, A3) { fn take(&self) -> (A1, A2, A3) { (*self).clone() } fn equal(&self, r: &(A1, A2, A3)) -> bool { self.eq(&r) } } impl MemoizedArgs<(A1, A2, A3)> for (&A1, &A2, &A3) { fn take(&self) -> (A1, A2, A3) { let (a, b, c) = self; ((*a).clone(), (*b).clone(), (*c).clone()) } fn equal(&self, (r1, r2, r3): &(A1, A2, A3)) -> bool { let (a, b, c) = self; a.eq(&r1) && b.eq(&r2) && c.eq(&r3) } } impl MemoizedArgs<(A1, A2, A3, A4)> for &(A1, A2, A3, A4) { fn take(&self) -> (A1, A2, A3, A4) { (*self).clone() } fn equal(&self, r: &(A1, A2, A3, A4)) -> bool { self.eq(&r) } } impl MemoizedArgs<(A1, A2, A3, A4)> for (&A1, &A2, &A3, &A4) { fn take(&self) -> (A1, A2, A3, A4) { let (a, b, c, d) = self; ((*a).clone(), (*b).clone(), (*c).clone(), (*d).clone()) } fn equal(&self, (r1, r2, r3, r4): &(A1, A2, A3, A4)) -> bool { let (a, b, c, d) = self; a.eq(&r1) && b.eq(&r2) && c.eq(&r3) && d.eq(&r4) } } trait_alias!(pub PC, PartialEq + Clone);