system_info/data/
host.rs

1const MAX_SIZE: usize = 255;
2
3use core::{hash, fmt, cmp};
4
5#[derive(Clone)]
6///Host name, limited to 255 characters.
7///
8///Commonly it is valid utf-8 string, but due to potential encoding differences, it is possible
9///that name cannot be interpreted as utf-8 string.
10///In this case  user is encouraged to use `as_bytes` method and perform conversion by himself.
11///
12///## fmt
13///
14///- `Debug` trait outputs byte content.
15///
16///- `Display` trait outputs content as string, if possible, otherwise fallbacks to byte slice.
17pub struct HostName {
18    name: [u8; MAX_SIZE]
19}
20
21impl HostName {
22    #[inline(always)]
23    ///Creates new empty string name
24    pub const fn new() -> Self {
25        Self {
26            name: [0; MAX_SIZE]
27        }
28    }
29
30    #[inline(always)]
31    ///Returns host name size limit.
32    pub const fn capacity() -> usize {
33        MAX_SIZE
34    }
35
36    #[inline(always)]
37    ///Initializes name from buffer.
38    pub const fn name(name: [u8; MAX_SIZE]) -> Self {
39        Self {
40            name
41        }
42    }
43
44    #[inline]
45    ///Returns name as byte slice
46    pub fn as_bytes(&self) -> &[u8] {
47        let mut idx = 0;
48        while idx < self.name.len() {
49            if self.name[idx] == 0 {
50                return &self.name[..idx]
51            }
52            idx += 1;
53        }
54
55        self.name.as_slice()
56    }
57
58    #[inline]
59    ///Returns name as string, checking whether it is valid utf-8 before.
60    ///
61    ///In case of underlying name not to be valid string, returns byte slice with content.
62    ///
63    ///On windows it never fails.
64    pub fn as_str(&self) -> Result<&str, &[u8]> {
65        #[cold]
66        #[inline(never)]
67        fn fail<T>(res: T) -> T {
68            res
69        }
70
71        let bytes = self.as_bytes();
72        match core::str::from_utf8(bytes) {
73            Ok(res) => Ok(res),
74            Err(_) => fail(Err(bytes)),
75        }
76    }
77}
78
79impl AsRef<[u8]> for HostName {
80    #[inline(always)]
81    fn as_ref(&self) -> &[u8] {
82        self.as_bytes()
83    }
84}
85
86impl core::borrow::Borrow<[u8]> for HostName {
87    #[inline(always)]
88    fn borrow(&self) -> &[u8] {
89        self.as_bytes()
90    }
91}
92
93impl Eq for HostName {}
94
95impl PartialEq<HostName> for HostName {
96    #[inline(always)]
97    fn eq(&self, other: &Self) -> bool {
98        self.as_bytes() == other.as_bytes()
99    }
100}
101
102impl PartialEq<HostName> for &str {
103    #[inline(always)]
104    fn eq(&self, other: &HostName) -> bool {
105        self.as_bytes() == other.as_bytes()
106    }
107}
108
109impl PartialEq<HostName> for str {
110    #[inline(always)]
111    fn eq(&self, other: &HostName) -> bool {
112        self.as_bytes() == other.as_bytes()
113    }
114}
115
116impl PartialEq<HostName> for &[u8] {
117    #[inline(always)]
118    fn eq(&self, other: &HostName) -> bool {
119        *self == other.as_bytes()
120    }
121}
122
123impl PartialEq<HostName> for [u8] {
124    #[inline(always)]
125    fn eq(&self, other: &HostName) -> bool {
126        self == other.as_bytes()
127    }
128}
129
130impl PartialEq<str> for HostName {
131    #[inline(always)]
132    fn eq(&self, other: &str) -> bool {
133        self.as_bytes() == other.as_bytes()
134    }
135}
136
137impl PartialEq<&str> for HostName {
138    #[inline(always)]
139    fn eq(&self, other: &&str) -> bool {
140        self.as_bytes() == other.as_bytes()
141    }
142}
143
144impl PartialEq<[u8]> for HostName {
145    #[inline(always)]
146    fn eq(&self, other: &[u8]) -> bool {
147        self.as_bytes() == other
148    }
149}
150
151impl PartialEq<&[u8]> for HostName {
152    #[inline(always)]
153    fn eq(&self, other: &&[u8]) -> bool {
154        self.as_bytes() == *other
155    }
156}
157
158impl cmp::Ord for HostName {
159    fn cmp(&self, other: &Self) -> cmp::Ordering {
160        self.as_bytes().cmp(other.as_bytes())
161    }
162}
163
164impl PartialOrd for HostName {
165    fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
166        Some(self.cmp(other))
167    }
168}
169
170impl hash::Hash for HostName {
171    fn hash<H: hash::Hasher>(&self, hasher: &mut H) {
172        self.as_bytes().hash(hasher)
173    }
174}
175
176impl fmt::Debug for HostName {
177    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
178        fmt::Debug::fmt(&self.as_bytes(), fmt)
179    }
180}
181
182impl fmt::Display for HostName {
183    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
184        match self.as_str() {
185            Ok(name) => fmt.write_str(name),
186            Err(bytes) => fmt::Debug::fmt(bytes, fmt)
187        }
188    }
189}