summaryrefslogtreecommitdiff
path: root/echo/src/main.rs
diff options
context:
space:
mode:
Diffstat (limited to 'echo/src/main.rs')
-rw-r--r--echo/src/main.rs108
1 files changed, 108 insertions, 0 deletions
diff --git a/echo/src/main.rs b/echo/src/main.rs
new file mode 100644
index 0000000..381099c
--- /dev/null
+++ b/echo/src/main.rs
@@ -0,0 +1,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,
+ }
+ }
+}