1use std::mem::MaybeUninit;
4
5use crate::error::Error;
6
7#[inline(always)]
9pub(crate) const fn unlikely(b: bool) -> bool {
10 #[allow(clippy::needless_bool, clippy::bool_to_int_with_if)]
11 if (1i32).checked_div(if b { 0 } else { 1 }).is_none() {
12 true
13 } else {
14 false
15 }
16}
17
18pub(crate) unsafe fn read_be_u32_fast(data_ptr: *const u8, size: usize) -> u32 {
26 match size {
27 1 => *data_ptr as u32,
28 2 => u16::from_be_bytes(*(data_ptr as *const [u8; 2])) as u32,
29 3 => {
30 let mut bytes = [0u8; 4];
31 std::ptr::copy_nonoverlapping(data_ptr, bytes.as_mut_ptr().add(1), 3);
32 u32::from_be_bytes(bytes)
33 }
34 4 => u32::from_be_bytes(*(data_ptr as *const [u8; 4])),
35 _ => std::hint::unreachable_unchecked(),
36 }
37}
38
39pub(crate) unsafe fn read_be_u64_fast(data_ptr: *const u8, size: usize) -> u64 {
47 match size {
48 1..=4 => read_be_u32_fast(data_ptr, size) as u64,
49 5..=8 => {
50 let mut bytes = [0u8; 8];
51 std::ptr::copy_nonoverlapping(data_ptr, bytes.as_mut_ptr().add(8 - size), size);
52 u64::from_be_bytes(bytes)
53 }
54 _ => std::hint::unreachable_unchecked(),
55 }
56}
57
58#[cfg(any(feature = "base64", test))]
59#[inline]
60pub(crate) fn encode_base64<T: AsRef<[u8]>>(data: T) -> String {
61 use base64::Engine;
62 fn encode_base64_impl(data: &[u8]) -> String {
63 base64::engine::general_purpose::STANDARD.encode(data)
64 }
65 encode_base64_impl(data.as_ref())
66}
67
68#[cfg(any(feature = "base64", test))]
69#[inline]
70pub(crate) fn decode_base64<T: AsRef<[u8]>>(data: T) -> Result<Vec<u8>, base64::DecodeError> {
71 use base64::Engine;
72 fn decode_base64_impl(data: &[u8]) -> Result<Vec<u8>, base64::DecodeError> {
73 base64::engine::general_purpose::STANDARD.decode(data)
74 }
75 decode_base64_impl(data.as_ref())
76}
77
78#[cfg(any(feature = "base64", test))]
79#[allow(unused)]
80#[inline]
81pub(crate) fn decode_base64_slice<T: AsRef<[u8]>>(
82 data: T,
83 target: &mut [u8],
84) -> Result<(), base64::DecodeSliceError> {
85 use base64::Engine;
86 fn decode_base64_slice_impl(
87 data: &[u8],
88 target: &mut [u8],
89 ) -> Result<(), base64::DecodeSliceError> {
90 base64::engine::general_purpose::STANDARD
91 .decode_slice(data, target)
92 .map(|_| ())
93 }
94 decode_base64_slice_impl(data.as_ref(), target)
95}
96
97#[cfg(any(feature = "base64", test))]
98#[inline]
99pub(crate) fn crc_16(data: &[u8]) -> u16 {
100 let mut crc: u32 = 0;
101 for c in data {
102 let t = c ^ ((crc >> 8) as u8);
103 crc = (CRC16_TABLE[t as usize] ^ ((crc << 8) as u16)) as u32;
104 }
105 crc as u16
106}
107
108#[cfg(any(feature = "base64", test))]
109static CRC16_TABLE: [u16; 256] = [
110 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7, 0x8108, 0x9129, 0xa14a, 0xb16b,
111 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef, 0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6,
112 0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de, 0x2462, 0x3443, 0x0420, 0x1401,
113 0x64e6, 0x74c7, 0x44a4, 0x5485, 0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d,
114 0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4, 0xb75b, 0xa77a, 0x9719, 0x8738,
115 0xf7df, 0xe7fe, 0xd79d, 0xc7bc, 0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823,
116 0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b, 0x5af5, 0x4ad4, 0x7ab7, 0x6a96,
117 0x1a71, 0x0a50, 0x3a33, 0x2a12, 0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a,
118 0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41, 0xedae, 0xfd8f, 0xcdec, 0xddcd,
119 0xad2a, 0xbd0b, 0x8d68, 0x9d49, 0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70,
120 0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78, 0x9188, 0x81a9, 0xb1ca, 0xa1eb,
121 0xd10c, 0xc12d, 0xf14e, 0xe16f, 0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067,
122 0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e, 0x02b1, 0x1290, 0x22f3, 0x32d2,
123 0x4235, 0x5214, 0x6277, 0x7256, 0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d,
124 0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405, 0xa7db, 0xb7fa, 0x8799, 0x97b8,
125 0xe75f, 0xf77e, 0xc71d, 0xd73c, 0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634,
126 0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab, 0x5844, 0x4865, 0x7806, 0x6827,
127 0x18c0, 0x08e1, 0x3882, 0x28a3, 0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a,
128 0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92, 0xfd2e, 0xed0f, 0xdd6c, 0xcd4d,
129 0xbdaa, 0xad8b, 0x9de8, 0x8dc9, 0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1,
130 0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8, 0x6e17, 0x7e36, 0x4e55, 0x5e74,
131 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0,
132];
133
134pub struct ArrayVec<T, const N: usize> {
136 inner: [MaybeUninit<T>; N],
137 len: u8,
138}
139
140impl<T, const N: usize> ArrayVec<T, N> {
141 const _ASSERT_LEN: () = assert!(N <= u8::MAX as usize);
143
144 pub const fn new() -> Self {
146 Self {
147 inner: unsafe { MaybeUninit::<[MaybeUninit<T>; N]>::uninit().assume_init() },
149 len: 0,
150 }
151 }
152
153 #[inline]
155 pub const fn len(&self) -> usize {
156 self.len as usize
157 }
158
159 #[inline]
161 pub const fn is_empty(&self) -> bool {
162 self.len == 0
163 }
164
165 #[inline]
172 pub unsafe fn push(&mut self, item: T) {
173 debug_assert!((self.len as usize) < N);
174
175 *self.inner.get_unchecked_mut(self.len as usize) = MaybeUninit::new(item);
176 self.len += 1;
177 }
178
179 pub const fn get(&self, n: u8) -> Option<&T> {
181 if n < self.len {
182 let references = self.inner.as_ptr() as *const T;
183 Some(unsafe { &*references.add(n as usize) })
185 } else {
186 None
187 }
188 }
189
190 #[inline]
197 pub unsafe fn into_inner(self) -> [MaybeUninit<T>; N] {
198 let this = std::mem::ManuallyDrop::new(self);
199 std::ptr::read(&this.inner)
200 }
201}
202
203impl<T, const N: usize> Default for ArrayVec<T, N> {
204 #[inline]
205 fn default() -> Self {
206 Self::new()
207 }
208}
209
210impl<R, const N: usize> AsRef<[R]> for ArrayVec<R, N> {
211 #[inline]
212 fn as_ref(&self) -> &[R] {
213 unsafe { std::slice::from_raw_parts(self.inner.as_ptr() as *const R, self.len as usize) }
215 }
216}
217
218impl<T: Clone, const N: usize> Clone for ArrayVec<T, N> {
219 fn clone(&self) -> Self {
220 let mut res = Self::default();
221 for item in self.as_ref() {
222 unsafe { res.push(item.clone()) };
224 }
225 res
226 }
227}
228
229impl<T, const N: usize> Drop for ArrayVec<T, N> {
230 fn drop(&mut self) {
231 debug_assert!(self.len as usize <= N);
232
233 let references_ptr = self.inner.as_mut_ptr() as *mut T;
234 for i in 0..self.len {
235 unsafe { std::ptr::drop_in_place(references_ptr.add(i as usize)) };
237 }
238 }
239}
240
241#[derive(Clone, Copy)]
242pub(crate) enum IterStatus {
243 Valid,
245 Pruned,
247 Broken,
249}
250
251impl IterStatus {
252 #[inline]
253 pub(crate) const fn is_valid(self) -> bool {
254 matches!(self, Self::Valid)
255 }
256
257 #[inline]
258 pub(crate) const fn is_pruned(self) -> bool {
259 matches!(self, Self::Pruned)
260 }
261}
262
263pub trait TryAsMut<T: ?Sized> {
265 fn try_as_mut(&mut self) -> Option<&mut T>;
267}
268
269pub struct Bitstring<'a> {
271 pub bytes: &'a [u8],
273 pub bit_len: u16,
275}
276
277impl Bitstring<'_> {
278 pub fn from_hex_str(s: &str) -> Result<(Vec<u8>, u16), Error> {
283 fn hex_char(c: u8) -> Result<u8, Error> {
284 match c {
285 b'A'..=b'F' => Ok(c - b'A' + 10),
286 b'a'..=b'f' => Ok(c - b'a' + 10),
287 b'0'..=b'9' => Ok(c - b'0'),
288 _ => Err(Error::InvalidData),
289 }
290 }
291
292 if !s.is_ascii() || s.len() > 128 * 2 {
293 return Err(Error::InvalidData);
294 }
295
296 let s = s.as_bytes();
297 let (mut s, with_tag) = match s.strip_suffix(b"_") {
298 Some(s) => (s, true),
299 None => (s, false),
300 };
301
302 let mut half_byte = None;
303 if s.len() % 2 != 0 {
304 if let Some((last, prefix)) = s.split_last() {
305 half_byte = Some(ok!(hex_char(*last)));
306 s = prefix;
307 }
308 }
309
310 let Ok(mut data) = hex::decode(s) else {
311 return Err(Error::InvalidData);
312 };
313
314 let mut bit_len = data.len() as u16 * 8;
315 if let Some(half_byte) = half_byte {
316 bit_len += 4;
317 data.push(half_byte << 4);
318 }
319
320 if with_tag {
321 bit_len = data.len() as u16 * 8;
322 for byte in data.iter_mut().rev() {
323 if *byte == 0 {
324 bit_len -= 8;
325 } else {
326 let trailing = byte.trailing_zeros();
327 bit_len -= 1 + trailing as u16;
328
329 *byte &= (0xff << trailing) << 1;
332 break;
333 }
334 }
335
336 data.truncate((bit_len as usize + 7) / 8);
337 }
338
339 Ok((data, bit_len))
340 }
341}
342
343impl std::fmt::Display for Bitstring<'_> {
344 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
345 const CHUNK_LEN: usize = 16;
346
347 let bit_len = std::cmp::min(self.bit_len as usize, self.bytes.len() * 8) as u16;
348 let byte_len = ((bit_len + 7) / 8) as usize;
349 let bytes = &self.bytes[..byte_len];
350
351 let rem = bit_len % 8;
352 let (bytes, last_byte) = match bytes.split_last() {
353 Some((last_byte, bytes)) if rem != 0 => {
354 let tag_mask: u8 = 1 << (7 - rem);
355 let data_mask = !(tag_mask - 1);
356 let last_byte = (*last_byte & data_mask) | tag_mask;
357 (bytes, Some(last_byte))
358 }
359 _ => (bytes, None),
360 };
361
362 let mut chunk = [0u8; CHUNK_LEN * 2];
363 for data in bytes.chunks(CHUNK_LEN) {
364 let chunk = &mut chunk[..data.len() * 2];
365 hex::encode_to_slice(data, chunk).unwrap();
366
367 ok!(f.write_str(unsafe { std::str::from_utf8_unchecked(chunk) }));
369 }
370
371 if let Some(mut last_byte) = last_byte {
372 let tag = if rem != 4 { "_" } else { "" };
373 let rem = 1 + (rem > 4) as usize;
374 if rem == 1 {
375 last_byte >>= 4;
376 }
377 ok!(write!(f, "{last_byte:0rem$x}{tag}"));
378 }
379
380 Ok(())
381 }
382}
383
384impl std::fmt::Binary for Bitstring<'_> {
385 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
386 let bit_len = std::cmp::min(self.bit_len as usize, self.bytes.len() * 8) as u16;
387 let byte_len = ((bit_len + 7) / 8) as usize;
388 let bytes = &self.bytes[..byte_len];
389
390 let rem = (bit_len % 8) as usize;
391 let (bytes, last_byte) = match bytes.split_last() {
392 Some((last_byte, bytes)) if rem != 0 => (bytes, Some(*last_byte)),
393 _ => (bytes, None),
394 };
395
396 for byte in bytes {
397 ok!(write!(f, "{byte:08b}"));
398 }
399
400 if let Some(mut last_byte) = last_byte {
401 last_byte >>= 8 - rem;
402 ok!(write!(f, "{last_byte:0rem$b}"))
403 }
404
405 Ok(())
406 }
407}
408
409#[allow(unused)]
410pub(crate) fn debug_tuple_field1_finish(
411 f: &mut std::fmt::Formatter<'_>,
412 name: &str,
413 value1: &dyn std::fmt::Debug,
414) -> std::fmt::Result {
415 let mut builder = std::fmt::Formatter::debug_tuple(f, name);
416 builder.field(value1);
417 builder.finish()
418}
419
420pub(crate) fn debug_struct_field1_finish(
421 f: &mut std::fmt::Formatter<'_>,
422 name: &str,
423 name1: &str,
424 value1: &dyn std::fmt::Debug,
425) -> std::fmt::Result {
426 let mut builder = std::fmt::Formatter::debug_struct(f, name);
427 builder.field(name1, value1);
428 builder.finish()
429}
430
431pub(crate) fn debug_struct_field2_finish(
432 f: &mut std::fmt::Formatter<'_>,
433 name: &str,
434 name1: &str,
435 value1: &dyn std::fmt::Debug,
436 name2: &str,
437 value2: &dyn std::fmt::Debug,
438) -> std::fmt::Result {
439 let mut builder = std::fmt::Formatter::debug_struct(f, name);
440 builder.field(name1, value1);
441 builder.field(name2, value2);
442 builder.finish()
443}
444
445#[cfg(test)]
446mod tests {
447 use super::*;
448
449 #[test]
450 fn parse_bitstring_from_hex_str() {
451 let (data, bit_len) = Bitstring::from_hex_str("").unwrap();
452 assert_eq!(bit_len, 0);
453 assert!(data.is_empty());
454
455 let (data, bit_len) = Bitstring::from_hex_str("8_").unwrap();
456 assert_eq!(bit_len, 0);
457 assert!(data.is_empty());
458
459 let (data, bit_len) = Bitstring::from_hex_str("ded_").unwrap();
460 assert_eq!(bit_len, 11);
461 assert_eq!(data, vec![0xde, 0xc0]);
462
463 let (data, bit_len) = Bitstring::from_hex_str("b00b1e5").unwrap();
464 assert_eq!(bit_len, 28);
465 assert_eq!(data, vec![0xb0, 0x0b, 0x1e, 0x50]);
466
467 let (data, bit_len) = Bitstring::from_hex_str("b00b1e5_").unwrap();
468 assert_eq!(bit_len, 27);
469 assert_eq!(data, vec![0xb0, 0x0b, 0x1e, 0x40]);
470 }
471
472 #[test]
473 fn bitstring_zero_char_with_completion_tag() {
474 assert_eq!(
475 format!(
476 "{}",
477 Bitstring {
478 bytes: &[0b_0011_0000],
479 bit_len: 4
480 }
481 ),
482 format!("{:x}", 0b_0011)
483 );
484 assert_eq!(
485 format!(
486 "{}",
487 Bitstring {
488 bytes: &[0b_0100_0000],
489 bit_len: 2
490 }
491 ),
492 format!("{:x}_", 0b_0110)
493 );
494 assert_eq!(
495 format!(
496 "{}",
497 Bitstring {
498 bytes: &[0b_0000_1000],
499 bit_len: 5
500 }
501 ),
502 format!("{:x}{:x}_", 0b_0000, 0b_1100)
503 );
504 assert_eq!(
505 format!(
506 "{}",
507 Bitstring {
508 bytes: &[0b_0000_1000, 0b_0100_0000],
509 bit_len: 8 + 2
510 }
511 ),
512 format!("{:x}{:x}{:x}_", 0b_0000, 0b_1000, 0b_0110)
513 );
514 assert_eq!(
515 format!(
516 "{}",
517 Bitstring {
518 bytes: &[0b_0100_0000, 0b_0000_1000],
519 bit_len: 8 + 5
520 }
521 ),
522 format!("{:x}{:x}{:x}{:x}_", 0b_0100, 0b_0000, 0b_0000, 0b_1100)
523 );
524 }
525}