use bytes::Bytes;
use protocol::{Command, CommandError};
use serde_json as json;
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Builder)]
pub struct ServerInfo {
#[builder(setter(into))]
pub(crate) server_id: String,
#[builder(setter(into))]
pub(crate) version: String,
#[builder(setter(into))]
pub(crate) go: String,
#[builder(setter(into))]
pub(crate) host: String,
#[builder(setter(into))]
pub(crate) port: u32,
#[builder(setter(into))]
pub(crate) max_payload: u32,
#[builder(default)]
#[serde(skip_serializing_if = "Option::is_none")]
pub(crate) proto: Option<u8>,
#[builder(default)]
#[serde(skip_serializing_if = "Option::is_none")]
pub(crate) client_id: Option<u64>,
#[builder(default)]
#[serde(skip_serializing_if = "Option::is_none")]
pub(crate) auth_required: Option<bool>,
#[builder(default)]
#[serde(skip_serializing_if = "Option::is_none")]
pub(crate) tls_required: Option<bool>,
#[builder(default)]
#[serde(skip_serializing_if = "Option::is_none")]
pub(crate) tls_verify: Option<bool>,
#[builder(default)]
#[serde(skip_serializing_if = "Option::is_none")]
pub(crate) connect_urls: Option<Vec<String>>,
}
impl ServerInfo {
pub fn builder() -> ServerInfoBuilder {
ServerInfoBuilder::default()
}
}
impl Command for ServerInfo {
const CMD_NAME: &'static [u8] = b"INFO";
fn into_vec(self) -> Result<Bytes, CommandError> {
Ok(format!("INFO\t{}\r\n", json::to_string(&self)?).as_bytes().into())
}
fn try_parse(buf: &[u8]) -> Result<Self, CommandError> {
let len = buf.len();
if buf[len - 2..] != [b'\r', b'\n'] {
return Err(CommandError::IncompleteCommandError);
}
if buf[..4] != *Self::CMD_NAME {
return Err(CommandError::CommandMalformed);
}
Ok(json::from_slice(&buf[4..len - 2])?)
}
}
#[cfg(test)]
mod tests {
use super::{ServerInfo, ServerInfoBuilder};
use protocol::Command;
static DEFAULT_INFO: &'static str = "INFO\t{\"server_id\":\"test\",\"version\":\"1.3.0\",\"go\":\"go1.10.3\",\"host\":\"0.0.0.0\",\"port\":4222,\"max_payload\":4000,\"proto\":1,\"client_id\":1337}\r\n";
#[test]
fn it_parses() {
let parse_res = ServerInfo::try_parse(DEFAULT_INFO.as_bytes());
assert!(parse_res.is_ok());
let cmd = parse_res.unwrap();
assert_eq!(&cmd.server_id, "test");
assert_eq!(&cmd.version, "1.3.0");
assert_eq!(cmd.proto, Some(1u8));
assert_eq!(&cmd.go, "go1.10.3");
assert_eq!(&cmd.host, "0.0.0.0");
assert_eq!(cmd.port, 4222u32);
assert_eq!(cmd.max_payload, 4000u32);
assert!(cmd.client_id.is_some());
assert_eq!(cmd.client_id, Some(1337u64));
}
#[test]
fn it_stringifies() {
let cmd = ServerInfoBuilder::default()
.server_id("test")
.version("1.3.0")
.proto(Some(1u8))
.go("go1.10.3")
.host("0.0.0.0")
.port(4222u32)
.max_payload(4000u32)
.client_id(Some(1337))
.build()
.unwrap();
let cmd_bytes_res = cmd.into_vec();
assert!(cmd_bytes_res.is_ok());
let cmd_bytes = cmd_bytes_res.unwrap();
assert_eq!(DEFAULT_INFO, cmd_bytes);
}
}