Created
November 7, 2024 19:03
-
-
Save matthunz/7bd56646ce05f0cd738dd55b4f8b74aa to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use std::{ | |
cell::{RefCell, UnsafeCell}, | |
mem, | |
ops::Deref, | |
}; | |
fn main() { | |
let c = Component::new(app); | |
let mut scope = Scope::new(c); | |
scope.run(); | |
} | |
fn app<'a>(scope: &'a Scope) -> Option<Component<'a>> { | |
let x = scope.use_state(|| String::new()); | |
Some(Component::new(|_: &'a Scope| { | |
dbg!(&*x.read()); | |
x.write(|s| s.push('x')); | |
None | |
})) | |
} | |
pub struct Ref<'a, T> { | |
value: &'a T, | |
} | |
impl<T> Deref for Ref<'_, T> { | |
type Target = T; | |
fn deref(&self) -> &Self::Target { | |
self.value | |
} | |
} | |
pub struct State<T> { | |
value: T, | |
} | |
impl<T> State<T> { | |
pub fn read(&self) -> Ref<T> { | |
Ref { value: &self.value } | |
} | |
pub fn write(&self, f: impl FnOnce(&mut T) + 'static) { | |
todo!() | |
} | |
} | |
pub struct Scope { | |
component: Component<'static>, | |
next: Option<Box<Self>>, | |
states: RefCell<Vec<*mut ()>>, | |
} | |
impl Scope { | |
pub fn new(component: Component<'_>) -> Self { | |
Self { | |
component: unsafe { mem::transmute(component) }, | |
next: None, | |
states: RefCell::new(Vec::new()), | |
} | |
} | |
pub fn run(&mut self) { | |
let r = self as *mut Scope; | |
self.component.run(unsafe { mem::transmute(&mut *r) }); | |
} | |
pub fn use_state<'a, T: 'a>(&'a self, make_value: impl FnOnce() -> T) -> &'a State<T> { | |
let mut states = self.states.borrow_mut(); | |
let boxed = Box::new(State { | |
value: make_value(), | |
}); | |
states.push(Box::into_raw(boxed) as _); | |
let ptr = *states.last().unwrap(); | |
drop(states); | |
unsafe { &mut *(ptr as *mut State<T>) } | |
} | |
} | |
pub struct Component<'a> { | |
f: Box<dyn Fn(&'a mut Scope)>, | |
} | |
impl<'a> Component<'a> { | |
pub fn new(f: impl Fn(&'a Scope) -> Option<Component<'a>> + 'a) -> Self { | |
let f: Box<dyn Fn(&mut Scope)> = Box::new(move |scope| { | |
let scope_ref = unsafe { mem::transmute(&*scope) }; | |
let content = f(scope_ref); | |
if let Some(content) = content { | |
scope.next = Some(Box::new(Scope { | |
component: unsafe { mem::transmute(content) }, | |
next: None, | |
states: RefCell::new(Vec::new()), | |
})); | |
let r = (&mut **scope.next.as_mut().unwrap()) as *mut Scope; | |
scope | |
.next | |
.as_ref() | |
.unwrap() | |
.component | |
.run(unsafe { &mut *r }); | |
} | |
}); | |
Self { | |
f: unsafe { mem::transmute(f) }, | |
} | |
} | |
pub fn run(&self, scope: &'a mut Scope) { | |
(self.f)(scope); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment