aboutsummaryrefslogtreecommitdiff
path: root/docs/pages/11-resource-system.md
blob: b54938a1477783d07a4db98b15cc02d9b1f9bb52 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
<h1 align="center">Using the Resource System</h1>
<p align="center">
    A hands-on guide to resources
</p>

Resources are Mingling's mechanism for managing global state. Any type that implements `Default + Clone` can be a resource.

## Define a Resource

```rust
// Any type implementing Default + Clone can be used as a resource
#[derive(Default, Clone)]
struct ResCurrentDir(String);
 
// Register with the Program
fn main() {
    let mut program = ThisProgram::new();
    program.with_resource(ResCurrentDir(".".into()));
    program.exec_and_exit();
}
```
 
Since `ResCurrentDir` implements both `Default` and `Clone`, the framework automatically implements `ResourceMarker` for it — no manual impl needed.

## Inject & Use

In a Chain or Renderer, simply declare the resource in the parameter list:

```rust
@@@#[derive(Default, Clone)]
@@@struct ResCurrentDir(String);
@@@dispatcher!("pwd", CMDPrintWorkingDir => EntryPrintWorkingDir);
@@@pack!(ResultPath = String);
// Inject read-only resource via &T
#[chain]
fn handle_pwd(_args: EntryPrintWorkingDir, cwd: &ResCurrentDir) -> Next {
    ResultPath::new(cwd.0.clone()).to_render()
}
 
#[renderer]
fn render_path(result: ResultPath) {
    r_println!("{}", *result);
}
```
 
## Modify a Resource

Use `&mut T` to inject a mutable resource:

```rust
@@@#[derive(Default, Clone)]
@@@struct ResVisitCount(u32);
@@@dispatcher!("visit", CMDVisit => EntryVisit);
@@@pack!(ResultDone = ());
#[chain]
fn handle_visit(_args: EntryVisit, counter: &mut ResVisitCount) -> Next {
    counter.0 += 1;
    ResultDone::default()
}
 
#[renderer]
fn render_done(_done: ResultDone, counter: &ResVisitCount) {
    r_println!("visit count is : {}", counter.0);
}
```
 
## Use Multiple Resources

A Chain can inject any number of resources at once — the framework matches them by type automatically:

```rust
@@@#[derive(Default, Clone)] struct ResConfig(String);
@@@#[derive(Default, Clone)] struct ResCounter(u32);
@@@dispatcher!("test", CMDTest => EntryTest);
@@@pack!(ResultDone = ());
// Inject both read-only and mutable resources
#[chain]
fn handle_test(_args: EntryTest, config: &ResConfig, counter: &mut ResCounter) -> Next {
    println!("config: {}", config.0);
    counter.0 += 1;
    ResultDone::default().to_render()
}
```
 
For deeper topics like `ResourceMarker`, lazy loading with `LazyRes`, etc., see [Core Concepts: Resource System](pages/concepts/2-resource).

<p align="center" style="font-size: 0.85em; color: gray;">
    Written by @Weicao-CatilGrass
</p>