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 WellKnownName<'name>(pub(crate) Str<'name>);
#[derive(Clone, Hash, PartialEq, Eq, Serialize, Type, Value, PartialOrd, Ord, OwnedValue)]
pub struct OwnedWellKnownName(#[serde(borrow)] WellKnownName<'static>);
define_name_type_impls! {
name: WellKnownName,
owned: OwnedWellKnownName,
validate: validate,
}
fn validate(name: &str) -> Result<()> {
validate_bytes(name.as_bytes()).map_err(|_| {
Error::InvalidName(
"Invalid well-known 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::separated,
stream::AsChar,
token::{one_of, take_while},
};
let first_element_char = one_of((AsChar::is_alpha, b'_', b'-'));
let subsequent_element_chars = take_while::<_, _, ()>(0.., (AsChar::is_alphanum, b'_', b'-'));
let element = (first_element_char, subsequent_element_chars);
let mut well_known_name = separated(2.., element, b'.');
well_known_name
.parse(bytes)
.map_err(|_| ())
.and_then(|_: ()| {
if bytes.len() > 255 {
return Err(());
}
Ok(())
})
}