diff options
author | Aria <me@aria.rip> | 2023-10-02 14:03:06 +0100 |
---|---|---|
committer | Aria <me@aria.rip> | 2023-10-02 14:03:06 +0100 |
commit | 186087b2010f7f2b9631a28b80527d99b751b882 (patch) | |
tree | 79e02c254cbeb5e0d981dccb51cd77cf4959d71a /unique_ids/src | |
parent | e189bb3ec7a355e314895a77d3ed25c393cf042b (diff) |
unique ids challenge
Diffstat (limited to 'unique_ids/src')
-rw-r--r-- | unique_ids/src/main.rs | 83 |
1 files changed, 83 insertions, 0 deletions
diff --git a/unique_ids/src/main.rs b/unique_ids/src/main.rs new file mode 100644 index 0000000..3787033 --- /dev/null +++ b/unique_ids/src/main.rs @@ -0,0 +1,83 @@ +use std::{ + io, + time::{SystemTime, UNIX_EPOCH}, +}; + +use common::{run_with, Handler}; +use rand::{rngs::StdRng, Rng, SeedableRng}; +use serde::{Deserialize, Serialize}; + +fn main() { + run_with::<UniqueIdsHandler>(io::stdin(), io::stdout()) +} + +#[derive(Debug, Serialize, Deserialize)] +#[serde(tag = "type")] +enum UniqueIdsBody { + #[serde(rename = "generate")] + Generate { msg_id: usize }, + + #[serde(rename = "generate_ok")] + GenerateOk { + msg_id: usize, + in_reply_to: usize, + id: u128, + }, +} + +type RngMethod = StdRng; + +struct UniqueIdsHandler { + rng: RngMethod, + next_msg_id: usize, +} + +impl Handler for UniqueIdsHandler { + type Body = UniqueIdsBody; + + fn init(_node_id: String, _node_ids: Vec<String>, _msg_id: usize) -> Self { + Self { + rng: RngMethod::from_entropy(), // TODO: This could be seeded from the node ID + next_msg_id: 1, + } + } + + fn handle( + &mut self, + header: common::msg::MessageHeader, + body: Self::Body, + writer: &mut common::MsgWriter<impl std::io::Write>, + ) -> () { + match body { + UniqueIdsBody::Generate { msg_id } => { + let id = self.gen_id(); + writer.write( + header.src, + &UniqueIdsBody::GenerateOk { + msg_id: self.next_msg_id, + in_reply_to: msg_id, + id, + }, + ); + + self.next_msg_id += 1; + } + UniqueIdsBody::GenerateOk { .. } => (), + }; + } +} + +impl UniqueIdsHandler { + fn gen_id(&mut self) -> u128 { + // Time since UNIX epoch in milliseconds + let now = SystemTime::now(); + let time_millis: u128 = now.duration_since(UNIX_EPOCH).unwrap().as_millis(); + + // 80 bits of randomness + let rand1: u16 = self.rng.gen(); + let rand2: u64 = self.rng.gen(); + let rand: u128 = rand1 as u128 | ((rand2 as u128) << 64); + + (time_millis << 80) | rand + } +} |