#![doc = include_str!(concat!(env!("CARGO_MANIFEST_DIR"), "/README.md"))]
pub use dns::DnsCommand;
pub use domain::DomainCommand;
use error::ErrorExt;
pub use invoice::{InvoiceAction, InvoiceCommand};
pub use product::ProductCommand;
use std::{env::VarError, fmt::Display, str::FromStr};
use strum::{Display, EnumString};
pub use vps::{VpsAction, VpsCommand};
pub use error::Error;
pub type Result<T> = std::result::Result<T, Error>;
mod dns;
mod domain;
mod error;
mod invoice;
mod product;
mod str_extension;
mod vps;
const COMMENT: &str = "#";
const PING: &str = "ping";
const DNS_COMMAND: &str = "dns ";
const DOMAIN_COMMAND: &str = "domain ";
const INVOICE_COMMAND: &str = "invoice ";
const ONERROR_COMMAND: &str = "onerror ";
const PRODUCT_COMMAND: &str = "product ";
const SLEEP_COMMAND: &str = "sleep ";
const VPS_COMMAND: &str = "vps ";
#[derive(Clone, Debug, PartialEq, Display, EnumString)]
#[strum(serialize_all = "lowercase")]
pub enum OnError {
Print,
Exit,
}
#[derive(Debug, PartialEq)]
pub enum TransipCommand {
Comment(String),
Domain(domain::DomainCommand),
Dns(dns::DnsCommand),
Invoice(invoice::InvoiceCommand),
OnError(OnError),
Product(product::ProductCommand),
Vps(vps::VpsCommand),
Ping,
Sleep(u64),
}
impl FromStr for TransipCommand {
type Err = Error;
fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
macro_rules! parse {
($trimmed:expr, $command:expr, $sub_command_type:path, $map:path) => {
if let Some(sub_command) = $trimmed.strip_prefix($command) {
return sub_command
.trim()
.parse::<$sub_command_type>()
.err_into()
.map($map);
}
};
}
if s.starts_with(COMMENT) {
return Ok(TransipCommand::Comment(s.to_owned()));
}
let trimmed = s.trim();
if trimmed == PING {
return Ok(TransipCommand::Ping);
}
parse!(trimmed, DNS_COMMAND, DnsCommand, TransipCommand::Dns);
parse!(
trimmed,
DOMAIN_COMMAND,
DomainCommand,
TransipCommand::Domain
);
parse!(
trimmed,
INVOICE_COMMAND,
InvoiceCommand,
TransipCommand::Invoice
);
parse!(trimmed, ONERROR_COMMAND, OnError, TransipCommand::OnError);
parse!(
trimmed,
PRODUCT_COMMAND,
ProductCommand,
TransipCommand::Product
);
parse!(trimmed, SLEEP_COMMAND, u64, TransipCommand::Sleep);
parse!(trimmed, VPS_COMMAND, VpsCommand, TransipCommand::Vps);
Err(Error::ParseTransipCommand(s.to_owned()))
}
}
impl Display for TransipCommand {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
TransipCommand::Comment(comment) => write!(f, "{}", comment),
TransipCommand::Dns(command) => write!(f, "{}{}", DNS_COMMAND, command),
TransipCommand::Domain(command) => write!(f, "{}{}", DOMAIN_COMMAND, command),
TransipCommand::Invoice(command) => write!(f, "{}{}", INVOICE_COMMAND, command),
TransipCommand::OnError(onerror) => write!(f, "{}{}", ONERROR_COMMAND, onerror),
TransipCommand::Product(command) => write!(f, "{}{}", PRODUCT_COMMAND, command),
TransipCommand::Sleep(timeout) => write!(f, "{}{}", SLEEP_COMMAND, timeout),
TransipCommand::Vps(command) => write!(f, "{}{}", VPS_COMMAND, command),
TransipCommand::Ping => write!(f, "{}", PING),
}
}
}
fn check_environment(name: &str) -> std::result::Result<String, VarError> {
if name.starts_with("${") && name.ends_with('}') {
let s = name[2..name.len() - 1].trim();
std::env::var(s)
} else {
Ok(name.to_owned())
}
}
#[cfg(test)]
mod test {
use super::TransipCommand;
#[test]
fn display() {
assert_eq!(
TransipCommand::Comment("# lksadjf".to_owned()).to_string(),
"# lksadjf".to_owned(),
);
assert_eq!(
TransipCommand::Dns(crate::DnsCommand::List("paulmin.nl".to_owned())).to_string(),
"dns list paulmin.nl".to_owned(),
);
assert_eq!(
TransipCommand::Domain(crate::DomainCommand::List).to_string(),
"domain list".to_owned(),
);
assert_eq!(
TransipCommand::Invoice(crate::InvoiceCommand::List).to_string(),
"invoice list".to_owned(),
);
assert_eq!(
TransipCommand::Product(crate::ProductCommand::List).to_string(),
"product list".to_owned(),
);
assert_eq!(
TransipCommand::OnError(crate::OnError::Exit).to_string(),
"onerror exit".to_owned(),
);
assert_eq!(
TransipCommand::OnError(crate::OnError::Print).to_string(),
"onerror print".to_owned(),
);
assert_eq!(TransipCommand::Ping.to_string(), "ping".to_owned(),);
}
#[test]
fn transip_command_from_str() {
assert_eq!(
"# alsjff".parse::<TransipCommand>().unwrap(),
TransipCommand::Comment("# alsjff".to_owned()),
);
assert_eq!(
"dns list paulmin.nl ".parse::<TransipCommand>().unwrap(),
TransipCommand::Dns(crate::DnsCommand::List("paulmin.nl".to_owned()))
);
assert_eq!(
"vps \treset paulusminus-vps2"
.parse::<TransipCommand>()
.unwrap(),
TransipCommand::Vps(crate::VpsCommand::Action(
"paulusminus-vps2".to_owned(),
crate::VpsAction::Reset,
))
);
assert_eq!(
"sleep 3984".parse::<TransipCommand>().unwrap(),
TransipCommand::Sleep(3984),
);
assert_eq!(
"onerror print ".parse::<TransipCommand>().unwrap(),
TransipCommand::OnError(crate::OnError::Print),
);
assert_eq!(
"onerror exit".parse::<TransipCommand>().unwrap(),
TransipCommand::OnError(crate::OnError::Exit),
);
assert_eq!(
" ping ".parse::<TransipCommand>().unwrap(),
TransipCommand::Ping,
);
}
}