use moq_net::{AsPath, Path, PathOwned};
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub enum Kind {
Camera,
Screen,
}
impl Kind {
pub const fn as_str(self) -> &'static str {
match self {
Self::Camera => "camera",
Self::Screen => "screen",
}
}
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct Parsed {
pub identity: PathOwned,
pub kind: Kind,
}
pub fn kind_from_segment(segment: &str) -> Option<Kind> {
let kind = segment.strip_suffix(".hang").unwrap_or(segment);
match kind {
"camera" => Some(Kind::Camera),
"screen" => Some(Kind::Screen),
_ => None,
}
}
pub fn parse(path: impl AsPath) -> Option<Parsed> {
let path = path.as_path();
let mut parts: Vec<&str> = path.parts().collect();
let last = parts.pop()?;
if parts.is_empty() {
return None;
}
let kind = kind_from_segment(last)?;
let identity = Path::new(&parts.join("/")).to_owned();
Some(Parsed { identity, kind })
}
pub fn broadcast_path(identity: impl AsPath, kind: Kind) -> PathOwned {
identity.as_path().join(format!("{}.hang", kind.as_str()))
}
#[cfg(test)]
mod tests {
use super::*;
fn p(s: &str) -> PathOwned {
Path::new(s).to_owned()
}
#[test]
fn parse_splits_identity_and_kind() {
assert_eq!(
parse(Path::new("alice/camera")),
Some(Parsed {
identity: p("alice"),
kind: Kind::Camera
})
);
assert_eq!(
parse(Path::new("alice/screen")),
Some(Parsed {
identity: p("alice"),
kind: Kind::Screen
})
);
}
#[test]
fn parse_accepts_hang_suffix() {
assert_eq!(
parse(Path::new("alice/camera.hang")).map(|p| p.kind),
Some(Kind::Camera)
);
assert_eq!(
parse(Path::new("alice/screen.hang")).map(|p| p.kind),
Some(Kind::Screen)
);
}
#[test]
fn parse_keeps_multi_segment_identity() {
assert_eq!(
parse(Path::new("guest/uuid/camera")),
Some(Parsed {
identity: p("guest/uuid"),
kind: Kind::Camera
})
);
}
#[test]
fn parse_rejects_unknown() {
assert_eq!(parse(Path::new("alice")), None);
assert_eq!(parse(Path::new("alice/chat")), None);
assert_eq!(parse(Path::new("camera")), None);
assert_eq!(parse(Path::empty()), None);
}
#[test]
fn broadcast_path_joins_with_hang_suffix() {
assert_eq!(broadcast_path(p("alice"), Kind::Camera).as_str(), "alice/camera.hang");
assert_eq!(
broadcast_path(p("guest/uuid"), Kind::Screen).as_str(),
"guest/uuid/screen.hang"
);
}
}