bubblegum_cli_rs/
bubblegum_cli.rs1use std::net::UdpSocket;
2use std::time::Duration;
3use crate::data_message::{CharVecCompatible, DataMessage, FromDataMessage, ToDataMessage};
4
5pub struct BubblegumClientConfig<'a> {
6 host: &'a str,
7 port: u32,
8}
9
10impl<'a> BubblegumClientConfig<'a> {
11 pub fn to_address(&self) -> String {
12 format!("{}:{}", self.host, self.port)
13 }
14}
15
16pub struct BubblegumClient<'a> {
17 config: BubblegumClientConfig<'a>,
18 socket: UdpSocket,
19}
20
21impl<'a> BubblegumClient<'a> {
22 const PUBLISH_COMMAND: u8 = 1;
23 const SUBSCRIBE_COMMAND: u8 = 2;
24
25 fn hash(str: &str) -> u64 {
26 let mut h: u64 = 5381;
27
28 for c in str.as_bytes() {
29 h = ((h << 5) + h) + (*c as u64);
30 }
31
32 return h
33 }
34
35 pub fn new() -> BubblegumClient<'a> {
36 let config = BubblegumClientConfig{ host: "127.0.0.1", port: 7878 };
37 let socket = UdpSocket::bind("0.0.0.0:0").unwrap();
38 socket.connect(config.to_address().as_str()).expect("Couldn't connect to server.");
39 socket.set_read_timeout(Some(Duration::from_millis(30))).expect("Couldn't send read timeout.");
40 BubblegumClient{ config, socket }
41 }
42
43 pub fn connect_to(url: &'a str, port: u32) -> BubblegumClient<'a> {
44 let config = BubblegumClientConfig{ host: url, port };
45 let socket = UdpSocket::bind("0.0.0.0:0").unwrap();
46 socket.connect(config.to_address().as_str()).expect("Couldn't connect to server.");
47 socket.set_read_timeout(Some(Duration::from_millis(30))).expect("Couldn't send read timeout.");
48 BubblegumClient{ config, socket }
49 }
50
51 pub fn publish<T>(&self, channel: &'a str, t: T) where T: ToDataMessage {
52 let data_message = t.to_data_message();
53 let mut message = vec![];
54 let hashed_channel = BubblegumClient::hash(channel);
55 message.push(BubblegumClient::PUBLISH_COMMAND);
56 message.append(&mut hashed_channel.to_le_bytes().to_vec());
57 message.append(&mut data_message.to_vec8());
58 self.socket.send(&message).expect("Couldn't send the message to the server.");
59 }
60
61 pub fn request(&self, channel: &'a str) {
62 let mut message = vec![];
63 let hashed_channel = BubblegumClient::hash(channel);
64 message.push(BubblegumClient::SUBSCRIBE_COMMAND);
65 message.append(&mut hashed_channel.to_le_bytes().to_vec());
66 self.socket.send(&message).expect("Couldn't request read from server.");
67 }
68
69 pub fn peek<T>(&self, channel: &'a str) -> Option<T>
70 where T: FromDataMessage {
71
72 self.request(channel);
73 let mut buf = [0; 2048];
74 if let Ok(len) = self.socket.recv(&mut buf) {
75 let encoded_message = buf[..len].to_vec();
76 if let Some(data_message) = DataMessage::from_vec8(encoded_message) {
77 return T::from_data_message(data_message);
78 }
79 }
80
81 return None;
82 }
83}