mirror of
https://github.com/arampoire/nut-rs.git
synced 2025-12-01 00:30:23 -05:00
Finish implementing decoding of server-bound sentences
This commit is contained in:
parent
497ac97395
commit
e937899f8a
2 changed files with 366 additions and 62 deletions
|
|
@ -20,6 +20,7 @@ mod cmd;
|
||||||
mod config;
|
mod config;
|
||||||
mod error;
|
mod error;
|
||||||
/// Bi-directional networking protocol implementation.
|
/// Bi-directional networking protocol implementation.
|
||||||
|
#[allow(dead_code)]
|
||||||
mod proto;
|
mod proto;
|
||||||
#[cfg(feature = "ssl")]
|
#[cfg(feature = "ssl")]
|
||||||
mod ssl;
|
mod ssl;
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@ macro_rules! impl_words {
|
||||||
$name:ident($word:tt),
|
$name:ident($word:tt),
|
||||||
)*
|
)*
|
||||||
) => {
|
) => {
|
||||||
|
#[allow(clippy::upper_case_acronyms)]
|
||||||
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
|
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
|
||||||
pub(crate) enum Word {
|
pub(crate) enum Word {
|
||||||
/// A string argument.
|
/// A string argument.
|
||||||
|
|
@ -138,16 +139,152 @@ impl_words! {
|
||||||
Version("VERSION"),
|
Version("VERSION"),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
macro_rules! impl_sentences {
|
||||||
|
(
|
||||||
|
$(
|
||||||
|
$(#[$attr:meta])+
|
||||||
|
$name:ident(
|
||||||
|
{
|
||||||
|
$($wordidx:tt: $word:ident,)*
|
||||||
|
},
|
||||||
|
{
|
||||||
|
$(
|
||||||
|
$(#[$argattr:meta])+
|
||||||
|
$argidx:tt: $arg:ident,
|
||||||
|
)*
|
||||||
|
}
|
||||||
|
),
|
||||||
|
)*
|
||||||
|
) => {
|
||||||
|
/// Protocol sentences.
|
||||||
|
#[derive(Debug, Clone, Eq, PartialEq)]
|
||||||
|
pub enum Sentences {
|
||||||
|
$(
|
||||||
|
$(#[$attr])*
|
||||||
|
$name {
|
||||||
|
$(
|
||||||
|
$(#[$argattr])*
|
||||||
|
$arg: String,
|
||||||
|
)*
|
||||||
|
},
|
||||||
|
)*
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Sentences {
|
||||||
|
/// Decodes a sentence. Returns `None` if the pattern cannot be recognized.
|
||||||
|
pub(crate) fn decode(raw: Vec<String>) -> Option<Sentences> {
|
||||||
|
use super::{Word::*, *};
|
||||||
|
use Sentences::*;
|
||||||
|
let words = Word::decode_words(raw.as_slice());
|
||||||
|
|
||||||
|
$(
|
||||||
|
if true $(&& $word.matches(words.get($wordidx)))* {
|
||||||
|
return Some($name {
|
||||||
|
$($arg: raw[$argidx].to_owned(),)*
|
||||||
|
})
|
||||||
|
}
|
||||||
|
)*
|
||||||
|
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
/// Messages decoded by the server.
|
/// Messages decoded by the server.
|
||||||
pub mod server_bound {
|
pub mod server_bound {
|
||||||
impl_sentences! {
|
impl_sentences! {
|
||||||
QueryVersion (
|
/// Client requests the number of prior logins to the given `ups_name` device.
|
||||||
|
QueryNumLogins (
|
||||||
{
|
{
|
||||||
0: Version,
|
0: Get,
|
||||||
1: EOL,
|
1: NumLogins,
|
||||||
|
2: Arg,
|
||||||
|
3: EOL,
|
||||||
},
|
},
|
||||||
{}
|
{
|
||||||
|
/// The name of the UPS device.
|
||||||
|
2: ups_name,
|
||||||
|
}
|
||||||
),
|
),
|
||||||
|
/// Client requests the description of the given `ups_name` device.
|
||||||
|
QueryUpsDesc (
|
||||||
|
{
|
||||||
|
0: Get,
|
||||||
|
1: UpsDesc,
|
||||||
|
2: Arg,
|
||||||
|
3: EOL,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
/// The name of the UPS device.
|
||||||
|
2: ups_name,
|
||||||
|
}
|
||||||
|
),
|
||||||
|
/// Client requests the value of the given `var_name` variable in the given `ups_name` device.
|
||||||
|
QueryVar (
|
||||||
|
{
|
||||||
|
0: Get,
|
||||||
|
1: Var,
|
||||||
|
2: Arg,
|
||||||
|
3: Arg,
|
||||||
|
4: EOL,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
/// The name of the UPS device.
|
||||||
|
2: ups_name,
|
||||||
|
/// The name of the variable.
|
||||||
|
3: var_name,
|
||||||
|
}
|
||||||
|
),
|
||||||
|
/// Client requests the type of the given `var_name` variable in the given `ups_name` device.
|
||||||
|
QueryType (
|
||||||
|
{
|
||||||
|
0: Get,
|
||||||
|
1: Type,
|
||||||
|
2: Arg,
|
||||||
|
3: Arg,
|
||||||
|
4: EOL,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
/// The name of the UPS device.
|
||||||
|
2: ups_name,
|
||||||
|
/// The name of the variable.
|
||||||
|
3: var_name,
|
||||||
|
}
|
||||||
|
),
|
||||||
|
/// Client requests the description of the given `var_name` variable in the given `ups_name` device.
|
||||||
|
QueryDesc (
|
||||||
|
{
|
||||||
|
0: Get,
|
||||||
|
1: Desc,
|
||||||
|
2: Arg,
|
||||||
|
3: Arg,
|
||||||
|
4: EOL,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
/// The name of the UPS device.
|
||||||
|
2: ups_name,
|
||||||
|
/// The name of the variable.
|
||||||
|
3: var_name,
|
||||||
|
}
|
||||||
|
),
|
||||||
|
/// Client requests the description of the given `cmd_name` command in the given `ups_name` device.
|
||||||
|
QueryCmdDesc (
|
||||||
|
{
|
||||||
|
0: Get,
|
||||||
|
1: CmdDesc,
|
||||||
|
2: Arg,
|
||||||
|
3: Arg,
|
||||||
|
4: EOL,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
/// The name of the UPS device.
|
||||||
|
2: ups_name,
|
||||||
|
/// The name of the command.
|
||||||
|
3: cmd_name,
|
||||||
|
}
|
||||||
|
),
|
||||||
|
/// Client requests the list of variables for the given `ups_name` device.
|
||||||
QueryListVar (
|
QueryListVar (
|
||||||
{
|
{
|
||||||
0: List,
|
0: List,
|
||||||
|
|
@ -156,68 +293,234 @@ pub mod server_bound {
|
||||||
3: EOL,
|
3: EOL,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
2: ups_name: String,
|
/// The name of the UPS device.
|
||||||
|
2: ups_name,
|
||||||
}
|
}
|
||||||
)
|
),
|
||||||
}
|
/// Client requests the list of mutable variables for the given `ups_name` device.
|
||||||
|
QueryListRw (
|
||||||
// TODO: Macro
|
|
||||||
#[derive(Debug, Clone, Eq, PartialEq)]
|
|
||||||
pub enum Sentences {
|
|
||||||
QueryVersion {},
|
|
||||||
QueryNetworkVersion {},
|
|
||||||
QueryHelp {},
|
|
||||||
QueryListUps {},
|
|
||||||
QueryListVar { ups_name: String },
|
|
||||||
QueryListRw { ups_name: String },
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: Macro
|
|
||||||
impl Sentences {
|
|
||||||
pub(crate) fn decode(raw: Vec<String>) -> Option<Sentences> {
|
|
||||||
use super::{Word::*, *};
|
|
||||||
use Sentences::*;
|
|
||||||
let words = Word::decode_words(raw.as_slice());
|
|
||||||
|
|
||||||
if Version.matches(words.get(0)) && EOL.matches(words.get(1)) {
|
|
||||||
return Some(QueryVersion {});
|
|
||||||
}
|
|
||||||
if List.matches(words.get(0))
|
|
||||||
&& Var.matches(words.get(1))
|
|
||||||
&& Arg.matches(words.get(2))
|
|
||||||
&& EOL.matches(words.get(3))
|
|
||||||
{
|
{
|
||||||
return Some(QueryListVar {
|
0: List,
|
||||||
ups_name: raw[2].to_owned(),
|
1: Rw,
|
||||||
});
|
2: Arg,
|
||||||
|
3: EOL,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
/// The name of the UPS device.
|
||||||
|
2: ups_name,
|
||||||
|
}
|
||||||
|
),
|
||||||
|
/// Client requests the list of commands for the given `ups_name` device.
|
||||||
|
QueryListCmd (
|
||||||
|
{
|
||||||
|
0: List,
|
||||||
|
1: Cmd,
|
||||||
|
2: Arg,
|
||||||
|
3: EOL,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
/// The name of the UPS device.
|
||||||
|
2: ups_name,
|
||||||
|
}
|
||||||
|
),
|
||||||
|
/// Client requests the list of possible values of the enumerable variable `var_name`
|
||||||
|
/// for the given `ups_name` device.
|
||||||
|
QueryListEnum (
|
||||||
|
{
|
||||||
|
0: List,
|
||||||
|
1: Enum,
|
||||||
|
2: Arg,
|
||||||
|
3: Arg,
|
||||||
|
4: EOL,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
/// The name of the UPS device.
|
||||||
|
2: ups_name,
|
||||||
|
/// The name of the variable.
|
||||||
|
3: var_name,
|
||||||
|
}
|
||||||
|
),
|
||||||
|
/// Client requests the list of possible ranges of the numerical variable `var_name`
|
||||||
|
/// for the given `ups_name` device.
|
||||||
|
QueryListRange (
|
||||||
|
{
|
||||||
|
0: List,
|
||||||
|
1: Range,
|
||||||
|
2: Arg,
|
||||||
|
3: Arg,
|
||||||
|
4: EOL,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
/// The name of the UPS device.
|
||||||
|
2: ups_name,
|
||||||
|
/// The name of the variable.
|
||||||
|
3: var_name,
|
||||||
|
}
|
||||||
|
),
|
||||||
|
/// Client requests the list of clients connected to the given `ups_name` device.
|
||||||
|
QueryListClient (
|
||||||
|
{
|
||||||
|
0: List,
|
||||||
|
1: Client,
|
||||||
|
3: Arg,
|
||||||
|
4: EOL,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
/// The name of the UPS device.
|
||||||
|
2: ups_name,
|
||||||
|
}
|
||||||
|
),
|
||||||
|
/// Client requests to set the value `value` of the `var_name` variable on the `ups_name` device.
|
||||||
|
ExecSetVar (
|
||||||
|
{
|
||||||
|
0: Set,
|
||||||
|
1: Var,
|
||||||
|
2: Arg,
|
||||||
|
3: Arg,
|
||||||
|
4: Arg,
|
||||||
|
5: EOL,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
/// The name of the UPS device.
|
||||||
|
2: ups_name,
|
||||||
|
/// The name of the variable.
|
||||||
|
3: var_name,
|
||||||
|
/// The new value of the variable.
|
||||||
|
4: value,
|
||||||
|
}
|
||||||
|
),
|
||||||
|
/// Client requests the execution of an instant command `cmd_name` on the `ups_name` device.
|
||||||
|
ExecInstCmd (
|
||||||
|
{
|
||||||
|
0: InstCmd,
|
||||||
|
1: Arg,
|
||||||
|
2: Arg,
|
||||||
|
3: EOL,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
/// The name of the UPS device.
|
||||||
|
1: ups_name,
|
||||||
|
/// The name of the command.
|
||||||
|
2: cmd_name,
|
||||||
|
}
|
||||||
|
),
|
||||||
|
/// Client logs-out of the current UPS device.
|
||||||
|
ExecLogout (
|
||||||
|
{
|
||||||
|
0: Logout,
|
||||||
|
1: EOL,
|
||||||
|
},
|
||||||
|
{}
|
||||||
|
),
|
||||||
|
/// Client logs-into the given `ups_name` device.
|
||||||
|
ExecLogin (
|
||||||
|
{
|
||||||
|
0: Login,
|
||||||
|
1: Arg,
|
||||||
|
2: EOL,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
/// The name of the UPS device.
|
||||||
|
1: ups_name,
|
||||||
|
}
|
||||||
|
),
|
||||||
|
/// Client asserts master-level access to the `ups_name` device.
|
||||||
|
ExecMaster (
|
||||||
|
{
|
||||||
|
0: Master,
|
||||||
|
1: Arg,
|
||||||
|
2: EOL,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
/// The name of the UPS device.
|
||||||
|
1: ups_name,
|
||||||
|
}
|
||||||
|
),
|
||||||
|
/// Client requests the forced shut-down of the `ups_name` device.
|
||||||
|
ExecForcedShutDown (
|
||||||
|
{
|
||||||
|
0: Fsd,
|
||||||
|
1: Arg,
|
||||||
|
2: EOL,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
/// The name of the UPS device.
|
||||||
|
1: ups_name,
|
||||||
|
}
|
||||||
|
),
|
||||||
|
/// Client sets the password on the connection.
|
||||||
|
SetPassword (
|
||||||
|
{
|
||||||
|
0: Password,
|
||||||
|
1: Arg,
|
||||||
|
2: EOL,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
/// The password to set.
|
||||||
|
1: password,
|
||||||
|
}
|
||||||
|
),
|
||||||
|
/// Client sets the username on the connection.
|
||||||
|
SetUsername (
|
||||||
|
{
|
||||||
|
0: Username,
|
||||||
|
1: Arg,
|
||||||
|
2: EOL,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
/// The username to set.
|
||||||
|
1: username,
|
||||||
|
}
|
||||||
|
),
|
||||||
|
/// Client requests the connection be upgraded to TLS.
|
||||||
|
ExecStartTLS (
|
||||||
|
{
|
||||||
|
0: StartTLS,
|
||||||
|
1: EOL,
|
||||||
|
},
|
||||||
|
{}
|
||||||
|
),
|
||||||
|
/// Client requests the list of commands supported by the server.
|
||||||
|
QueryHelp (
|
||||||
|
{
|
||||||
|
0: Help,
|
||||||
|
1: EOL,
|
||||||
|
},
|
||||||
|
{}
|
||||||
|
),
|
||||||
|
/// Client requests the server version.
|
||||||
|
QueryVersion (
|
||||||
|
{
|
||||||
|
0: Version,
|
||||||
|
1: EOL,
|
||||||
|
},
|
||||||
|
{}
|
||||||
|
),
|
||||||
|
/// Client requests the network version.
|
||||||
|
QueryNetworkVersion (
|
||||||
|
{
|
||||||
|
0: NetworkVersion,
|
||||||
|
1: EOL,
|
||||||
|
},
|
||||||
|
{}
|
||||||
|
),
|
||||||
}
|
}
|
||||||
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO Macro
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
#[test]
|
#[test]
|
||||||
fn test_serverbound_decode() {
|
fn test_decode() {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
server_bound::Sentences::decode(vec!["VERSION".into()]),
|
Sentences::decode(vec!["VERSION".into()]),
|
||||||
Some(server_bound::Sentences::QueryVersion {})
|
Some(Sentences::QueryVersion {})
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
server_bound::Sentences::decode(vec!["LIST".into(), "VAR".into(), "nutdev".into()]),
|
Sentences::decode(vec!["LIST".into(), "VAR".into(), "nutdev".into()]),
|
||||||
Some(server_bound::Sentences::QueryListVar {
|
Some(Sentences::QueryListVar {
|
||||||
ups_name: "nutdev".into()
|
ups_name: "nutdev".into(),
|
||||||
})
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
server_bound::Sentences::decode(vec!["LIST".into(), "RW".into(), "nutdev".into()]),
|
|
||||||
Some(server_bound::Sentences::QueryListRw {
|
|
||||||
ups_name: "nutdev".into()
|
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue