Implement rupsc, clone of upsc (#5)

Fixes #4
This commit is contained in:
Aram Peres 2021-07-31 04:18:39 -04:00 committed by GitHub
parent 43121ce2ea
commit 8556a7ca0e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
16 changed files with 676 additions and 82 deletions

View file

@ -1,9 +1,10 @@
use core::fmt;
use crate::NutError;
use crate::{ClientError, NutError};
#[derive(Debug, Clone)]
pub enum Command<'a> {
Get(&'a [&'a str]),
/// Passes the login username.
SetUsername(&'a str),
/// Passes the login password.
@ -16,6 +17,7 @@ impl<'a> Command<'a> {
/// The network identifier of the command.
pub fn name(&self) -> &'static str {
match self {
Self::Get(_) => "GET",
Self::SetUsername(_) => "USERNAME",
Self::SetPassword(_) => "PASSWORD",
Self::List(_) => "LIST",
@ -25,6 +27,7 @@ impl<'a> Command<'a> {
/// The arguments of the command to serialize.
pub fn args(&self) -> Vec<&str> {
match self {
Self::Get(cmd) => cmd.to_vec(),
Self::SetUsername(username) => vec![username],
Self::SetPassword(password) => vec![password],
Self::List(query) => query.to_vec(),
@ -48,6 +51,18 @@ pub enum Response {
BeginList(String),
/// Marks the end of a list response.
EndList(String),
/// A variable (VAR) response.
///
/// Params: (var name, var value)
Var(String, String),
/// A UPS (UPS) response.
///
/// Params: (device name, device description)
Ups(String, String),
/// A client (CLIENT) response.
///
/// Params: (client IP)
Client(String),
}
impl Response {
@ -109,6 +124,64 @@ impl Response {
}
}
}
"VAR" => {
let _var_device = if args.is_empty() {
Err(ClientError::from(NutError::Generic(
"Unspecified VAR device name in response".into(),
)))
} else {
Ok(args.remove(0))
}?;
let var_name = if args.is_empty() {
Err(ClientError::from(NutError::Generic(
"Unspecified VAR name in response".into(),
)))
} else {
Ok(args.remove(0))
}?;
let var_value = if args.is_empty() {
Err(ClientError::from(NutError::Generic(
"Unspecified VAR value in response".into(),
)))
} else {
Ok(args.remove(0))
}?;
Ok(Response::Var(var_name, var_value))
}
"UPS" => {
let name = if args.is_empty() {
Err(ClientError::from(NutError::Generic(
"Unspecified UPS name in response".into(),
)))
} else {
Ok(args.remove(0))
}?;
let description = if args.is_empty() {
Err(ClientError::from(NutError::Generic(
"Unspecified UPS description in response".into(),
)))
} else {
Ok(args.remove(0))
}?;
Ok(Response::Ups(name, description))
}
"CLIENT" => {
let _device = if args.is_empty() {
Err(ClientError::from(NutError::Generic(
"Unspecified CLIENT device in response".into(),
)))
} else {
Ok(args.remove(0))
}?;
let ip_address = if args.is_empty() {
Err(ClientError::from(NutError::Generic(
"Unspecified CLIENT IP in response".into(),
)))
} else {
Ok(args.remove(0))
}?;
Ok(Response::Client(ip_address))
}
_ => Err(NutError::UnknownResponseType(cmd_name).into()),
}
}
@ -133,14 +206,25 @@ impl Response {
}
}
pub fn expect_end_list(self, expected_args: &[&str]) -> crate::Result<Response> {
let expected_args = shell_words::join(expected_args);
if let Self::EndList(args) = &self {
if &expected_args == args {
Ok(self)
} else {
Err(NutError::UnexpectedResponse.into())
}
pub fn expect_var(&self) -> crate::Result<(String, String)> {
if let Self::Var(name, value) = &self {
Ok((name.to_owned(), value.to_owned()))
} else {
Err(NutError::UnexpectedResponse.into())
}
}
pub fn expect_ups(&self) -> crate::Result<(String, String)> {
if let Self::Ups(name, description) = &self {
Ok((name.to_owned(), description.to_owned()))
} else {
Err(NutError::UnexpectedResponse.into())
}
}
pub fn expect_client(&self) -> crate::Result<String> {
if let Self::Client(client_ip) = &self {
Ok(client_ip.to_owned())
} else {
Err(NutError::UnexpectedResponse.into())
}