omp_core/encoding/
fixed_arr.rs1use std::{
10 borrow::{Borrow, BorrowMut},
11 fmt::{self, Write},
12 ops::{Deref, DerefMut},
13};
14
15#[derive(Debug, Clone, Copy)]
17pub struct Array<const N: usize>([u8; N], u16);
18
19impl<const N: usize> Default for Array<N> {
20 fn default() -> Self {
21 Self([0u8; N], 0)
22 }
23}
24
25impl<const N: usize> Array<N> {
26 pub(crate) const fn new(data: [u8; N], len: usize) -> Self {
29 debug_assert!(len <= N);
30 debug_assert!(len <= u16::MAX as usize);
31 Self(data, len as u16)
32 }
33
34 #[inline(always)]
36 pub const fn as_bytes(&self) -> &[u8] {
37 unsafe { self.0.split_at_unchecked(self.1 as usize).0 }
39 }
40
41 #[inline(always)]
43 pub const fn as_bytes_mut(&mut self) -> &mut [u8] {
44 unsafe { self.0.split_at_mut_unchecked(self.1 as usize).0 }
46 }
47}
48
49impl<const N: usize> Deref for Array<N> {
50 type Target = [u8];
51
52 #[inline]
53 fn deref(&self) -> &Self::Target {
54 self.as_bytes()
55 }
56}
57
58impl<const N: usize> DerefMut for Array<N> {
59 #[inline]
60 fn deref_mut(&mut self) -> &mut Self::Target {
61 self.as_bytes_mut()
62 }
63}
64
65impl<const N: usize> AsRef<[u8]> for Array<N> {
66 #[inline]
67 fn as_ref(&self) -> &[u8] {
68 self.as_bytes()
69 }
70}
71
72impl<const N: usize> AsMut<[u8]> for Array<N> {
73 #[inline]
74 fn as_mut(&mut self) -> &mut [u8] {
75 self.as_bytes_mut()
76 }
77}
78
79#[derive(Clone, Copy)]
81pub struct ArrayStr<const N: usize>([[u8; 2]; N], u16);
82
83impl<const N: usize> Default for ArrayStr<N> {
84 fn default() -> Self {
85 Self([[0u8; 2]; N], 0)
86 }
87}
88
89impl<const N: usize> ArrayStr<N> {
90 pub(crate) const fn new(data: [[u8; 2]; N], len: usize) -> Self {
93 debug_assert!(len <= N * 2, "Invalid length");
94 debug_assert!(len <= u16::MAX as usize, "Invalid length");
95 debug_assert!(data.as_flattened().split_at(len).0.is_ascii(), "Invalid ASCII");
96 Self(data, len as u16)
97 }
98
99 pub const fn truncate(&mut self, new_len: usize) {
103 if new_len <= self.1 as usize {
104 self.1 = new_len as u16;
105 }
106 }
107
108 #[inline(always)]
110 pub const fn as_bytes(&self) -> &[u8] {
111 unsafe { self.0.as_flattened().split_at_unchecked(self.1 as usize).0 }
113 }
114
115 #[inline(always)]
121 pub const unsafe fn as_bytes_mut(&mut self) -> &mut [u8] {
122 unsafe {
124 self
125 .0
126 .as_flattened_mut()
127 .split_at_mut_unchecked(self.1 as usize)
128 .0
129 }
130 }
131
132 #[inline(always)]
134 pub const fn as_str(&self) -> &str {
135 ascii_to_str(self.as_bytes())
138 }
139
140 #[inline]
142 pub const fn as_str_mut(&mut self) -> &mut str {
143 ascii_to_str_mut(unsafe { self.as_bytes_mut() })
146 }
147}
148
149impl<const N: usize> Deref for ArrayStr<N> {
150 type Target = str;
151
152 #[inline]
153 fn deref(&self) -> &Self::Target {
154 self.as_str()
155 }
156}
157
158impl<const N: usize> DerefMut for ArrayStr<N> {
159 #[inline]
160 fn deref_mut(&mut self) -> &mut Self::Target {
161 self.as_str_mut()
162 }
163}
164
165impl<const N: usize> AsRef<[u8]> for ArrayStr<N> {
166 #[inline]
167 fn as_ref(&self) -> &[u8] {
168 self.as_bytes()
169 }
170}
171
172impl<const N: usize> AsRef<str> for ArrayStr<N> {
173 #[inline]
174 fn as_ref(&self) -> &str {
175 self.as_str()
176 }
177}
178
179impl<const N: usize> AsMut<str> for ArrayStr<N> {
180 #[inline]
181 fn as_mut(&mut self) -> &mut str {
182 self.as_str_mut()
183 }
184}
185
186impl<const N: usize> Borrow<str> for ArrayStr<N> {
187 #[inline]
188 fn borrow(&self) -> &str {
189 self.as_str()
190 }
191}
192
193impl<const N: usize> BorrowMut<str> for ArrayStr<N> {
194 #[inline]
195 fn borrow_mut(&mut self) -> &mut str {
196 self.as_str_mut()
197 }
198}
199
200impl<const N: usize> fmt::Debug for ArrayStr<N> {
201 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
202 f.write_str("\"")?;
203 fmt::Display::fmt(self, f)?;
204 f.write_str("\"")?;
205 Ok(())
206 }
207}
208
209impl<const N: usize> fmt::Display for ArrayStr<N> {
210 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
211 if self.1 as usize == N * 2 && f.alternate() {
212 f.write_str("0x")?;
213 }
214 format_with_precision(self.as_bytes().iter().copied(), f)
215 }
216}
217
218impl<const N: usize> fmt::LowerHex for ArrayStr<N> {
219 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
220 if self.1 as usize == N * 2 {
222 if f.alternate() {
223 f.write_str("0x")?;
224 }
225 format_with_precision(
226 self
227 .as_bytes()
228 .iter()
229 .copied()
230 .map(|b| b.to_ascii_lowercase()),
231 f,
232 )
233 } else {
234 format_with_precision(self.as_bytes().iter().copied(), f)
235 }
236 }
237}
238
239impl<const N: usize> fmt::UpperHex for ArrayStr<N> {
240 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
241 if self.1 as usize == N * 2 {
243 if f.alternate() {
244 f.write_str("0x")?;
245 }
246 format_with_precision(
247 self
248 .as_bytes()
249 .iter()
250 .copied()
251 .map(|b| b.to_ascii_uppercase()),
252 f,
253 )
254 } else {
255 format_with_precision(self.as_bytes().iter().copied(), f)
256 }
257 }
258}
259
260#[inline(always)]
269pub const fn ascii_to_str(b: &[u8]) -> &str {
270 debug_assert!(b.is_ascii(), "Invalid ASCII");
271 unsafe { str::from_utf8_unchecked(b) }
275}
276
277#[inline(always)]
282pub const fn ascii_to_str_mut(b: &mut [u8]) -> &mut str {
283 debug_assert!(b.is_ascii(), "Invalid ASCII");
284 unsafe { str::from_utf8_unchecked_mut(b) }
288}
289
290#[inline(always)]
295pub fn ascii_to_str_owned(b: Vec<u8>) -> String {
296 debug_assert!(b.as_slice().is_ascii(), "Invalid ASCII");
297 unsafe { String::from_utf8_unchecked(b) }
301}
302
303pub fn format_with_precision(
307 mut it: impl ExactSizeIterator<Item = u8>,
308 f: &mut fmt::Formatter<'_>,
309) -> fmt::Result {
310 let Some(mut prec) = f.precision() else {
311 for item in it {
312 f.write_str(ascii_to_str(&[item]))?;
313 }
314 return Ok(());
315 };
316
317 let (align, fill) = match (f.align(), f.fill()) {
318 (Some(align), ' ') => (align, '…'),
319 (Some(align), fill) => (align, fill),
320 (None, _) => (fmt::Alignment::Center, '…'),
321 };
322
323 let len = it.len();
324 match align {
325 fmt::Alignment::Left => {
326 for item in it.by_ref() {
327 let Some(pnew) = prec.checked_sub(1) else {
328 f.write_char(fill)?;
329 break;
330 };
331 prec = pnew;
332 f.write_str(ascii_to_str(&[item]))?;
333 }
334 },
335 fmt::Alignment::Right => {
336 let skip_count = len.saturating_sub(prec);
338 if skip_count > 0 {
339 f.write_char(fill)?;
340 }
341 for i in it.skip(skip_count) {
342 f.write_str(ascii_to_str(&[i]))?;
343 }
344 },
345 fmt::Alignment::Center => {
346 let (mut l, mut r) = (len, 0);
348 if prec < l {
349 r = prec >> 1;
350 l = prec - r;
351 }
352
353 for i in (&mut it).take(l) {
354 f.write_str(ascii_to_str(&[i]))?;
355 }
356 if r > 0 {
357 f.write_char(fill)?;
358 for i in it.skip(len - r - l) {
359 f.write_str(ascii_to_str(&[i]))?;
360 }
361 }
362 },
363 }
364 Ok(())
365}
366
367pub fn serialize<S, F>(serializer: S, n: usize, wr: F) -> Result<S::Ok, S::Error>
368where
369 S: serde::Serializer,
370 F: FnOnce(&mut [u8]) -> usize,
371{
372 let mut stack = [0u8; 1024];
373 let mut heap = Vec::new();
374 let buffer = if let Some(slice) = stack.get_mut(..n) {
375 slice
376 } else {
377 heap.resize(n, 0);
378 &mut heap
379 };
380
381 let written = wr(buffer);
382 serializer.serialize_str(ascii_to_str(&buffer[..written]))
383}