Implement varargs

This commit is contained in:
Aram 🍐 2021-08-04 02:05:57 -04:00
parent 95cf9aeccf
commit a7f730c04a
2 changed files with 50 additions and 11 deletions

View file

@ -36,16 +36,18 @@ impl_sentences! {
{} {}
), ),
/// Server returns an error. /// Server returns an error.
/// TODO: Support "extra" vararg.
RespondErr ( RespondErr (
{ {
0: Err, 0: Err,
1: Arg, 1: Arg,
2: EOL,
}, },
{ {
/// The error code. /// The error code.
1: message, 1: message,
},
{
/// Extra information about the error.
2...: extras
} }
), ),
/// Server responds with the number of prior logins to the given `ups_name` device. /// Server responds with the number of prior logins to the given `ups_name` device.
@ -97,22 +99,21 @@ impl_sentences! {
} }
), ),
/// Server responds with the type of the given `var_name` variable for the UPS device. /// Server responds with the type of the given `var_name` variable for the UPS device.
/// TODO: Support multiple type words (3...).
RespondType ( RespondType (
{ {
0: Type, 0: Type,
1: Arg, 1: Arg,
2: Arg, 2: Arg,
3: Arg,
4: EOL,
}, },
{ {
/// The name of the UPS device. /// The name of the UPS device.
1: ups_name, 1: ups_name,
/// The name of the variable. /// The name of the variable.
2: var_name, 2: var_name,
/// The type of the variable. },
3: var_type, {
/// The variable definition (RW, ENUN, STRING...)
3...: var_types
} }
), ),
/// Server responds with the description of the given `var_name` variable for the UPS device. /// Server responds with the description of the given `var_name` variable for the UPS device.
@ -483,6 +484,14 @@ mod tests {
["ERR", "ACCESS-DENIED"] <=> ["ERR", "ACCESS-DENIED"] <=>
Sentences::RespondErr { Sentences::RespondErr {
message: "ACCESS-DENIED".into(), message: "ACCESS-DENIED".into(),
extras: vec![],
}
);
test_encode_decode!(
["ERR", "ACCESS-DENIED", "extra1", "extra2"] <=>
Sentences::RespondErr {
message: "ACCESS-DENIED".into(),
extras: vec!["extra1".into(), "extra2".into()],
} }
); );
test_encode_decode!( test_encode_decode!(
@ -508,11 +517,11 @@ mod tests {
} }
); );
test_encode_decode!( test_encode_decode!(
["TYPE", "nutdev", "input.transfer.low", "ENUM"] <=> ["TYPE", "nutdev", "input.transfer.low", "ENUM", "RW"] <=>
Sentences::RespondType { Sentences::RespondType {
ups_name: "nutdev".into(), ups_name: "nutdev".into(),
var_name: "input.transfer.low".into(), var_name: "input.transfer.low".into(),
var_type: "ENUM".into(), var_types: vec!["ENUM".into(), "RW".into()],
} }
); );
test_encode_decode!( test_encode_decode!(

View file

@ -82,6 +82,16 @@ macro_rules! impl_words {
false false
} }
} }
/// Whether the `Word` matches all words in the vec, starting at the given index.
pub(crate) fn matches_until_end(&self, start: usize, others: &[Option<Self>]) -> bool {
for i in start..others.len() {
if !self.matches(others.get(i)) {
return false;
}
}
true
}
} }
}; };
} }
@ -102,6 +112,12 @@ macro_rules! impl_sentences {
$argidx:tt: $arg:ident, $argidx:tt: $arg:ident,
)* )*
} }
$(
,{
$(#[$varargattr:meta])+
$varargidx:tt...: $vararg:ident
}
)?
), ),
)* )*
) => { ) => {
@ -115,6 +131,10 @@ macro_rules! impl_sentences {
$(#[$argattr])* $(#[$argattr])*
$arg: String, $arg: String,
)* )*
$(
$(#[$varargattr])*
$vararg: Vec<String>,
)*
}, },
)* )*
} }
@ -127,13 +147,16 @@ macro_rules! impl_sentences {
let words = Word::decode_words(raw.as_slice()); let words = Word::decode_words(raw.as_slice());
$( $(
if true $(&& $word.matches(words.get($wordidx)))* { if true
$(&& $word.matches(words.get($wordidx)))*
$(&& Arg.matches_until_end($varargidx, &words))*
{
return Some($name { return Some($name {
$($arg: raw[$argidx].to_owned(),)* $($arg: raw[$argidx].to_owned(),)*
$($vararg: raw[$varargidx..].to_owned(),)*
}) })
} }
)* )*
None None
} }
@ -144,6 +167,7 @@ macro_rules! impl_sentences {
$( $(
Self::$name { Self::$name {
$($arg,)* $($arg,)*
$($vararg,)*
} => { } => {
#[allow(unused_mut)] #[allow(unused_mut)]
let mut words = vec![ let mut words = vec![
@ -156,6 +180,12 @@ macro_rules! impl_sentences {
words[$argidx] = Some($arg); words[$argidx] = Some($arg);
)* )*
$(
for vararg in $vararg {
words.push(Some(vararg));
}
)*
words words
.into_iter() .into_iter()
.flatten() .flatten()