1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140
#[macro_use] extern crate serde_derive; use redis::Commands; use rmp_serde::Serializer; use serde::Serialize; use std::collections::HashMap; #[derive(Debug, Clone)] pub struct Emitter { redis: redis::Client, prefix: String, nsp: String, channel: String, rooms: Vec<String>, flags: HashMap<String, bool>, uid: String, } #[derive(Debug, PartialEq, Serialize, Deserialize)] struct Opts { rooms: Vec<String>, flags: HashMap<String, bool>, } #[derive(Debug, PartialEq, Serialize, Deserialize)] pub struct Packet { #[serde(rename = "type")] _type: i32, data: Vec<String>, nsp: String, } #[derive(Debug, PartialEq, Clone, Default)] pub struct EmitterOpts<'a> { pub host: String, pub port: i32, pub socket: Option<String>, pub key: Option<&'a str>, } pub trait IntoEmitter { fn into_emitter(self) -> Emitter; } impl IntoEmitter for redis::Client { fn into_emitter(self) -> Emitter { create_emitter(self, "socket.io", "/") } } impl<'a> IntoEmitter for EmitterOpts<'a> { fn into_emitter(self) -> Emitter { let addr = format!("redis://{}:{}", self.host, self.port); let prefix = match self.key { Some(key) => key, None => "socket.io", }; create_emitter(redis::Client::open(addr.as_str()).unwrap(), prefix, "/") } } impl IntoEmitter for &str { fn into_emitter(self) -> Emitter { create_emitter( redis::Client::open(format!("redis://{}", self).as_str()).unwrap(), "socket.io", "/", ) } } fn create_emitter(redis: redis::Client, prefix: &str, nsp: &str) -> Emitter { Emitter { redis: redis, prefix: prefix.to_string(), nsp: nsp.to_string(), channel: format!("{}#{}#", prefix, nsp), rooms: Vec::new(), flags: HashMap::new(), uid: "emitter".to_string(), } } impl Emitter { pub fn new<I: IntoEmitter>(data: I) -> Emitter { data.into_emitter() } pub fn to(mut self, room: &str) -> Emitter { self.rooms.push(room.to_string()); self } pub fn of(self, nsp: &str) -> Emitter { create_emitter(self.redis, self.prefix.as_str(), nsp) } pub fn json(mut self) -> Emitter { let mut flags = HashMap::new(); flags.insert("json".to_string(), true); self.flags = flags; self } pub fn volatile(mut self) -> Emitter { let mut flags = HashMap::new(); flags.insert("volatile".to_string(), true); self.flags = flags; self } pub fn broadcast(mut self) -> Emitter { let mut flags = HashMap::new(); flags.insert("broadcast".to_string(), true); self.flags = flags; self } pub fn emit(mut self, message: Vec<&str>) -> Emitter { let packet = Packet { _type: 2, data: message.iter().map(|s| s.to_string()).collect(), nsp: self.nsp.clone(), }; let opts = Opts { rooms: self.rooms.clone(), flags: self.flags.clone(), }; let mut msg = Vec::new(); let val = (self.uid.clone(), packet, opts); val.serialize(&mut Serializer::new_named(&mut msg)).unwrap(); let channel = if self.rooms.len() == 1 { format!("{}{}#", self.channel.clone(), self.rooms.join("#")) } else { self.channel.clone() }; let _: () = self.redis.publish(channel, msg).unwrap(); self.rooms = vec![]; self.flags = HashMap::new(); self } }