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 UniqueName<'name>(pub(crate) Str<'name>);
#[derive(Clone, Hash, PartialEq, Eq, Serialize, Type, Value, PartialOrd, Ord, OwnedValue)]
pub struct OwnedUniqueName(#[serde(borrow)] UniqueName<'static>);
define_name_type_impls! {
name: UniqueName,
owned: OwnedUniqueName,
validate: validate,
}
fn validate(name: &str) -> Result<()> {
validate_bytes(name.as_bytes()).map_err(|_| {
Error::InvalidName(
"Invalid unique name. \
See https://dbus.freedesktop.org/doc/dbus-specification.html#message-protocol-names-bus"
)
})
}
pub(crate) fn validate_bytes(bytes: &[u8]) -> std::result::Result<(), ()> {
use winnow::{
Parser,
combinator::{alt, separated},
stream::AsChar,
token::take_while,
};
let element = take_while::<_, _, ()>(1.., (AsChar::is_alphanum, b'_', b'-'));
let peer_name = (b':', (separated(2.., element, b'.'))).map(|_: (_, ())| ());
let bus_name = b"org.freedesktop.DBus".map(|_| ());
let mut unique_name = alt((bus_name, peer_name));
unique_name.parse(bytes).map_err(|_| ()).and_then(|_: ()| {
if bytes.len() > 255 {
return Err(());
}
Ok(())
})
}