storefd/src/notify/types.rs

135 lines
3.2 KiB
Rust

//! Newtypes used by [`NotifyState`](super::NotifyState)
use super::error;
/// Allowed File descriptor name.
///
/// A name is allowed when it :
///
/// * Has less than 255 characters.
/// * Is ASCII.
/// * Doesn't contains control characters.
/// * Doesn't contains a colon (`:`).
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct FdName<'a>(pub(super) &'a str);
impl<'a> TryFrom<&'a str> for FdName<'a> {
type Error = error::FdNameError;
fn try_from(name: &'a str) -> Result<Self, Self::Error> {
if name.len() > 255 {
return Err(error::FdNameError::TooLong {
length: name.len(),
name: name.into(),
});
}
for c in name.chars() {
if !c.is_ascii() || c.is_ascii_control() {
return Err(error::FdNameError::NotAsciiNonControl {
disallowed_char: c,
name: name.into(),
});
}
if c == ':' {
return Err(error::FdNameError::ContainColon(name.into()));
}
}
Ok(Self(name))
}
}
impl AsRef<str> for FdName<'_> {
fn as_ref(&self) -> &str {
self.0
}
}
/// A status line for [`NotifyState::Status`](super::NotifyState::Status).
///
/// As the name explains it needs to be a single line.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct StatusLine<'a>(pub(super) &'a str);
impl<'a> TryFrom<&'a str> for StatusLine<'a> {
type Error = error::StatusLineError;
fn try_from(value: &'a str) -> Result<Self, Self::Error> {
if value.lines().nth(1).is_some() {
return Err(Self::Error::TooManyLines);
}
Ok(Self(value))
}
}
impl AsRef<str> for StatusLine<'_> {
fn as_ref(&self) -> &str {
self.0
}
}
/// Semantic type representing a number of microseconds.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct Microseconds(pub(super) u64);
impl From<u64> for Microseconds {
fn from(value: u64) -> Self {
Self(value)
}
}
impl AsRef<u64> for Microseconds {
fn as_ref(&self) -> &u64 {
&self.0
}
}
/// A D-Bus error-style error code.
///
/// Right now it doesn't impose any additional constraint on [`str`]
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct BusError<'a>(pub(super) &'a str);
impl<'a> From<&'a str> for BusError<'a> {
fn from(value: &'a str) -> Self {
Self(value)
}
}
impl AsRef<str> for BusError<'_> {
fn as_ref(&self) -> &str {
self.0
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct OtherState<'a>(pub(super) &'a str);
impl<'a> TryFrom<&'a str> for OtherState<'a> {
type Error = error::OtherStateError;
fn try_from(value: &'a str) -> Result<Self, Self::Error> {
if value.contains('\n') {
return Err(Self::Error::TooManyLines);
}
if !value.contains('=') {
return Err(Self::Error::NoAssignement);
}
if value == "BARRIER=1" {
return Err(Self::Error::DisallowedState(String::from(value)));
}
Ok(Self(value))
}
}
impl AsRef<str> for OtherState<'_> {
fn as_ref(&self) -> &str {
self.0
}
}