derive_deep/
derive_deep.rs

1use pathmod::prelude::*;
2
3// A small, realistic nested model
4#[derive(Accessor, Debug, PartialEq)]
5struct Address {
6    city: String,
7    zip: u32,
8}
9
10#[derive(Accessor, Debug, PartialEq)]
11struct Profile {
12    address: Address,
13    stats: Stats,
14}
15
16#[derive(Accessor, Debug, PartialEq)]
17struct Stats {
18    logins: u32,
19}
20
21#[derive(Accessor, Debug, PartialEq)]
22struct User {
23    profile: Profile,
24    settings: Settings,
25}
26
27#[derive(Accessor, Debug, PartialEq)]
28struct Settings {
29    theme: Theme,
30}
31
32#[derive(Accessor, Debug, PartialEq)]
33struct Theme {
34    name: String,
35}
36
37fn main() {
38    let mut user = User {
39        profile: Profile {
40            address: Address {
41                city: "berlin".into(),
42                zip: 10115,
43            },
44            stats: Stats { logins: 1 },
45        },
46        settings: Settings {
47            theme: Theme {
48                name: "light".into(),
49            },
50        },
51    };
52
53    // Compose a deep accessor: User -> Profile -> Address -> city
54    let acc_city = User::acc_profile()
55        .compose(Profile::acc_address())
56        .compose(Address::acc_city());
57
58    println!("city before: {}", acc_city.get(&user));
59
60    // In-place deep mutation via set_mut
61    acc_city.set_mut(&mut user, |c| c.make_ascii_uppercase());
62    println!("city upper: {}", acc_city.get(&user));
63
64    // Set via cloning only the leaf value
65    let new_city = String::from("Lund");
66    acc_city.set_clone(&mut user, &new_city);
67    println!("city after set_clone: {}", acc_city.get(&user));
68
69    // Compose another deep accessor: User -> Settings -> Theme -> name
70    let acc_theme_name = User::acc_settings()
71        .compose(Settings::acc_theme())
72        .compose(Theme::acc_name());
73
74    acc_theme_name.set(&mut user, "dark".to_string());
75    println!("theme after set: {}", acc_theme_name.get(&user));
76
77    // Show a non-string leaf with arithmetic updates
78    let acc_zip = User::acc_profile()
79        .compose(Profile::acc_address())
80        .compose(Address::acc_zip());
81
82    acc_zip.set_mut(&mut user, |z| *z += 5);
83    println!("zip after +5: {}", acc_zip.get(&user));
84}