https://github.com/cksac/compose-rt
A positional memoization runtime
https://github.com/cksac/compose-rt
Last synced: about 2 months ago
JSON representation
A positional memoization runtime
- Host: GitHub
- URL: https://github.com/cksac/compose-rt
- Owner: cksac
- License: apache-2.0
- Created: 2022-03-11T05:32:02.000Z (over 3 years ago)
- Default Branch: main
- Last Pushed: 2024-12-24T16:25:07.000Z (6 months ago)
- Last Synced: 2025-04-28T05:20:49.169Z (2 months ago)
- Language: Rust
- Homepage:
- Size: 251 KB
- Stars: 37
- Watchers: 4
- Forks: 2
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE-APACHE
Awesome Lists containing this project
README
# compose-rt

[](https://docs.rs/compose-rt)
[](https://crates.io/crates/compose-rt)A positional memoization runtime similar to Jetpack Compose Runtime.
>What this means is that Compose is, at its core, a general-purpose tool for managing a tree of nodes of any type. Well a “tree of nodes” describes just about anything, and as a result Compose can target just about anything. – [jakewharton](https://jakewharton.com/a-jetpack-compose-by-any-other-name/)
## Example
```rust
use std::env;use compose_rt::{ComposeNode, Composer, Root};
#[derive(Debug)]
pub struct Data(String);impl From for Data {
fn from(s: String) -> Self {
Self(s)
}
}impl From<&str> for Data {
fn from(s: &str) -> Self {
Self(s.to_string())
}
}impl ComposeNode for Data {
type Context = ();
}type Scope = compose_rt::Scope;
pub struct Div;
pub struct Button;
pub struct Text;pub trait Html {
fn div(&self, content: C)
where
C: Fn(Scope) + Clone + 'static;fn button(&self, text: T)
where
T: Into + Clone + 'static;fn text(&self, text: T)
where
T: Into + Clone + 'static;
}impl Html for Scope
where
S: 'static,
{
#[track_caller]
fn div(&self, content: C)
where
C: Fn(Scope) + Clone + 'static,
{
let child_scope = self.child::();
self.create_node(
child_scope,
content,
|| {},
|_, _| "div".into(),
|_, _, _| {},
);
}#[track_caller]
fn button(&self, text: T)
where
T: Into + Clone + 'static,
{
let child_scope = self.child::();
self.create_node(
child_scope,
|_| {},
move || text.clone().into(),
|text, _| format!("button({})", text).into(),
|n, text, _| {
n.0 = text;
},
);
}#[track_caller]
fn text(&self, text: T)
where
T: Into + Clone + 'static,
{
let child_scope = self.child::();
self.create_node(
child_scope,
|_| {},
move || text.clone().into(),
|text, _| format!("text({})", text).into(),
|n, text, _| {
n.0 = text;
},
);
}
}fn app(s: Scope, n: usize) {
s.div(move |s| {
let count = s.use_state(|| 0);
s.text("start");
s.div(move |s| {
let c = count.get();
if c == 0 {
s.button("Load items");
count.set(n);
} else {
for i in 0..c {
s.key(i, move |s| {
s.button(format!("Item {}", i));
});
}
count.set(0);
}
});
s.text("end");
});
}fn main() {
let count = env::args()
.nth(1)
.unwrap_or("2".to_string())
.parse()
.unwrap();
let iter = env::args()
.nth(2)
.unwrap_or("1".to_string())
.parse()
.unwrap();
let print = env::args()
.nth(3)
.unwrap_or("true".to_string())
.parse()
.unwrap();
println!("count: {}, iter: {}, print: {}", count, iter, print);
let start = std::time::Instant::now();
let mut recomposer = Composer::compose(move |s| app(s, count), ());
if print {
recomposer.print_tree();
}
for _ in 0..iter {
recomposer.recompose();
}
if print {
recomposer.print_tree();
}
println!("Time: {:?}", start.elapsed());
}
```## LICENSE
This project is licensed under either of- Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or
http://www.apache.org/licenses/LICENSE-2.0)
- MIT license ([LICENSE-MIT](LICENSE-MIT) or
http://opensource.org/licenses/MIT)at your option.