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
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
use std::{
io::Write,
ops::ControlFlow,
sync::{
atomic::{AtomicI32, Ordering},
Arc,
},
};
use dptree::prelude::*;
#[tokio::main]
async fn main() {
let store = Arc::new(AtomicI32::new(0));
let dispatcher = dptree::entry()
.branch(ping_handler())
.branch(set_value_handler())
.branch(print_value_handler());
repl(dispatcher, store).await
}
async fn repl(dispatcher: Handler<'static, DependencyMap, String>, store: Arc<AtomicI32>) -> ! {
loop {
print!(">> ");
std::io::stdout().flush().unwrap();
let mut cmd = String::new();
std::io::stdin().read_line(&mut cmd).unwrap();
let strs = cmd.trim().split(' ').collect::<Vec<_>>();
let event = Event::parse(strs.as_slice());
let out = match event {
Some(event) => match dispatcher.dispatch(dptree::deps![event, store.clone()]).await {
ControlFlow::Continue(event) => panic!("Unhandled event {:?}", event),
ControlFlow::Break(result) => result,
},
_ => "Unknown command".to_string(),
};
println!("{}", out);
}
}
#[derive(Copy, Clone, Debug)]
enum Event {
Ping,
SetValue(i32),
PrintValue,
}
impl Event {
fn parse(input: &[&str]) -> Option<Self> {
match input {
["ping"] => Some(Event::Ping),
["set_value", value] => Some(Event::SetValue(value.parse().ok()?)),
["print"] => Some(Event::PrintValue),
_ => None,
}
}
}
type CommandHandler = Endpoint<'static, DependencyMap, String>;
fn ping_handler() -> CommandHandler {
dptree::filter_async(|event: Event| async move { matches!(event, Event::Ping) })
.endpoint(|| async { "Pong".to_string() })
}
fn set_value_handler() -> CommandHandler {
dptree::filter_map_async(|event: Event| async move {
match event {
Event::SetValue(value) => Some(value),
_ => None,
}
})
.endpoint(move |value: i32, store: Arc<AtomicI32>| async move {
store.store(value, Ordering::SeqCst);
format!("{} stored", value)
})
}
fn print_value_handler() -> CommandHandler {
dptree::filter_async(|event: Event| async move { matches!(event, Event::PrintValue) }).endpoint(
move |store: Arc<AtomicI32>| async move {
let value = store.load(Ordering::SeqCst);
format!("{}", value)
},
)
}