Skip to content

Instantly share code, notes, and snippets.

@pragmatrix
Last active October 29, 2023 12:05
Show Gist options
  • Save pragmatrix/17154296733dc7eaf378dcf8dc23e9cd to your computer and use it in GitHub Desktop.
Save pragmatrix/17154296733dc7eaf378dcf8dc23e9cd to your computer and use it in GitHub Desktop.
A Versioned<T> type.
use std::ops::{Deref, DerefMut, Index};
#[test]
fn test() {
let mut outer: Versioned<_> = Outer {
a: 0.into(),
b: 0.into(),
multiplied: 0,
}
.into();
*outer.a += 1;
outer.recompute();
assert_eq!(outer.multiplied, 111);
}
struct Outer {
a: Versioned<u64>,
b: Versioned<u64>,
multiplied: u64,
}
struct Versioned<V> {
version: u64,
value: V,
}
impl Versioned<Outer> {
fn recompute(&mut self) {
self.context(|outer, ctx| {
// let a = ctx.resolve(&outer.a);
// let b = ctx.resolve(&outer.b);
let a = outer.a[ctx];
let b = outer.b[ctx];
if ctx.changed() {
outer.multiplied = a + b
}
})
}
}
impl<T> From<T> for Versioned<T> {
fn from(value: T) -> Self {
Versioned { version: 0, value }
}
}
impl Versioned<XX> {}
impl<V> Deref for Versioned<V> {
type Target = V;
fn deref(&self) -> &Self::Target {
&self.value
}
}
impl<V> DerefMut for Versioned<V> {
fn deref_mut(&mut self) -> &mut Self::Target {
self.version += 1;
&mut self.value
}
}
struct VersionContext {
version: u64,
changed: bool,
}
impl VersionContext {
pub fn resolve<'a, V>(&mut self, v: &'a Versioned<V>) -> &'a V {
if self.version < v.version {
self.version = v.version;
self.changed = true
}
v.deref()
}
pub fn changed(&self) -> bool {
self.changed
}
}
impl<V> Index<&mut VersionContext> for Versioned<V> {
type Output = V;
fn index(&self, index: &mut VersionContext) -> &Self::Output {
index.resolve(self)
}
}
impl<V> Versioned<V> {
pub fn context(&mut self, f: impl FnOnce(&mut V, &mut VersionContext)) {
let mut context = VersionContext {
version: self.version,
changed: false,
};
f(&mut self.value, &mut context);
// commit if changed.
if context.changed {
self.version = context.version;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment