tailtalk_packets/afp/
util.rs1use crate::afp::types::AfpError;
2use encoding_rs::MACINTOSH;
3
4#[derive(Debug, Clone, PartialEq, Eq, Default)]
6pub struct MacString(String);
7
8impl MacString {
9 pub fn new(s: String) -> Self {
10 Self(s)
11 }
12
13 pub fn as_str(&self) -> &str {
14 &self.0
15 }
16
17 pub fn into_string(self) -> String {
18 self.0
19 }
20
21 pub fn bytes(&self, buf: &mut [u8]) -> Result<usize, AfpError> {
24 let (encoded, _, _) = MACINTOSH.encode(&self.0);
25 let len = encoded.len().min(255);
26
27 if buf.len() < 1 + len {
28 return Err(AfpError::InvalidSize);
29 }
30
31 buf[0] = len as u8;
32 buf[1..1 + len].copy_from_slice(&encoded[..len]);
33
34 Ok(1 + len)
35 }
36
37 pub fn byte_len(&self) -> usize {
39 let (encoded, _, _) = MACINTOSH.encode(&self.0);
40 let len = encoded.len().min(255);
41 1 + len
42 }
43}
44
45impl TryFrom<&[u8]> for MacString {
46 type Error = AfpError;
47
48 fn try_from(buf: &[u8]) -> Result<Self, Self::Error> {
52 if buf.is_empty() {
53 return Err(AfpError::InvalidSize);
54 }
55
56 let len = buf[0] as usize;
57 if len == 0 {
58 return Ok(MacString(String::new()));
59 }
60
61 if buf.len() < 1 + len {
62 return Err(AfpError::InvalidSize);
63 }
64
65 let string_data = &buf[1..1 + len];
66 let (decoded, _, _) = MACINTOSH.decode(string_data);
67
68 Ok(MacString(decoded.into_owned()))
69 }
70}
71
72impl AsRef<str> for MacString {
73 fn as_ref(&self) -> &str {
74 &self.0
75 }
76}
77
78impl std::ops::Deref for MacString {
79 type Target = str;
80
81 fn deref(&self) -> &Self::Target {
82 &self.0
83 }
84}
85
86impl From<String> for MacString {
87 fn from(s: String) -> Self {
88 Self(s)
89 }
90}
91
92impl From<&str> for MacString {
93 fn from(s: &str) -> Self {
94 Self(s.to_string())
95 }
96}
97
98impl AsRef<std::ffi::OsStr> for MacString {
99 fn as_ref(&self) -> &std::ffi::OsStr {
100 std::ffi::OsStr::new(&self.0)
101 }
102}
103
104impl std::fmt::Display for MacString {
105 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
106 write!(f, "{}", self.0)
107 }
108}