socketio-rust-emitter 0.1.2

A Rust implementation of socketio-emitter
Documentation
#[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
    }
}