saorsa_core/messaging/
user_handle.rs1use serde::{Deserialize, Serialize};
2use std::fmt;
3use std::hash::{Hash, Hasher};
4
5#[derive(Clone, Eq, Serialize, Deserialize)]
8pub struct UserHandle(String);
9
10impl UserHandle {
11 pub fn new<S: Into<String>>(s: S) -> Result<Self, String> {
13 let v = s.into().trim().to_string();
14 if v.is_empty() {
15 return Err("handle cannot be empty".to_string());
16 }
17 if v.len() > 64 {
18 return Err("handle too long (max 64)".to_string());
19 }
20 if v.chars().any(|c| c.is_control()) {
21 return Err("handle contains control characters".to_string());
22 }
23 Ok(UserHandle(v))
24 }
25
26 pub fn as_str(&self) -> &str {
27 &self.0
28 }
29}
30
31impl From<&str> for UserHandle {
32 fn from(s: &str) -> Self {
33 UserHandle(s.trim().to_string())
34 }
35}
36
37impl From<String> for UserHandle {
38 fn from(s: String) -> Self {
39 UserHandle(s.trim().to_string())
40 }
41}
42
43impl fmt::Debug for UserHandle {
44 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
45 write!(f, "UserHandle({})", self.0)
46 }
47}
48
49impl fmt::Display for UserHandle {
50 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
51 write!(f, "{}", self.0)
52 }
53}
54
55impl PartialEq for UserHandle {
56 fn eq(&self, other: &Self) -> bool {
57 self.0.eq(&other.0)
58 }
59}
60
61impl Hash for UserHandle {
62 fn hash<H: Hasher>(&self, state: &mut H) {
63 self.0.hash(state)
64 }
65}