use crate::{Error, Result, utils::define_name_type_impls};
use serde::Serialize;
use zvariant::{OwnedValue, Str, Type, Value};
#[derive(
Clone, Debug, Hash, PartialEq, Eq, Serialize, Type, Value, PartialOrd, Ord, OwnedValue,
)]
pub struct InterfaceName<'name>(Str<'name>);
#[derive(Clone, Hash, PartialEq, Eq, Serialize, Type, Value, PartialOrd, Ord, OwnedValue)]
pub struct OwnedInterfaceName(#[serde(borrow)] InterfaceName<'static>);
define_name_type_impls! {
name: InterfaceName,
owned: OwnedInterfaceName,
validate: validate,
}
fn validate(name: &str) -> Result<()> {
validate_bytes(name.as_bytes()).map_err(|_| {
Error::InvalidName(
"Invalid interface name. See \
https://dbus.freedesktop.org/doc/dbus-specification.html#message-protocol-names-interface"
)
})
}
pub(crate) fn validate_bytes(bytes: &[u8]) -> std::result::Result<(), ()> {
use winnow::{
Parser,
combinator::separated,
stream::AsChar,
token::{one_of, take_while},
};
let first_element_char = one_of((AsChar::is_alpha, b'_'));
let subsequent_element_chars = take_while::<_, _, ()>(0.., (AsChar::is_alphanum, b'_'));
let element = (first_element_char, subsequent_element_chars);
let mut interface_name = separated(2.., element, b'.');
interface_name
.parse(bytes)
.map_err(|_| ())
.and_then(|_: ()| {
if bytes.len() > 255 {
return Err(());
}
Ok(())
})
}