You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
distant/distant-net/src/server/config.rs

108 lines
3.3 KiB
Rust

use derive_more::{Display, Error};
use serde::{Deserialize, Serialize};
use std::{num::ParseFloatError, str::FromStr, time::Duration};
const DEFAULT_CONNECTION_SLEEP: Duration = Duration::from_millis(1);
const DEFAULT_HEARTBEAT_DURATION: Duration = Duration::from_secs(5);
/// Represents a general-purpose set of properties tied with a server instance
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub struct ServerConfig {
/// Time to wait inbetween connection read/write when nothing was read or written on last pass
pub connection_sleep: Duration,
/// Minimum time to wait inbetween sending heartbeat messages
pub connection_heartbeat: Duration,
/// Rules for how a server will shutdown automatically
pub shutdown: Shutdown,
}
impl Default for ServerConfig {
fn default() -> Self {
Self {
connection_sleep: DEFAULT_CONNECTION_SLEEP,
connection_heartbeat: DEFAULT_HEARTBEAT_DURATION,
shutdown: Default::default(),
}
}
}
/// Rules for how a server will shut itself down automatically
#[derive(Copy, Clone, Debug, Display, PartialEq, Eq, Serialize, Deserialize)]
pub enum Shutdown {
/// Server should shutdown immediately after duration exceeded
#[display(fmt = "after={}", "_0.as_secs_f32()")]
After(Duration),
/// Server should shutdown after no connections for over duration time
#[display(fmt = "lonely={}", "_0.as_secs_f32()")]
Lonely(Duration),
/// No shutdown logic will be applied to the server
#[display(fmt = "never")]
Never,
}
impl Shutdown {
/// Return duration associated with shutdown if it has one
pub fn duration(&self) -> Option<Duration> {
match self {
Self::Never => None,
Self::After(x) | Self::Lonely(x) => Some(*x),
}
}
}
impl Default for Shutdown {
/// By default, shutdown is never
fn default() -> Self {
Self::Never
}
}
/// Parsing errors that can occur for [`Shutdown`]
#[derive(Clone, Debug, Display, Error, PartialEq, Eq)]
pub enum ShutdownParseError {
#[display(fmt = "Bad value for after: {}", _0)]
BadValueForAfter(ParseFloatError),
#[display(fmt = "Bad value for lonely: {}", _0)]
BadValueForLonely(ParseFloatError),
#[display(fmt = "Missing key")]
MissingKey,
#[display(fmt = "Unknown key")]
UnknownKey,
}
impl FromStr for Shutdown {
type Err = ShutdownParseError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
if s.eq_ignore_ascii_case("never") {
Ok(Self::Never)
} else {
let (left, right) = s.split_once('=').ok_or(ShutdownParseError::MissingKey)?;
let left = left.trim();
let right = right.trim();
if left.eq_ignore_ascii_case("after") {
Ok(Self::After(Duration::from_secs_f32(
right
.parse()
.map_err(ShutdownParseError::BadValueForAfter)?,
)))
} else if left.eq_ignore_ascii_case("lonely") {
Ok(Self::Lonely(Duration::from_secs_f32(
right
.parse()
.map_err(ShutdownParseError::BadValueForLonely)?,
)))
} else {
Err(ShutdownParseError::UnknownKey)
}
}
}
}