summaryrefslogtreecommitdiff
path: root/echo/src/main.rs
blob: 381099c444c7f9429675c91a8cb8d83f60347e8f (plain)
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
use std::io;

use common::{msg::*, send_msg, Handler};
use serde::{Deserialize, Serialize};
use serde_json::Deserializer;

#[derive(Debug, Serialize, Deserialize)]
#[serde(tag = "type")]
pub enum EchoBody {
    #[serde(rename = "echo")]
    Echo { msg_id: usize, echo: String },

    #[serde(rename = "echo_ok")]
    EchoOk {
        msg_id: usize,
        in_reply_to: usize,
        echo: String,
    },
}
fn main() {
    let mut stdout = io::stdout();
    let deser = Deserializer::from_reader(io::stdin());
    let mut deser = deser.into_iter::<Message<()>>();
    let Some(msg) = deser.next() else {
        panic!("stream ended before init message");
    };
    let Ok(msg) = msg else {
            panic!("{}", msg.unwrap_err());
    };

    let (node_id, node_ids, msg_id) = match msg.body {
        MaelstromBodyOr::MaelstromBody {
            inner:
                MaelstromBody::Init {
                    node_id,
                    node_ids,
                    msg_id,
                },
        } => (node_id, node_ids, msg_id),
        _ => {
            panic!("expected init message to be first message");
        }
    };

    send_msg(
        &mut stdout,
        &Message {
            header: msg.header.flip(),
            body: MaelstromBodyOr::MaelstromBody::<()> {
                inner: MaelstromBody::InitOk {
                    msg_id: 0,
                    in_reply_to: msg_id,
                },
            },
        },
    );

    let mut handler = EchoHandler::init(node_id, node_ids, msg_id);

    drop(deser);

    let deser = Deserializer::from_reader(io::stdin());
    for msg in deser.into_iter::<Message<EchoBody>>() {
        let msg = msg.unwrap();
        match msg.body {
            MaelstromBodyOr::Other { inner } => {
                if let Some(out) = handler.handle(msg.header, inner) {
                    send_msg(&mut stdout, &out);
                }
            }
            _ => todo!(),
        };
    }
}

pub struct EchoHandler {
    next_msg_id: usize,
}

impl Handler for EchoHandler {
    type Body = EchoBody;

    fn init(_node_id: String, _node_ids: Vec<String>, _msg_id: usize) -> Self {
        EchoHandler { next_msg_id: 1 }
    }

    fn handle(&mut self, header: MessageHeader, body: Self::Body) -> Option<Message<EchoBody>> {
        match body {
            EchoBody::Echo { msg_id, echo } => {
                let msg = Message {
                    header: header.flip(),
                    body: MaelstromBodyOr::Other {
                        inner: EchoBody::EchoOk {
                            msg_id: self.next_msg_id,
                            in_reply_to: msg_id,
                            echo,
                        },
                    },
                };

                self.next_msg_id += 1;

                Some(msg)
            }
            EchoBody::EchoOk { .. } => None,
        }
    }
}