mgr: Add sleep action
This commit is contained in:
@@ -8,6 +8,10 @@ pub enum ParseError {
|
||||
UnknownAction { action: String },
|
||||
#[error("unexpected input: {rest:?}")]
|
||||
UnexpectedInput { rest: Vec<String> },
|
||||
#[error("missing argument")]
|
||||
MissingArgument,
|
||||
#[error("error parsing argument: {message}")]
|
||||
ArgumentParse { message: String },
|
||||
}
|
||||
|
||||
pub trait CliCommand {
|
||||
|
||||
@@ -11,6 +11,7 @@ pub mod power;
|
||||
pub mod present;
|
||||
pub(crate) mod pulseaudio;
|
||||
pub(crate) mod redshift;
|
||||
pub(crate) mod sleep;
|
||||
pub(crate) mod spotify;
|
||||
pub(crate) mod systemd;
|
||||
pub(crate) mod theme;
|
||||
@@ -36,6 +37,8 @@ pub enum ExecError {
|
||||
#[error(transparent)]
|
||||
Brightness(#[from] brightness::Error),
|
||||
#[error(transparent)]
|
||||
Sleep(#[from] sleep::Error),
|
||||
#[error(transparent)]
|
||||
Parse(#[from] cli::ParseError),
|
||||
}
|
||||
|
||||
@@ -49,6 +52,7 @@ pub enum Action {
|
||||
Redshift(redshift::Action),
|
||||
Weather(weather::Action),
|
||||
Brightness(brightness::Action),
|
||||
Sleep(sleep::Action),
|
||||
}
|
||||
|
||||
impl wire::WireCommand for Action {
|
||||
@@ -62,6 +66,7 @@ impl wire::WireCommand for Action {
|
||||
0x06 => Ok(Self::Redshift(redshift::Action::parse_wire(input)?)),
|
||||
0x07 => Ok(Self::Weather(weather::Action::parse_wire(input)?)),
|
||||
0x08 => Ok(Self::Brightness(brightness::Action::parse_wire(input)?)),
|
||||
0x09 => Ok(Self::Sleep(sleep::Action::parse_wire(input)?)),
|
||||
other => Err(wire::server::ParseError::Unknown(other)),
|
||||
}
|
||||
}
|
||||
@@ -108,6 +113,11 @@ impl wire::WireCommand for Action {
|
||||
v.extend_from_slice(&action.to_wire());
|
||||
v
|
||||
}
|
||||
Self::Sleep(action) => {
|
||||
let mut v = vec![0x09];
|
||||
v.extend_from_slice(&action.to_wire());
|
||||
v
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -159,6 +169,10 @@ impl cli::CliCommand for Action {
|
||||
&choice, rest,
|
||||
)?))
|
||||
}
|
||||
"sleep" => {
|
||||
let choice = rest.next().ok_or(cli::ParseError::MissingAction)?;
|
||||
Ok(Self::Sleep(sleep::Action::parse_str(&choice, rest)?))
|
||||
}
|
||||
s => Err(cli::ParseError::UnknownAction {
|
||||
action: s.to_owned(),
|
||||
}),
|
||||
@@ -185,6 +199,7 @@ impl Exec for Action {
|
||||
Self::Redshift(action) => Ok(action.execute()?),
|
||||
Self::Weather(action) => Ok(action.execute()?),
|
||||
Self::Brightness(action) => Ok(action.execute()?),
|
||||
Self::Sleep(action) => Ok(action.execute()?),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
104
mgr/src/sleep.rs
Normal file
104
mgr/src/sleep.rs
Normal file
@@ -0,0 +1,104 @@
|
||||
use super::{
|
||||
Exec,
|
||||
cli::{self, CliCommand},
|
||||
cmd,
|
||||
wire::{WireCommand, server},
|
||||
};
|
||||
|
||||
use thiserror::Error;
|
||||
|
||||
#[derive(Error, Debug)]
|
||||
pub enum Error {
|
||||
#[error(transparent)]
|
||||
Cmd(#[from] cmd::Error),
|
||||
#[error(transparent)]
|
||||
Cli(#[from] cli::ParseError),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub enum Action {
|
||||
Sleep(std::time::Duration),
|
||||
}
|
||||
|
||||
impl WireCommand for Action {
|
||||
fn parse_wire(mut input: impl Iterator<Item = u8>) -> Result<Self, server::ParseError> {
|
||||
match input.next().ok_or(server::ParseError::Eof)? {
|
||||
0x01 => {
|
||||
const BYTES: usize = (u64::BITS / 8) as usize;
|
||||
let input = input.take(BYTES).collect::<Vec<u8>>();
|
||||
let input: [u8; BYTES] =
|
||||
input
|
||||
.try_into()
|
||||
.map_err(|vec: Vec<u8>| server::ParseError::MissingBytes {
|
||||
expected: BYTES,
|
||||
received: vec.len(),
|
||||
})?;
|
||||
|
||||
let secs = u64::from_le_bytes(input);
|
||||
let duration = std::time::Duration::from_secs(secs);
|
||||
Ok(Self::Sleep(duration))
|
||||
}
|
||||
byte => Err(server::ParseError::Unknown(byte)),
|
||||
}
|
||||
}
|
||||
|
||||
fn to_wire(&self) -> Vec<u8> {
|
||||
match *self {
|
||||
Self::Sleep(duration) => {
|
||||
let mut v = vec![0x01];
|
||||
v.extend(duration.as_secs().to_le_bytes());
|
||||
v
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Exec for Action {
|
||||
type ExecErr = Error;
|
||||
|
||||
fn execute(&self) -> Result<Option<String>, Self::ExecErr> {
|
||||
match *self {
|
||||
Self::Sleep(duration) => {
|
||||
std::thread::sleep(duration);
|
||||
Ok(None)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl CliCommand for Action {
|
||||
type ExecErr = Error;
|
||||
|
||||
fn parse_str(
|
||||
input: &str,
|
||||
mut rest: impl Iterator<Item = String>,
|
||||
) -> Result<Self, cli::ParseError>
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
let result = match input {
|
||||
"sleep" => {
|
||||
let input = rest.next().ok_or(cli::ParseError::MissingArgument)?;
|
||||
let seconds =
|
||||
input
|
||||
.parse::<u64>()
|
||||
.map_err(|err| cli::ParseError::ArgumentParse {
|
||||
message: err.to_string(),
|
||||
})?;
|
||||
Self::Sleep(std::time::Duration::from_secs(seconds))
|
||||
}
|
||||
s => {
|
||||
return Err(cli::ParseError::UnknownAction {
|
||||
action: s.to_owned(),
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
let rest = rest.collect::<Vec<String>>();
|
||||
if rest.is_empty() {
|
||||
Ok(result)
|
||||
} else {
|
||||
Err(cli::ParseError::UnexpectedInput { rest })
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -32,6 +32,8 @@ pub enum ParseError {
|
||||
Unknown(u8),
|
||||
#[error("received surplus input: {0:?}")]
|
||||
Surplus(Vec<u8>),
|
||||
#[error("expected {expected} bytes, received only {received}")]
|
||||
MissingBytes { expected: usize, received: usize },
|
||||
}
|
||||
|
||||
fn handle_client(stream: &mut UnixStream) -> Result<(), Error> {
|
||||
|
||||
Reference in New Issue
Block a user