use super::scope::Scope;
use serialize::json::{Json, ToJson, Object, Array};
use super::event::EventType;
use std::string::ToString;
use std::str::FromStr;
use super::error::ParseConfigGroupError;
use std::ascii::AsciiExt;
pub const PROTOCOL_VERSION: &'static str = "1";
pub type Network = String;
pub type Message = String;
pub type Target = String;
pub type Command = String;
pub type PluginName = String;
pub type PluginVersion = String;
#[derive(Debug, Clone, PartialEq)]
pub enum ConfigGroup {
Plugin,
Core,
}
impl ToString for ConfigGroup {
fn to_string(&self) -> String {
match *self {
ConfigGroup::Plugin => "plugin".to_string(),
ConfigGroup::Core => "core".to_string(),
}
}
}
impl FromStr for ConfigGroup {
type Err = ParseConfigGroupError;
fn from_str(s: &str) -> Result<Self, ParseConfigGroupError> {
match &s.to_ascii_lowercase()[..] {
"plugin" => Ok(ConfigGroup::Plugin),
"core" => Ok(ConfigGroup::Core),
_ => Err(ParseConfigGroupError::new())
}
}
}
#[derive(Debug, Clone, PartialEq)]
pub enum Request {
Subscribe(EventType),
Unsubscribe(EventType),
SubscribeCommand(Command, Option<Network>),
Networks,
Channels(Network),
Message(Network, Target, Message),
Notice(Network, Target, Message),
Ctcp(Network, Target, Message),
CtcpReply(Network, Target, Message),
Action(Network, Target, Message),
Names(Network, Target),
Whois(Network, Target),
Join(Network, Target),
Part(Network, Target),
Nick(Network),
Handshake(PluginName, PluginVersion, Option<String>),
Config(String, ConfigGroup),
GetProperty(String, Scope),
SetProperty(String, String, Scope),
UnsetProperty(String, Scope),
PropertyKeys(String, Scope),
SetPermission(String, bool, Scope),
HasPermission(String, bool, Scope),
UnsetPermission(String, Scope),
}
impl Request {
fn get_json_name(&self) -> Json {
let s = match *self {
Request::Subscribe(EventType::Command(_)) => "command",
Request::Subscribe(_) => "subscribe",
Request::Unsubscribe(_) => "unsubscribe",
Request::SubscribeCommand(_, _) => "command",
Request::Networks => "networks",
Request::Channels(_) => "channels",
Request::Message(_, _, _) => "message",
Request::Notice(_, _, _) => "notice",
Request::Ctcp(_, _, _) => "ctcp",
Request::CtcpReply(_, _, _) => "ctcp_rep",
Request::Action(_, _, _) => "action",
Request::Names(_, _) => "names",
Request::Whois(_, _) => "whois",
Request::Join(_, _) => "join",
Request::Part(_, _) => "part",
Request::Nick(_) => "nick",
Request::Handshake(_, _, _) => "handshake",
Request::Config(_, _) => "config",
Request::GetProperty(_, _) => "property",
Request::SetProperty(_, _, _) => "property",
Request::UnsetProperty(_, _) => "property",
Request::PropertyKeys(_, _) => "property",
Request::SetPermission(_, _, _) => "permission",
Request::HasPermission(_, _, _) => "permission",
Request::UnsetPermission(_, _) => "permission",
};
Json::String(s.to_string())
}
fn get_action_type(&self) -> String {
let s = match *self {
Request::Networks | Request::Channels(_) | Request::Nick(_) | Request::Config(_, _) => "get",
_ => "do",
};
s.to_string()
}
}
impl ToJson for Request {
fn to_json(&self) -> Json {
let mut obj = Object::new();
obj.insert(self.get_action_type(), self.get_json_name());
let mut params = Array::new();
macro_rules! push_str { ($x: expr) => ( params.push(Json::String($x.clone())) ) }
match *self {
Request::Subscribe(EventType::Command(ref cmd)) => {
push_str!(cmd);
},
Request::Unsubscribe(EventType::Command(_)) => {
panic!("Cannot unsubscribe from command");
},
Request::Subscribe(ref evt) => {
push_str!(evt.to_string());
},
Request::Unsubscribe(ref evt) => {
push_str!(evt.to_string());
},
Request::SubscribeCommand(ref cmd, Some(ref network)) => {
push_str!(cmd);
push_str!(network);
},
Request::SubscribeCommand(ref cmd, None) => {
push_str!(cmd);
},
Request::Networks => (),
Request::Channels(ref network)
| Request::Nick(ref network) => {
push_str!(network);
},
Request::Message(ref network, ref channel, ref message)
| Request::Notice(ref network, ref channel, ref message)
| Request::Ctcp(ref network, ref channel, ref message)
| Request::CtcpReply(ref network, ref channel, ref message)
| Request::Action(ref network, ref channel, ref message) => {
push_str!(network);
push_str!(channel);
push_str!(message);
},
Request::Names(ref network, ref channel)
| Request::Join(ref network, ref channel)
| Request::Part(ref network, ref channel) => {
push_str!(network);
push_str!(channel);
},
Request::Whois(ref network, ref user) => {
push_str!(network);
push_str!(user);
},
Request::Handshake(ref name, ref version, Some(ref config_name)) => {
push_str!(name);
push_str!(version);
push_str!(PROTOCOL_VERSION.to_string());
push_str!(config_name);
},
Request::Handshake(ref name, ref version, None) => {
push_str!(name);
push_str!(version);
push_str!(PROTOCOL_VERSION.to_string());
push_str!(name);
},
Request::Config(ref key, ref ctype) => {
push_str!(ctype.to_string());
push_str!(key);
},
Request::GetProperty(ref property, ref scope) => {
push_str!("get".to_string());
push_str!(property);
if !scope.is_any() {
obj.insert("scope".to_string(), scope.to_json());
}
},
Request::SetProperty(ref property, ref value, ref scope) => {
push_str!("set".to_string());
push_str!(property);
push_str!(value);
if !scope.is_any() {
obj.insert("scope".to_string(), scope.to_json());
}
},
Request::UnsetProperty(ref property, ref scope) => {
push_str!("unset".to_string());
push_str!(property);
if !scope.is_any() {
obj.insert("scope".to_string(), scope.to_json());
}
},
Request::PropertyKeys(ref prefix, ref scope) => {
push_str!("keys".to_string());
push_str!(prefix);
if !scope.is_any() {
obj.insert("scope".to_string(), scope.to_json());
}
},
Request::SetPermission(ref permission, ref default, ref scope) => {
push_str!("set".to_string());
push_str!(permission);
params.push(Json::Boolean(*default));
if !scope.is_any() {
obj.insert("scope".to_string(), scope.to_json());
}
},
Request::HasPermission(ref permission, ref default, ref scope) => {
push_str!("get".to_string());
push_str!(permission);
params.push(Json::Boolean(*default));
if !scope.is_any() {
obj.insert("scope".to_string(), scope.to_json());
}
},
Request::UnsetPermission(ref permission, ref scope) => {
push_str!("unset".to_string());
push_str!(permission);
if !scope.is_any() {
obj.insert("scope".to_string(), scope.to_json());
}
},
}
if params.len() > 0 {
obj.insert("params".to_string(), Json::Array(params));
}
Json::Object(obj)
}
}