bubblegum_cli_rs/
bubblegum_cli.rs

1use 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}