//! 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 { 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 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 { if value.lines().nth(1).is_some() { return Err(Self::Error::TooManyLines); } Ok(Self(value)) } } impl AsRef 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 for Microseconds { fn from(value: u64) -> Self { Self(value) } } impl AsRef 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 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 { 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 for OtherState<'_> { fn as_ref(&self) -> &str { self.0 } }