roboplc_io_ads/
strings.rs1#[repr(C)]
13#[derive(Clone, Copy)]
14pub struct String<const LEN: usize>([u8; LEN], u8); impl<const LEN: usize> String<LEN> {
17 pub fn new() -> Self {
19 Self([0; LEN], 0)
20 }
21
22 pub fn len(&self) -> usize {
24 self.0.iter().position(|&b| b == 0).unwrap_or(self.0.len())
25 }
26
27 pub fn is_empty(&self) -> bool {
28 self.0[0] == 0
29 }
30
31 pub fn as_bytes(&self) -> &[u8] {
33 &self.0[..self.len()]
34 }
35
36 pub fn backing_array(&mut self) -> &mut [u8; LEN] {
38 &mut self.0
39 }
40}
41
42impl<const LEN: usize> std::default::Default for String<LEN> {
45 fn default() -> Self {
46 Self::new()
47 }
48}
49
50impl<const LEN: usize> std::fmt::Debug for String<LEN> {
51 fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {
52 std::fmt::Debug::fmt(&std::string::String::from_utf8_lossy(self.as_bytes()), fmt)
53 }
54}
55
56impl<const LEN: usize> std::cmp::PartialEq for String<LEN> {
57 fn eq(&self, other: &Self) -> bool {
58 self.as_bytes() == other.as_bytes()
59 }
60}
61
62impl<const LEN: usize> std::cmp::PartialEq<&[u8]> for String<LEN> {
63 fn eq(&self, other: &&[u8]) -> bool {
64 self.as_bytes() == *other
65 }
66}
67
68impl<const LEN: usize> std::cmp::PartialEq<&str> for String<LEN> {
69 fn eq(&self, other: &&str) -> bool {
70 self.as_bytes() == other.as_bytes()
71 }
72}
73
74impl<const LEN: usize> std::convert::From<[u8; LEN]> for String<LEN> {
77 fn from(arr: [u8; LEN]) -> Self {
78 Self(arr, 0)
79 }
80}
81
82impl<const LEN: usize> std::convert::From<String<LEN>> for [u8; LEN] {
83 fn from(bstr: String<LEN>) -> Self {
84 bstr.0
85 }
86}
87
88impl<const LEN: usize> std::convert::TryFrom<&'_ [u8]> for String<LEN> {
91 type Error = ();
92 fn try_from(arr: &[u8]) -> std::result::Result<Self, ()> {
93 if arr.len() > LEN {
94 return Err(());
95 }
96 let mut bstr = Self::new();
97 bstr.0[..arr.len()].copy_from_slice(arr);
98 Ok(bstr)
99 }
100}
101
102impl<const LEN: usize> std::convert::From<String<LEN>> for std::vec::Vec<u8> {
103 fn from(bstr: String<LEN>) -> Self {
104 bstr.as_bytes().to_vec()
105 }
106}
107
108impl<const LEN: usize> std::convert::TryFrom<&'_ str> for String<LEN> {
111 type Error = ();
112 fn try_from(s: &str) -> std::result::Result<Self, ()> {
113 Self::try_from(s.as_bytes())
114 }
115}
116
117impl<const LEN: usize> std::convert::TryFrom<String<LEN>> for std::string::String {
118 type Error = std::str::Utf8Error;
119 fn try_from(bstr: String<LEN>) -> std::result::Result<Self, Self::Error> {
120 std::str::from_utf8(bstr.as_bytes()).map(Into::into)
121 }
122}
123
124unsafe impl<const LEN: usize> zerocopy::AsBytes for String<LEN> {
127 fn only_derive_is_allowed_to_implement_this_trait() {}
128}
129
130unsafe impl<const LEN: usize> zerocopy::FromBytes for String<LEN> {
131 fn only_derive_is_allowed_to_implement_this_trait() {}
132}
133
134#[repr(C)]
146#[derive(Clone, Copy)]
147pub struct WString<const LEN: usize>([u16; LEN], u16); impl<const LEN: usize> WString<LEN> {
150 pub fn new() -> Self {
152 Self([0; LEN], 0)
153 }
154
155 pub fn len(&self) -> usize {
157 self.0.iter().position(|&b| b == 0).unwrap_or(self.0.len())
158 }
159
160 pub fn is_empty(&self) -> bool {
161 self.0[0] == 0
162 }
163
164 pub fn as_slice(&self) -> &[u16] {
166 &self.0[..self.len()]
167 }
168
169 pub fn backing_array(&mut self) -> &mut [u16; LEN] {
171 &mut self.0
172 }
173}
174
175impl<const LEN: usize> std::default::Default for WString<LEN> {
176 fn default() -> Self {
177 Self::new()
178 }
179}
180
181impl<const LEN: usize> std::fmt::Debug for WString<LEN> {
182 fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {
183 let fmted: std::string::String =
184 std::char::decode_utf16(self.0.iter().copied().take_while(|&b| b != 0))
185 .map(|ch| ch.unwrap_or(std::char::REPLACEMENT_CHARACTER))
186 .collect();
187 std::fmt::Debug::fmt(&fmted, fmt)
188 }
189}
190
191impl<const LEN: usize> std::cmp::PartialEq for WString<LEN> {
192 fn eq(&self, other: &Self) -> bool {
193 self.as_slice() == other.as_slice()
194 }
195}
196
197impl<const LEN: usize> std::cmp::PartialEq<&[u16]> for WString<LEN> {
198 fn eq(&self, other: &&[u16]) -> bool {
199 self.as_slice() == *other
200 }
201}
202
203impl<const LEN: usize> std::cmp::PartialEq<&str> for WString<LEN> {
204 fn eq(&self, other: &&str) -> bool {
205 self.as_slice().iter().copied().eq(other.encode_utf16())
206 }
207}
208
209impl<const LEN: usize> std::convert::From<[u16; LEN]> for WString<LEN> {
212 fn from(arr: [u16; LEN]) -> Self {
213 Self(arr, 0)
214 }
215}
216
217impl<const LEN: usize> std::convert::From<WString<LEN>> for [u16; LEN] {
218 fn from(wstr: WString<LEN>) -> Self {
219 wstr.0
220 }
221}
222
223impl<const LEN: usize> std::convert::TryFrom<&'_ [u16]> for WString<LEN> {
226 type Error = ();
227 fn try_from(arr: &[u16]) -> std::result::Result<Self, ()> {
228 if arr.len() > LEN {
229 return Err(());
230 }
231 let mut wstr = Self::new();
232 wstr.0[..arr.len()].copy_from_slice(arr);
233 Ok(wstr)
234 }
235}
236
237impl<const LEN: usize> std::convert::From<WString<LEN>> for std::vec::Vec<u16> {
238 fn from(wstr: WString<LEN>) -> Self {
239 wstr.as_slice().to_vec()
240 }
241}
242
243impl<const LEN: usize> std::convert::TryFrom<&'_ str> for WString<LEN> {
246 type Error = ();
247 fn try_from(s: &str) -> std::result::Result<Self, ()> {
248 let mut wstr = Self::new();
249 for (i, unit) in s.encode_utf16().enumerate() {
250 if i >= wstr.0.len() {
251 return Err(());
252 }
253 wstr.0[i] = unit;
254 }
255 Ok(wstr)
256 }
257}
258
259impl<const LEN: usize> std::convert::TryFrom<WString<LEN>> for std::string::String {
260 type Error = std::char::DecodeUtf16Error;
261 fn try_from(wstr: WString<LEN>) -> std::result::Result<Self, Self::Error> {
262 std::char::decode_utf16(wstr.0.iter().copied().take_while(|&b| b != 0)).collect()
263 }
264}
265
266unsafe impl<const LEN: usize> zerocopy::AsBytes for WString<LEN> {
269 fn only_derive_is_allowed_to_implement_this_trait() {}
270}
271
272unsafe impl<const LEN: usize> zerocopy::FromBytes for WString<LEN> {
273 fn only_derive_is_allowed_to_implement_this_trait() {}
274}
275
276pub type String80 = String<80>;
280
281pub type WString80 = WString<80>;