use std::fmt::Display;
#[derive(Clone, Debug, Default, PartialEq, serde::Serialize)]
#[serde(rename_all = "camelCase")]
pub struct CommandRequest {
pub command: String,
#[serde(skip_serializing_if = "CommandRequest::can_omit_parameter")]
pub parameter: String,
#[serde(skip_serializing_if = "CommandRequest::can_omit_command_type")]
pub command_type: String,
}
impl CommandRequest {
const DEFAULT_PARAMETER: &str = "default";
const DEFAULT_COMMAND_TYPE: &str = "command";
fn can_omit_parameter(str: &str) -> bool {
str.is_empty() || str == Self::DEFAULT_PARAMETER
}
fn can_omit_command_type(str: &str) -> bool {
str.is_empty() || str == Self::DEFAULT_COMMAND_TYPE
}
}
impl Display for CommandRequest {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
if !Self::can_omit_command_type(&self.command_type) {
write!(f, "{}/", self.command_type)?;
}
write!(f, "{}", self.command)?;
if !Self::can_omit_parameter(&self.parameter) {
write!(f, ":{}", self.parameter)?;
}
Ok(())
}
}
impl From<&str> for CommandRequest {
fn from(mut text: &str) -> Self {
let mut command = CommandRequest::default();
if let Some((name, parameter)) = text.split_once(':') {
command.parameter = parameter.into();
text = name;
}
if let Some((command_type, name)) = text.split_once('/') {
command.command_type = command_type.into();
text = name;
}
command.command = text.into();
command
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn serialize_all() {
let all = CommandRequest {
command: "test_command".into(),
parameter: "param".into(),
command_type: "type".into(),
};
assert_eq!(
serde_json::to_string(&all).unwrap(),
r#"{"command":"test_command","parameter":"param","commandType":"type"}"#
);
}
#[test]
fn serialize_default() {
let param_type_default = CommandRequest {
command: "test_command".into(),
..Default::default()
};
assert_eq!(
serde_json::to_string(¶m_type_default).unwrap(),
r#"{"command":"test_command"}"#
);
}
#[test]
fn serialize_default_str() {
let param_type_default = CommandRequest {
command: "test_command".into(),
parameter: CommandRequest::DEFAULT_PARAMETER.into(),
command_type: CommandRequest::DEFAULT_COMMAND_TYPE.into(),
};
assert_eq!(
serde_json::to_string(¶m_type_default).unwrap(),
r#"{"command":"test_command"}"#
);
}
#[test]
fn serialize_empty() {
let param_type_empty = CommandRequest {
command: "test_command".into(),
parameter: String::default(),
command_type: String::default(),
};
assert_eq!(
serde_json::to_string(¶m_type_empty).unwrap(),
r#"{"command":"test_command"}"#
);
}
#[test]
fn serialize_param() {
let with_param = CommandRequest {
command: "test_command".into(),
parameter: "param".into(),
..Default::default()
};
assert_eq!(
serde_json::to_string(&with_param).unwrap(),
r#"{"command":"test_command","parameter":"param"}"#
);
}
#[test]
fn serialize_type() {
let with_type = CommandRequest {
command: "test_command".into(),
command_type: "type".into(),
..Default::default()
};
assert_eq!(
serde_json::to_string(&with_type).unwrap(),
r#"{"command":"test_command","commandType":"type"}"#
);
}
}