3 unstable releases
0.2.0 | Jun 25, 2021 |
---|---|
0.1.1 | Jun 18, 2021 |
0.1.0 | Jun 15, 2021 |
#2480 in Rust patterns
Used in keypath-proc-macros
24KB
561 lines
keypath
Strongly typed references to arbitrarily nested fields.
This is an early experiment in implementing Swift-style keypaths in Rust. It is currently intended as a proof of concept, and is missing some fancier features such as 'partial keypaths' and composibility, although implementing these should not be especially challanging. What this does include is what I believe is the most difficult case, of generating typed keypaths for arbitrary types that are guaranteed at compile time.
This means you can do the following:
#[derive(Keyable)]
struct Person {
name: String,
friends: Vec<String>,
size: Size,
}
#[derive(Keyable)]
struct Size {
big: bool,
heft: u8,
}
let mut person = Person {
name: "coco".into(),
friends: vec!["eli".into(), "nico".into(), "yaya".into()],
size: Size { big: false, heft: 45 }
};
let first_friend: KeyPath<Person, String> = keypath!(Person.friends[0]);
let heft = keypath!(Person.size.heft);
assert_eq!(person[&first_friend], "eli");
// mutation:
person[&heft] = 101;
assert_eq!(person.size.heft, 101);
This may not seem especially useful on its own, but it is an ergonomic building block for things like UI bindings, and observable objects.
todos
There are a bunch of additional features and ideas that would be worth exploring, here:
- allow collection access to return optionals, with chaining:
People.friends[10]?.age
would allow the indexing operation to fail. - easier implementation for collections (currently manual, no derive available)
- support for generics in the
keypath!
macro
Dependencies
~1.5MB
~40K SLoC