11# 🔑 KeyPaths & CasePaths in Rust
22
33Key paths and case paths provide a ** safe, composable way to access and modify nested data** in Rust.
4- Inspired by ** Swift’s KeyPath / CasePath** system, this crate lets you work with ** struct fields** and ** enum variants** as * first-class values* .
4+ Inspired by ** Swift’s KeyPath / CasePath** system, this this feature rich crate lets you work with ** struct fields** and ** enum variants** as * first-class values* .
55
66---
77
88## ✨ Features
99
10- * ✅ ** ReadableKeyPath ** → safely read struct fields.
11- * ✅ ** WritableKeyPath ** → safely read/write struct fields.
12- * ✅ ** EnumKeyPath ( CasePaths) ** → extract and embed enum variants.
13- * ✅ ** Composable ** → chain key paths together(Upcoming).
14- * ✅ ** Iterable ** → iterate or mutate values across collections.
15- * ✅ ** Macros ** → concise ` readable_keypath! ` , ` writable_keypath! ` , ` enum_keypath! ` .
10+ - ✅ ** Readable/Writable keypaths ** for struct fields
11+ - ✅ ** Failable keypaths ** for ` Option<T> ` chains ( ` _fr ` / ` _fw ` )
12+ - ✅ ** Enum CasePaths** (readable and writable prisms)
13+ - ✅ ** Composition ** across structs, options and enum cases
14+ - ✅ ** Iteration helpers ** over collections via keypaths
15+ - ✅ ** Proc-macros ** : ` #[derive(Keypaths)] ` for structs/tuple-structs and enums , ` #[derive(Casepaths)] ` for enums
1616
1717---
1818
1919## 📦 Installation
2020
2121``` toml
2222[dependencies ]
23- key_paths_core = " 0.6"
23+ key-paths-core = " 0.6"
24+ key-paths-derive = " 0.1"
2425```
2526
2627---
2728
28- ## 🚀 Examples - Go to latest examples directory docs will be updated later
29+ ## 🚀 Examples
2930
30- ### 1. CasePaths with Enums
31+ See ` examples/ ` for many runnable samples. Below are a few highlights.
32+
33+ ### 1) Structs with #[ derive(Keypaths)]
34+
35+ ``` rust
36+ use key_paths_core :: KeyPaths ;
37+ use key_paths_derive :: Keypaths ;
38+
39+ #[derive(Debug , Keypaths )]
40+ struct Size { width : u32 , height : u32 }
41+
42+ #[derive(Debug , Keypaths )]
43+ struct Rectangle { size : Size , name : String }
44+
45+ fn main () {
46+ let mut rect = Rectangle { size : Size { width : 30 , height : 50 }, name : " MyRect" . into () };
47+
48+ // Readable/writable
49+ println! (" width = {:?}" , Size :: width_r (). get (& rect . size));
50+ if let Some (w ) = Size :: width_w (). get_mut (& mut rect . size) { * w += 10 ; }
51+
52+ // Compose: Rectangle -> Size -> width
53+ let rect_width = Rectangle :: size_r (). compose (Size :: width_r ());
54+ println! (" rect.width = {:?}" , rect_width . get (& rect ));
55+ }
56+ ```
57+
58+ ### 2) Optional chaining (failable keypaths)
59+
60+ ``` rust
61+ use key_paths_core :: KeyPaths ;
62+ use key_paths_derive :: Keypaths ;
63+
64+ #[derive(Debug , Keypaths )]
65+ struct Engine { horsepower : u32 }
66+ #[derive(Debug , Keypaths )]
67+ struct Car { engine : Option <Engine > }
68+ #[derive(Debug , Keypaths )]
69+ struct Garage { car : Option <Car > }
70+
71+ fn main () {
72+ let mut g = Garage { car : Some (Car { engine : Some (Engine { horsepower : 120 }) }) };
73+
74+ // Read horsepower if present
75+ let hp = Garage :: car_fr ()
76+ . compose (Car :: engine_fr ())
77+ . compose (Engine :: horsepower_r ());
78+ println! (" hp = {:?}" , hp . get (& g ));
79+
80+ // Mutate horsepower if present
81+ if let Some (car ) = Garage :: car_fw (). get_mut (& mut g ) {
82+ if let Some (engine ) = Car :: engine_fw (). get_mut (car ) {
83+ if let Some (hp ) = Engine :: horsepower_w (). get_mut (engine ) { * hp += 30 ; }
84+ }
85+ }
86+ }
87+ ```
88+
89+ ### 3) Enum CasePaths (readable/writable prisms)
3190
3291``` rust
3392use key_paths_core :: KeyPaths ;
@@ -38,7 +97,7 @@ enum Payment {
3897}
3998
4099fn main () {
41- let kp = KeyPaths :: writable_enum (
100+ let kp = KeyPaths :: writable_enum (
42101 | v | Payment :: Cash { amount : v },
43102 | p : & Payment | match p {
44103 Payment :: Cash { amount } => Some (amount ),
@@ -64,74 +123,7 @@ fn main() {
64123
65124---
66125
67- ### 2. Readable KeyPaths - helper macros wip
68-
69- ``` rust
70- use key_paths_core :: KeyPaths ;
71-
72- #[derive(Debug )]
73- struct Size {
74- width : u32 ,
75- height : u32 ,
76- }
77-
78- #[derive(Debug )]
79- struct Rectangle {
80- size : Size ,
81- name : String ,
82- }
83-
84- fn main () {
85- let mut rect = Rectangle {
86- size : Size {
87- width : 30 ,
88- height : 50 ,
89- },
90- name : " MyRect" . into (),
91- };
92-
93- let width_direct = KeyPaths :: readable (| r : & Rectangle | & r . size. width);
94- println! (" Width: {:?}" , width_direct . get (& rect ));
95- }
96- ```
97-
98- ---
99-
100- ### 3. Writable KeyPaths - helper macros wip
101-
102- ``` rust
103- use key_paths_core :: KeyPaths ;
104-
105- #[derive(Debug )]
106- struct Size {
107- width : u32 ,
108- height : u32 ,
109- }
110- #[derive(Debug )]
111- struct Rectangle {
112- size : Size ,
113- name : String ,
114- }
115- fn main () {
116- let mut rect = Rectangle {
117- size : Size {
118- width : 30 ,
119- height : 50 ,
120- },
121- name : " MyRect" . into (),
122- };
123- let width_mut = KeyPaths :: writable (
124- | r : & mut Rectangle | & mut r . size. width,
125- );
126- // Mutable
127- if let Some (hp_mut ) = width_mut . get_mut (& mut rect ) {
128- * hp_mut += 50 ;
129- }
130- println! (" Updated rectangle: {:?}" , rect );
131- }
132- ```
133-
134- ### 4. Composability and failablity
126+ ### 4) Compose enum prisms with struct fields
135127 ``` rust
136128use key_paths_core :: KeyPaths ;
137129
@@ -170,7 +162,7 @@ fn main() {
170162 println! (" {garage:?}" );
171163}
172164```
173- ### 4. Mutablity
165+ ### 5) Iteration via keypaths
174166 ``` rust
175167use key_paths_core :: KeyPaths ;
176168
@@ -264,10 +256,10 @@ ABox { name: "A box", size: Size { width: 10, height: 20 }, color: Other(RGBU8(0
264256
265257## 🛠 Roadmap
266258
267- * [ ] ` compose ` support for combining multiple key paths.
268- * [ ] Derive macros for automatic KeyPath generation (Upcoming).
269- * [ ] Nested struct & enum traversal.
270- * [ ] Optional chaining ( ` User?.profile?.name ` ) with failable.
259+ - [x] Compose across structs, options and enum cases
260+ - [x ] Derive macros for automatic keypath generation
261+ - [x] Optional chaining with failable keypaths
262+ - [ ] Derive macros for complex multi-field enum variants
271263---
272264
273265## 📜 License
0 commit comments