diff --git a/Cargo.lock b/Cargo.lock index e5b98b3..189af4f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -69,9 +69,9 @@ dependencies = [ [[package]] name = "async-trait" -version = "0.1.87" +version = "0.1.88" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d556ec1359574147ec0c4fc5eb525f3f23263a592b1a9c07e0a75b427de55c97" +checksum = "e539d3fca749fcee5236ab05e93a52867dd549cc157c8cb7f99595f3cedffdb5" dependencies = [ "proc-macro2", "quote", @@ -199,12 +199,6 @@ dependencies = [ "generic-array", ] -[[package]] -name = "byteorder" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" - [[package]] name = "bytes" version = "1.10.1" @@ -219,9 +213,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "clap" -version = "4.5.31" +version = "4.5.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "027bb0d98429ae334a8698531da7077bdf906419543a35a55c2cb1b66437d767" +checksum = "e958897981290da2a852763fe9cdb89cd36977a5d729023127095fa94d95e2ff" dependencies = [ "clap_builder", "clap_derive", @@ -229,9 +223,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.31" +version = "4.5.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5589e0cba072e0f3d23791efac0fd8627b49c829c196a492e88168e6a669d863" +checksum = "83b0f35019843db2160b5bb19ae09b4e6411ac33fc6a712003c33e03090e2489" dependencies = [ "anstream", "anstyle", @@ -241,9 +235,9 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.5.28" +version = "4.5.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf4ced95c6f4a675af3da73304b9ac4ed991640c36374e4b46795c49e17cf1ed" +checksum = "09176aae279615badda0765c0c0b3f6ed53f4709118af73cf4655d85d1530cd7" dependencies = [ "heck", "proc-macro2", @@ -300,9 +294,9 @@ dependencies = [ [[package]] name = "deranged" -version = "0.3.11" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" +checksum = "28cfac68e08048ae1883171632c2aef3ebc555621ae56fbccce1cbf22dd7f058" dependencies = [ "powerfmt", ] @@ -404,14 +398,14 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.3.1" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43a49c392881ce6d5c3b8cb70f98717b7c07aabbdff06687b9030dbfbe2725f8" +checksum = "73fea8450eea4bac3940448fb7ae50d91f034f941199fcd9d909a5a07aa455f0" dependencies = [ "cfg-if", "libc", - "wasi 0.13.3+wasi-0.2.2", - "windows-targets", + "r-efi", + "wasi 0.14.2+wasi-0.2.4", ] [[package]] @@ -437,9 +431,9 @@ dependencies = [ [[package]] name = "http" -version = "1.2.0" +version = "1.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f16ca2af56261c99fba8bac40a10251ce8188205a4c448fbb745a2e4daa76fea" +checksum = "f4a85d31aea989eead29a3aaf9e1115a180df8282431156e533de47660892565" dependencies = [ "bytes", "fnv", @@ -458,12 +452,12 @@ dependencies = [ [[package]] name = "http-body-util" -version = "0.1.2" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "793429d76616a256bcb62c2a2ec2bed781c8307e797e2598c50010f2bee2544f" +checksum = "b021d93e26becf5dc7e1b75b1bed1fd93124b374ceb73f43d4d4eafec896a64a" dependencies = [ "bytes", - "futures-util", + "futures-core", "http", "http-body", "pin-project-lite", @@ -530,9 +524,9 @@ checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" [[package]] name = "libc" -version = "0.2.170" +version = "0.2.171" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "875b3680cb2f8f71bdcf9a30f38d48282f5d3c95cbf9b3fa57269bb5d5c06828" +checksum = "c19937216e9d3aa9956d9bb8dfc0b0c8beb6058fc4f7a4dc4d850edf86a237d6" [[package]] name = "lock_api" @@ -546,9 +540,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.26" +version = "0.4.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30bde2b3dc3671ae49d8e2e9f044c7c005836e7a023ee57cffa25ab82764bb9e" +checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94" [[package]] name = "matchit" @@ -635,9 +629,9 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.20.3" +version = "1.21.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "945462a4b81e43c4e3ba96bd7b49d834c6f61198356aa858733bc4acf3cbe62e" +checksum = "d75b0bedcc4fe52caa0e03d9f1151a323e4aa5e2d78ba3580400cd3c9e2bc4bc" [[package]] name = "parking_lot" @@ -688,9 +682,9 @@ checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" [[package]] name = "ppv-lite86" -version = "0.2.20" +version = "0.2.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" +checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" dependencies = [ "zerocopy", ] @@ -706,13 +700,19 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.39" +version = "1.0.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1f1914ce909e1658d9907913b4b91947430c7d9be598b15a1912935b8c04801" +checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" dependencies = [ "proc-macro2", ] +[[package]] +name = "r-efi" +version = "5.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74765f6d916ee2faa39bc8e68e4f3ed8949b48cccdac59983d287a7cb71ce9c5" + [[package]] name = "rand" version = "0.8.5" @@ -778,18 +778,18 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] name = "serde" -version = "1.0.218" +version = "1.0.219" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8dfc9d19bdbf6d17e22319da49161d5d0108e4188e8b680aef6299eed22df60" +checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.218" +version = "1.0.219" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f09503e191f4e797cb8aac08e9a4a4695c5edf6a2e70e376d961ddd5c969f82b" +checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" dependencies = [ "proc-macro2", "quote", @@ -886,9 +886,9 @@ checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" [[package]] name = "syn" -version = "2.0.99" +version = "2.0.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e02e925281e18ffd9d640e234264753c43edc62d64b2d4cf898f1bc5e75f3fc2" +checksum = "b09a44accad81e1ba1cd74a32461ba89dee89095ba17b32f5d03683b1b1fc2a0" dependencies = [ "proc-macro2", "quote", @@ -903,9 +903,9 @@ checksum = "0bf256ce5efdfa370213c1dabab5935a12e49f2c58d15e9eac2870d3b4f27263" [[package]] name = "time" -version = "0.3.38" +version = "0.3.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb041120f25f8fbe8fd2dbe4671c7c2ed74d83be2e7a77529bf7e0790ae3f472" +checksum = "8a7619e19bc266e0f9c5e6686659d394bc57973859340060a69221e57dbc0c40" dependencies = [ "deranged", "itoa", @@ -918,15 +918,15 @@ dependencies = [ [[package]] name = "time-core" -version = "0.1.3" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "765c97a5b985b7c11d7bc27fa927dc4fe6af3a6dfb021d28deb60d3bf51e76ef" +checksum = "c9e9a38711f559d9e3ce1cdb06dd7c5b8ea546bc90052da6d06bb76da74bb07c" [[package]] name = "time-macros" -version = "0.2.20" +version = "0.2.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8093bc3e81c3bc5f7879de09619d06c9a5a5e45ca44dfeeb7225bae38005c5c" +checksum = "3526739392ec93fd8b359c8e98514cb3e8e021beb4e5f597b00a0221f8ed8a49" dependencies = [ "num-conv", "time-core", @@ -934,9 +934,9 @@ dependencies = [ [[package]] name = "tokio" -version = "1.43.0" +version = "1.44.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d61fa4ffa3de412bfea335c6ecff681de2b609ba3c77ef3e00e521813a9ed9e" +checksum = "f382da615b842244d4b8738c82ed1275e6c5dd90c459a30941cd07080b06c91a" dependencies = [ "backtrace", "bytes", @@ -1029,11 +1029,11 @@ checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" [[package]] name = "uuid" -version = "1.15.1" +version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0f540e3240398cce6128b64ba83fdbdd86129c16a3aa1a3a252efd66eb3d587" +checksum = "458f7a779bf54acc9f347480ac654f68407d3aab21269a6e3c9f922acd9e2da9" dependencies = [ - "getrandom 0.3.1", + "getrandom 0.3.2", ] [[package]] @@ -1050,9 +1050,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasi" -version = "0.13.3+wasi-0.2.2" +version = "0.14.2+wasi-0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26816d2e1a4a36a2940b96c5296ce403917633dff8f3440e9b236ed6f6bacad2" +checksum = "9683f9a5a998d873c0d21fcbe3c083009670149a8fab228644b8bd36b2c48cb3" dependencies = [ "wit-bindgen-rt", ] @@ -1141,28 +1141,27 @@ checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] name = "wit-bindgen-rt" -version = "0.33.0" +version = "0.39.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3268f3d866458b787f390cf61f4bbb563b922d091359f9608842999eaee3943c" +checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1" dependencies = [ "bitflags", ] [[package]] name = "zerocopy" -version = "0.7.35" +version = "0.8.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" +checksum = "2586fea28e186957ef732a5f8b3be2da217d65c5969d4b1e17f973ebbe876879" dependencies = [ - "byteorder", "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.7.35" +version = "0.8.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" +checksum = "a996a8f63c5c4448cd959ac1bab0aaa3306ccfd060472f85943ee0750f0169be" dependencies = [ "proc-macro2", "quote", diff --git a/src/field.rs b/src/field.rs index c453886..8d52360 100644 --- a/src/field.rs +++ b/src/field.rs @@ -1,10 +1,24 @@ -use std::fmt; +use crate::queue::Message; +use std::{ + fmt, + sync::mpsc::Sender, +}; use uuid::Uuid; #[derive(Clone, Debug)] pub enum Field { Static(String), Uuid(Uuid), + Tx(Sender), +} + +impl Field { + pub fn to_sender(&self) -> Result, String> { + match self { + Field::Tx(sender) => Ok(sender.clone()), + _ => Err("not a sender field".to_string()), + } + } } impl From for Field { @@ -33,17 +47,25 @@ impl From for Field { } } +impl From> for Field { + fn from(value: Sender) -> Self { + Field::Tx(value) + } +} + impl fmt::Display for Field { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { Field::Uuid(data) => write!(f, "{}", data), Field::Static(data) => write!(f, "{}", data), + Field::Tx(_) => write!(f, "{}", "message sender"), } } } #[cfg(test)] mod fields { + use std::sync::mpsc::channel; use super::*; #[test] @@ -98,6 +120,19 @@ mod fields { } } + #[test] + fn sender_to_field() { + let (tx, rx) = channel::(); + match tx.into() { + Field::Tx(sender) => { + let msg = Message::new(); + sender.send(msg).unwrap(); + rx.recv().unwrap(); + }, + _ => unreachable!("should have been a sender"), + } + } + #[test] fn uuid_field_to_string() { let id = Uuid::new_v4(); @@ -119,4 +154,13 @@ mod fields { let input: Field = result.clone().into(); assert_eq!(input.to_string(), result); } + + #[test] + fn get_sender() { + let (tx, rx) = channel::(); + let field: Field = tx.into(); + let sender = field.to_sender().unwrap(); + sender.send(Message::new()).unwrap(); + rx.recv().unwrap(); + } } diff --git a/src/lib.rs b/src/lib.rs index 4bf63a9..8fc8d87 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,5 +1,6 @@ mod client; mod field; +mod queue; use client::{Client, Reply, Request}; use field::Field; diff --git a/src/queue.rs b/src/queue.rs new file mode 100644 index 0000000..b5ec052 --- /dev/null +++ b/src/queue.rs @@ -0,0 +1,180 @@ +use crate::field::Field; +use std::{ + collections::HashMap, + sync::mpsc::{channel, Receiver, Sender}, + thread::spawn, +}; + +use uuid::Uuid; + +enum MsgType { + ClientNewMessage, + NoOp, + Register, +} + +pub struct Message { + id: Uuid, + class: MsgType, + data: HashMap, +} + +impl Message { + pub fn new() -> Self { + Self { + id: Uuid::nil(), + class: MsgType::NoOp, + data: HashMap::new(), + } + } + + fn reply(&self, data: MsgType) -> Message { + Self { + id: self.id.clone(), + class: data, + data: self.data.clone(), + } + } + + fn get_class(&self) -> &MsgType { + &self.class + } + + fn add_data(&mut self, name: S, data: F) where S: Into, F: Into { + self.data.insert(name.into(), data.into()); + } + + fn get_data(&self) -> &HashMap { + &self.data + } +} + +#[cfg(test)] +mod messages { + use super::*; + + #[test] + fn new_message() { + let msg = Message::new(); + assert_eq!(msg.id, Uuid::nil()); + match msg.class { + MsgType::NoOp => (), + _ => unreachable!("new defaults to noop"), + } + assert!(msg.data.is_empty()); + } + + #[test] + fn create_reply() { + let id = Uuid::new_v4(); + let mut msg = Message::new(); + msg.id = id.clone(); + let data = MsgType::Register; + let result = msg.reply(data); + assert_eq!(result.id, id); + match result.class { + MsgType::Register => {}, + _ => unreachable!("should have been a registration request"), + } + } + + #[test] + fn get_message_type() { + let msg = Message::new(); + match msg.get_class() { + MsgType::NoOp => {}, + _ => unreachable!("should have bneen noopn"), + } + } + + #[test] + fn add_data() { + let mut msg = Message::new(); + let one = "one"; + let two = "two".to_string(); + msg.add_data(one, one); + msg.add_data(two.clone(), two.clone()); + let result = msg.get_data(); + assert_eq!(result.get(one).unwrap().to_string(), one); + assert_eq!(result.get(&two).unwrap().to_string(), two); + } +} + +struct Queue { + senders: Vec>, + rx: Receiver, +} + +impl Queue { + fn new(rx: Receiver) -> Self { + Self { + senders: Vec::new(), + rx: rx, + } + } + + fn start() -> Sender { + let (tx, rx) = channel(); + spawn(move || { + let mut queue = Queue::new(rx); + queue.listen(); + }); + tx + } + + fn listen(&mut self) { + loop { + let msg = self.rx.recv().unwrap(); + match msg.get_class() { + MsgType::Register => self.register(msg.get_data()).unwrap(), + _ => { + for sender in self.senders.iter() { + sender.send(Message::new()).unwrap(); + } + }, + } + } + } + + fn register(&mut self, data: &HashMap) -> Result<(), String> { + match data.get("tx") { + Some(data) => { + self.senders.push(data.to_sender().unwrap()); + Ok(()) + }, + None => Err("missing tx sender".to_string()), + } + } +} + +#[cfg(test)] +mod queues { + use std::time::Duration; + use super::*; + + fn start_queue() -> (Sender, Receiver) { + let (tx, rx) = channel::(); + let initial = Message::new(); + let mut msg = initial.reply(MsgType::Register); + msg.add_data("tx", tx); + let queue_tx = Queue::start(); + (queue_tx, rx) + } + + #[test] + fn run_queue() { + let queue_tx = Queue::start(); + let (tx, rx) = channel(); + let msg = Message::new(); + let mut reply = msg.reply(MsgType::Register); + reply.add_data("tx", tx); + queue_tx.send(reply); + queue_tx.send(msg.reply(MsgType::NoOp)); + rx.recv_timeout(Duration::from_millis(400)).unwrap(); + } + + #[test] + fn get_new_client_message() { + let (tx, rx) = start_queue(); + } +}