-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathlib.rs
107 lines (91 loc) · 2.88 KB
/
lib.rs
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
use core::panic;
use std::io::{BufRead, StdoutLock, Write};
use anyhow::Context;
use serde::de::DeserializeOwned;
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Message<Payload> {
pub src: String,
#[serde(rename = "dest")]
pub dst: String,
pub body: Body<Payload>,
}
impl<Payload> Message<Payload> {
pub fn into_reply(self, id: Option<&mut usize>) -> Self {
Self {
src: self.dst,
dst: self.src,
body: Body {
id: id.map(|id| {
let mid = *id;
*id += 1;
mid
}),
in_reply_to: self.body.id,
payload: self.body.payload,
},
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Body<Payload> {
#[serde(rename = "msg_id")]
pub id: Option<usize>,
pub in_reply_to: Option<usize>,
#[serde(flatten)]
pub payload: Payload,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Init {
pub node_id: String,
pub node_ids: Vec<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(tag = "type")]
#[serde(rename_all = "snake_case")]
enum InitPayload {
Init(Init),
InitOk,
}
pub trait Node<S, P> {
fn from_init(state: S, init: Init) -> anyhow::Result<Self>
where
Self: Sized;
fn step(&mut self, input: Message<P>, output: &mut StdoutLock) -> anyhow::Result<()>;
}
pub fn main_loop<S, N, P>(init_state: S) -> anyhow::Result<()>
where
P: DeserializeOwned,
N: Node<S, P>,
{
let stdin = std::io::stdin().lock();
let mut stdin = stdin.lines();
let mut stdout = std::io::stdout().lock();
let init_msg: Message<InitPayload> =
serde_json::from_str(&stdin.next().expect("no input message on stdin")?)
.context("init message could not be deserialized")?;
let InitPayload::Init(init) = init_msg.body.payload else {
panic!("first message should be init")
};
let mut node: N = Node::from_init(init_state, init).context("node initialization failed")?;
let reply = Message {
src: init_msg.dst,
dst: init_msg.src,
body: Body {
id: Some(0),
in_reply_to: init_msg.body.id,
payload: InitPayload::InitOk,
},
};
serde_json::to_writer(&mut stdout, &reply).context("serialize response to echo")?;
stdout.write_all(b"\n").context("write trailing newline")?;
// let inputs = serde_json::Deserializer::from_reader(stdin).into_iter::<Message<P>>();
for line in stdin {
let line = line.context("MaleStrom input could not be read")?;
let line: Message<P> =
serde_json::from_str(&line).context("MaleStrom input could not be deserialized")?;
node.step(line, &mut stdout)
.context("Node step function failed")?;
}
Ok(())
}