liminal_server/server/connection/
declared_holder.rs1pub const PREFIX: &str = "open:";
13
14pub const ANONYMOUS: &str = "anonymous";
16
17#[derive(Debug, Clone, PartialEq, Eq)]
19pub enum DeclaredHolder {
20 Open(String),
22}
23
24impl DeclaredHolder {
25 #[must_use]
29 pub fn from_record(record: &[u8]) -> Self {
30 let name = std::str::from_utf8(record)
31 .ok()
32 .and_then(|text| text.strip_prefix(PREFIX))
33 .filter(|name| is_name(name));
34 Self::Open(name.unwrap_or(ANONYMOUS).to_owned())
35 }
36
37 #[must_use]
39 pub fn name(&self) -> &str {
40 match self {
41 Self::Open(name) => name,
42 }
43 }
44
45 #[must_use]
47 pub fn record(&self) -> String {
48 match self {
49 Self::Open(name) => format!("{PREFIX}{name}"),
50 }
51 }
52}
53
54#[must_use]
56pub fn is_name(name: &str) -> bool {
57 (1..=64).contains(&name.len())
58 && name.bytes().all(|b| {
59 b.is_ascii_lowercase() || b.is_ascii_digit() || matches!(b, b'.' | b'_' | b'-')
60 })
61}
62
63#[cfg(test)]
64mod tests {
65 use super::{DeclaredHolder, is_name};
66
67 #[test]
68 fn a_record_names_its_holder_or_is_anonymous() {
69 assert_eq!(
70 DeclaredHolder::from_record(b"open:hermes").record(),
71 "open:hermes"
72 );
73 for record in [
74 &b""[..],
75 b"open:",
76 b"open:Hermes",
77 b"hermes",
78 b"\xff",
79 b"open:a b",
80 ] {
81 assert_eq!(
82 DeclaredHolder::from_record(record).record(),
83 "open:anonymous",
84 "{record:?}"
85 );
86 }
87 }
88
89 #[test]
90 fn a_name_is_one_to_sixty_four_of_the_allowed_bytes() {
91 assert!(is_name("hermes") && is_name("a.b_c-d9") && is_name(&"x".repeat(64)));
92 assert!(!is_name("") && !is_name("Hermes") && !is_name("a/b") && !is_name(&"x".repeat(65)));
93 }
94}