#![allow(dead_code)]
use std::convert::Into;
use std::fmt;
use std::string::String;
use std::vec::Vec;
use super::constants as C;
use super::constants::{CommandID, ProtocolMode, NEWLINE_STR};
pub struct Command<I>
where
I: fmt::Display,
{
id: CommandID,
args: Option<I>,
}
pub fn abort() -> Command<arg::NoArg> {
Command {
id: CommandID::ABORT,
args: None,
}
}
pub fn arqbw(bw: u16, forced: bool) -> Command<arg::ArqBw> {
Command {
id: CommandID::ARQBW,
args: Some(arg::ArqBw { bw, forced }),
}
}
pub fn arqcall<S>(target: S, attempts: u16) -> Command<arg::ArqCall>
where
S: Into<String>,
{
let s = target.into();
Command {
id: CommandID::ARQCALL,
args: Some(arg::ArqCall {
target: s,
attempts,
}),
}
}
pub fn arqtimeout(timeout: u16) -> Command<u16> {
Command {
id: CommandID::ARQTIMEOUT,
args: Some(timeout),
}
}
pub fn autobreak(autobreak: bool) -> Command<arg::BoolArg> {
Command {
id: CommandID::AUTOBREAK,
args: Some(arg::BoolArg { arg: autobreak }),
}
}
pub fn busyblock(block: bool) -> Command<arg::BoolArg> {
Command {
id: CommandID::BUSYBLOCK,
args: Some(arg::BoolArg { arg: block }),
}
}
pub fn busydet(level: u16) -> Command<u16> {
Command {
id: CommandID::BUSYDET,
args: Some(level),
}
}
pub fn cwid(cw: bool) -> Command<arg::BoolArg> {
Command {
id: CommandID::CWID,
args: Some(arg::BoolArg { arg: cw }),
}
}
pub fn disconnect() -> Command<arg::NoArg> {
Command {
id: CommandID::DISCONNECT,
args: None,
}
}
pub fn gridsquare<S>(grid: S) -> Command<String>
where
S: Into<String>,
{
let s = grid.into();
Command {
id: CommandID::GRIDSQUARE,
args: Some(s),
}
}
pub fn initialize() -> Command<arg::NoArg> {
Command {
id: CommandID::INITIALIZE,
args: None,
}
}
pub fn leader(duration: u16) -> Command<u16> {
Command {
id: CommandID::LEADER,
args: Some(duration),
}
}
pub fn listen(listen: bool) -> Command<arg::BoolArg> {
Command {
id: CommandID::LISTEN,
args: Some(arg::BoolArg { arg: listen }),
}
}
pub fn myaux(aux: Vec<String>) -> Command<arg::MyAux> {
Command {
id: CommandID::MYAUX,
args: Some(arg::MyAux { aux }),
}
}
pub fn mycall<S>(callsign: S) -> Command<String>
where
S: Into<String>,
{
let s = callsign.into();
Command {
id: CommandID::MYCALL,
args: Some(s),
}
}
pub fn ping<S>(target: S, attempts: u16) -> Command<arg::ArqCall>
where
S: Into<String>,
{
let s = target.into();
Command {
id: CommandID::PING,
args: Some(arg::ArqCall {
target: s,
attempts,
}),
}
}
pub fn protocolmode(mode: ProtocolMode) -> Command<ProtocolMode> {
Command {
id: CommandID::PROTOCOLMODE,
args: Some(mode),
}
}
pub fn sendid() -> Command<arg::NoArg> {
Command {
id: CommandID::SENDID,
args: None,
}
}
pub fn twotonetest() -> Command<arg::NoArg> {
Command {
id: CommandID::TWOTONETEST,
args: None,
}
}
pub fn version() -> Command<arg::NoArg> {
Command {
id: CommandID::VERSION,
args: None,
}
}
impl<I> Command<I>
where
I: fmt::Display,
{
pub fn command_id(&self) -> &CommandID {
&self.id
}
}
impl<I> fmt::Display for Command<I>
where
I: fmt::Display,
{
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match &self.args {
None => write!(f, "{}{}", self.command_id(), NEWLINE_STR),
Some(x) => write!(f, "{} {}{}", self.command_id(), x, NEWLINE_STR),
}
}
}
mod arg {
use super::C;
use std::fmt;
use std::string::String;
use std::vec;
pub struct NoArg {}
impl fmt::Display for NoArg {
fn fmt(&self, _f: &mut fmt::Formatter) -> fmt::Result {
Ok(())
}
}
pub struct BoolArg {
pub arg: bool,
}
impl fmt::Display for BoolArg {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", C::truth_str(self.arg),)
}
}
pub struct ArqBw {
pub bw: u16,
pub forced: bool,
}
impl fmt::Display for ArqBw {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
const FORCED: &'static [&'static str] = &["MAX", "FORCED"];
write!(f, "{}{}", self.bw, FORCED[self.forced as usize])
}
}
pub struct ArqCall {
pub target: String,
pub attempts: u16,
}
impl fmt::Display for ArqCall {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{} {}", self.target, self.attempts)
}
}
pub struct MyAux {
pub aux: vec::Vec<String>,
}
impl fmt::Display for MyAux {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
if self.aux.is_empty() {
write!(f, "X")
} else {
write!(f, "{}", self.aux.join(","))
}
}
}
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn test_abort() {
let cmd = abort();
let cmdstring = format!("{}", cmd);
assert_eq!("ABORT\r", cmdstring);
}
#[test]
fn test_autobreak() {
let cmd = autobreak(false);
let cmdstring = format!("{}", cmd);
assert_eq!("AUTOBREAK FALSE\r", cmdstring);
}
#[test]
fn test_mycall() {
let cmd = mycall("W1AW");
let cmdstring = format!("{}", cmd);
assert_eq!("MYCALL W1AW\r", cmdstring);
}
#[test]
fn test_arqbw() {
let cmd = arqbw(500, true);
let cmdstring = format!("{}", cmd);
assert_eq!("ARQBW 500FORCED\r", cmdstring);
let cmd = arqbw(2500, false);
let cmdstring = format!("{}", cmd);
assert_eq!("ARQBW 2500MAX\r", cmdstring);
}
#[test]
fn test_arqcall() {
let cmd = arqcall("W1AW-10", 5);
let cmdstring = format!("{}", cmd);
assert_eq!("ARQCALL W1AW-10 5\r", cmdstring);
}
#[test]
fn test_protocolmode() {
let cmd = protocolmode(ProtocolMode::FEC);
let cmdstring = format!("{}", cmd);
assert_eq!("PROTOCOLMODE FEC\r", cmdstring);
}
#[test]
fn test_myaux() {
let cmd = myaux(vec![]);
let cmdstring = format!("{}", cmd);
assert_eq!("MYAUX X\r", cmdstring);
let cmd = myaux(vec!["W1AW-1".to_owned()]);
let cmdstring = format!("{}", cmd);
assert_eq!("MYAUX W1AW-1\r", cmdstring);
let cmd = myaux(vec!["W1AW-1".to_owned(), "W1AW-Z".to_owned()]);
let cmdstring = format!("{}", cmd);
assert_eq!("MYAUX W1AW-1,W1AW-Z\r", cmdstring);
}
#[test]
fn test_ping() {
let cmd = ping("W1AW-10", 5);
let cmdstring = format!("{}", cmd);
assert_eq!("PING W1AW-10 5\r", cmdstring);
}
}