1use super::primitive_read::*;
2use smart_default::SmartDefault;
3use std::borrow::Cow;
4
5#[cfg(feature = "serialize")]
6use serde::Serialize;
7
8#[derive(Debug, Clone, Copy, PartialEq, Eq)]
10pub enum ByteOrder {
11 LittleEndian,
12 BigEndian,
13}
14
15#[derive(Debug, Clone, Copy, PartialEq, Eq)]
16pub enum CompressType {
17 Uncompressed,
18 #[cfg(feature = "gzip")]
19 GzipCompressed,
20 #[cfg(feature = "bzip")]
21 BzipCompressed,
22 #[cfg(feature = "zipfile")]
23 ZipCompressed,
24}
25
26pub type B1 = [u8; 1];
31pub type C1 = char;
34pub type U1 = u8;
35pub type U2 = u16;
36pub type U4 = u32;
37pub type U8 = u64;
38pub type I1 = i8;
39pub type I2 = i16;
40pub type I4 = i32;
41pub type R4 = f32;
42pub type R8 = f64;
43
44pub type Cn = String;
46
47pub type Cf = String;
49
50pub type Sn = String;
52
53pub type Bn = Vec<u8>;
55
56pub type Dn = Vec<u8>;
58
59pub type KxCn = Vec<Cn>;
60pub type KxSn = Vec<Sn>;
61pub type KxCf = Vec<Cf>;
62pub type KxU1 = Vec<U1>;
63pub type KxU2 = Vec<U2>;
64pub type KxU4 = Vec<U4>;
65pub type KxU8 = Vec<U8>;
66pub type KxR4 = Vec<R4>;
67pub type KxN1 = Vec<U1>;
68
69#[cfg_attr(feature = "serialize", derive(Serialize))]
75#[derive(SmartDefault, Debug, Clone, PartialEq, Eq)]
76pub enum KxUf {
77 #[default]
78 F1(KxU1),
79 F2(KxU2),
80 F4(KxU4),
81 F8(KxU8),
82}
83
84#[cfg_attr(feature = "serialize", derive(Serialize))]
88#[derive(Debug, Clone, PartialEq)]
89pub enum V1 {
90 B0,
91 U1(U1),
92 U2(U2),
93 U4(U4),
94 I1(I1),
95 I2(I2),
96 I4(I4),
97 R4(R4),
98 R8(R8),
99 Cn(Cn),
100 Bn(Bn),
101 Dn(Dn),
102 N1(U1),
103 Invalid,
104}
105
106pub type Vn = Vec<V1>;
107
108pub(crate) const VIEW_ABSENT_OFT: u16 = u16::MAX;
117
118#[inline]
120pub(crate) fn validate_offset(off: u16) -> Option<usize> {
121 if off == VIEW_ABSENT_OFT {
122 None
123 } else {
124 Some(off as usize)
125 }
126}
127
128#[derive(SmartDefault, Clone, Copy, Debug)]
130pub struct CnRef<'a>(&'a [u8]);
131
132#[derive(SmartDefault, Clone, Copy, Debug)]
135pub struct SnRef<'a>(&'a [u8]);
136
137#[derive(SmartDefault, Clone, Copy, Debug)]
139pub struct BnRef<'a>(&'a [u8]);
140
141#[derive(SmartDefault, Clone, Copy, Debug)]
144pub struct DnRef<'a>(&'a [u8]);
145
146#[derive(Clone, Copy, Default)]
162pub struct KxCnRef<'a> {
163 raw: &'a [u8],
164 start: usize,
165 k: usize,
166}
167
168pub struct KxCnRefIter<'a> {
170 raw: &'a [u8],
171 pos: usize,
172 remaining: usize,
173}
174
175#[derive(SmartDefault, Clone, Copy)]
191pub struct KxSnRef<'a> {
192 raw: &'a [u8],
193 start: usize,
194 k: usize,
195 #[default(ByteOrder::LittleEndian)]
196 order: ByteOrder,
197}
198
199pub struct KxSnRefIter<'a> {
201 raw: &'a [u8],
202 pos: usize,
203 remaining: usize,
204 order: ByteOrder,
205}
206
207#[derive(Clone, Copy, Default)]
223pub struct KxCfRef<'a> {
224 raw: &'a [u8],
225 start: usize,
226 k: usize,
227 f: usize,
228}
229
230pub struct KxCfRefIter<'a> {
232 raw: &'a [u8],
233 pos: usize,
234 remaining: usize,
235 f: usize,
236}
237
238impl<'a> CnRef<'a> {
239 #[inline]
242 pub(crate) fn read_at(raw: &'a [u8], off: u16) -> Option<Self> {
243 let p = validate_offset(off)?;
244 let cnt = *raw.get(p)? as usize;
245 let start = p + 1;
246 let end = std::cmp::min(start + cnt, raw.len()); Some(CnRef(&raw[start..end]))
248 }
249
250 #[inline]
252 pub fn as_bytes(&self) -> &'a [u8] {
253 self.0
254 }
255
256 #[inline]
260 pub fn as_str(&self) -> Cow<'a, str> {
261 bytes_to_cow_str(self.0)
262 }
263
264 pub fn to_owned(&self) -> Cn {
267 bytes_to_string(self.0)
268 }
269}
270
271impl<'a> SnRef<'a> {
272 #[inline]
275 pub(crate) fn read_at(raw: &'a [u8], off: u16, order: &ByteOrder) -> Option<Self> {
276 let p = validate_offset(off)?;
277 let mut cp = p;
278 let cnt = read_u2(raw, &mut cp, order) as usize;
279 let start = cp;
280 let end = std::cmp::min(start + cnt, raw.len());
281 Some(SnRef(raw.get(start..end).unwrap_or(&[])))
282 }
283
284 #[inline]
286 pub fn as_bytes(&self) -> &'a [u8] {
287 self.0
288 }
289
290 #[inline]
294 pub fn as_str(&self) -> Cow<'a, str> {
295 bytes_to_cow_str(self.0)
296 }
297
298 pub fn to_owned(&self) -> Sn {
301 bytes_to_string(self.0)
302 }
303}
304
305impl<'a> BnRef<'a> {
306 #[inline]
309 pub(crate) fn read_at(raw: &'a [u8], off: u16) -> Option<Self> {
310 let p = validate_offset(off)?;
311 let cnt = *raw.get(p)? as usize;
312 let start = p + 1;
313 let end = std::cmp::min(start + cnt, raw.len());
314 Some(BnRef(&raw[start..end]))
315 }
316
317 #[inline]
319 pub fn as_bytes(&self) -> &'a [u8] {
320 self.0
321 }
322
323 #[inline]
324 pub fn is_empty(&self) -> bool {
325 self.0.is_empty()
326 }
327
328 #[inline]
329 pub fn len(&self) -> usize {
330 self.0.len()
331 }
332
333 pub fn to_owned(&self) -> Bn {
336 self.0.to_vec()
337 }
338}
339
340impl<'a> DnRef<'a> {
341 #[inline]
344 pub(crate) fn read_at(raw: &'a [u8], off: u16, order: &ByteOrder) -> Option<Self> {
345 let p = validate_offset(off)?;
346 let mut cp = p;
347 let bitcount = read_u2(raw, &mut cp, order) as usize;
348 let bytecount = bitcount.div_ceil(8);
349 let start = cp;
350 let end = std::cmp::min(start + bytecount, raw.len());
351 Some(DnRef(raw.get(start..end).unwrap_or(&[])))
352 }
353
354 #[inline]
356 pub fn as_bytes(&self) -> &'a [u8] {
357 self.0
358 }
359
360 #[inline]
361 pub fn is_empty(&self) -> bool {
362 self.0.is_empty()
363 }
364
365 #[inline]
366 pub fn len(&self) -> usize {
367 self.0.len()
368 }
369
370 pub fn to_owned(&self) -> Dn {
373 self.0.to_vec()
374 }
375}
376
377impl<'a> KxCnRef<'a> {
378 #[inline]
383 pub fn new(raw: &'a [u8], start: usize, k: usize) -> Self {
384 KxCnRef { raw, start, k }
385 }
386
387 #[inline]
389 pub fn len(&self) -> usize {
390 self.k
391 }
392
393 #[inline]
395 pub fn is_empty(&self) -> bool {
396 self.k == 0
397 }
398
399 #[inline]
404 pub fn get_str(&self, i: usize) -> Option<Cow<'a, str>> {
405 self.get_bytes(i).map(bytes_to_cow_str)
406 }
407
408 #[inline]
411 pub fn get_bytes(&self, i: usize) -> Option<&'a [u8]> {
412 if i >= self.k {
413 return None;
414 }
415 let mut pos = self.start;
418 for _ in 0..i {
419 let cnt = *self.raw.get(pos)? as usize;
420 pos = std::cmp::min(pos + 1 + cnt, self.raw.len());
421 }
422 let cnt = *self.raw.get(pos)? as usize;
423 let start = pos + 1;
424 let end = std::cmp::min(start + cnt, self.raw.len());
425 Some(&self.raw[start..end])
426 }
427
428 #[inline]
430 pub fn iter(&self) -> KxCnRefIter<'a> {
431 KxCnRefIter {
432 raw: self.raw,
433 pos: self.start,
434 remaining: self.k,
435 }
436 }
437
438 #[inline]
440 pub fn as_vec(&self) -> Vec<Cow<'a, str>> {
441 self.iter().collect()
442 }
443
444 #[inline]
447 pub fn to_owned(&self) -> KxCn {
448 self.iter().map(Cow::into_owned).collect()
449 }
450}
451
452impl<'a> Iterator for KxCnRefIter<'a> {
453 type Item = Cow<'a, str>;
454
455 fn next(&mut self) -> Option<Self::Item> {
456 if self.remaining == 0 {
457 return None;
458 }
459 self.remaining -= 1;
460 let cnt = *self.raw.get(self.pos)? as usize;
461 self.pos += 1;
462 let end = std::cmp::min(self.pos + cnt, self.raw.len());
463 let slice = &self.raw[self.pos..end];
464 self.pos = end;
465 Some(bytes_to_cow_str(slice))
466 }
467}
468
469impl<'a> IntoIterator for &'a KxCnRef<'a> {
470 type Item = Cow<'a, str>;
471 type IntoIter = KxCnRefIter<'a>;
472
473 fn into_iter(self) -> Self::IntoIter {
474 self.iter()
475 }
476}
477
478impl<'a> KxSnRef<'a> {
479 #[inline]
485 pub fn new(raw: &'a [u8], start: usize, k: usize, order: ByteOrder) -> Self {
486 KxSnRef {
487 raw,
488 start,
489 k,
490 order,
491 }
492 }
493
494 #[inline]
496 pub fn len(&self) -> usize {
497 self.k
498 }
499
500 #[inline]
502 pub fn is_empty(&self) -> bool {
503 self.k == 0
504 }
505
506 #[inline]
511 pub fn get_str(&self, i: usize) -> Option<Cow<'a, str>> {
512 self.get_bytes(i).map(bytes_to_cow_str)
513 }
514
515 #[inline]
518 pub fn get_bytes(&self, i: usize) -> Option<&'a [u8]> {
519 if i >= self.k {
520 return None;
521 }
522 let mut pos = self.start;
525 for _ in 0..i {
526 let mut cp = pos;
527 let cnt = read_u2(self.raw, &mut cp, &self.order) as usize;
528 pos = std::cmp::min(cp + cnt, self.raw.len());
529 }
530 let mut cp = pos;
531 let cnt = read_u2(self.raw, &mut cp, &self.order) as usize;
532 let start = cp;
533 let end = std::cmp::min(start + cnt, self.raw.len());
534 Some(self.raw.get(start..end).unwrap_or(&[]))
535 }
536
537 #[inline]
539 pub fn iter(&self) -> KxSnRefIter<'a> {
540 KxSnRefIter {
541 raw: self.raw,
542 pos: self.start,
543 remaining: self.k,
544 order: self.order,
545 }
546 }
547
548 #[inline]
550 pub fn as_vec(&self) -> Vec<Cow<'a, str>> {
551 self.iter().collect()
552 }
553
554 #[inline]
557 pub fn to_owned(&self) -> KxSn {
558 self.iter().map(Cow::into_owned).collect()
559 }
560}
561
562impl<'a> Iterator for KxSnRefIter<'a> {
563 type Item = Cow<'a, str>;
564
565 fn next(&mut self) -> Option<Self::Item> {
566 if self.remaining == 0 {
567 return None;
568 }
569 self.remaining -= 1;
570 let mut cp = self.pos;
571 let cnt = read_u2(self.raw, &mut cp, &self.order) as usize;
572 self.pos = cp;
573 let end = std::cmp::min(self.pos + cnt, self.raw.len());
574 let slice = self.raw.get(self.pos..end).unwrap_or(&[]);
575 self.pos = end;
576 Some(bytes_to_cow_str(slice))
577 }
578}
579
580impl<'a> IntoIterator for &'a KxSnRef<'a> {
581 type Item = Cow<'a, str>;
582 type IntoIter = KxSnRefIter<'a>;
583
584 fn into_iter(self) -> Self::IntoIter {
585 self.iter()
586 }
587}
588
589impl<'a> KxCfRef<'a> {
590 #[inline]
596 pub fn new(raw: &'a [u8], start: usize, k: usize, f: usize) -> Self {
597 KxCfRef { raw, start, k, f }
598 }
599
600 #[inline]
602 pub fn len(&self) -> usize {
603 self.k
604 }
605
606 #[inline]
608 pub fn is_empty(&self) -> bool {
609 self.k == 0
610 }
611
612 #[inline]
617 pub fn get_str(&self, i: usize) -> Option<Cow<'a, str>> {
618 self.get_bytes(i).map(bytes_to_cow_str)
619 }
620
621 #[inline]
624 pub fn get_bytes(&self, i: usize) -> Option<&'a [u8]> {
625 if i >= self.k {
626 return None;
627 }
628 let start = self.start + i * self.f;
629 let end = std::cmp::min(start + self.f, self.raw.len());
630 self.raw.get(start..end)
631 }
632
633 #[inline]
635 pub fn iter(&self) -> KxCfRefIter<'a> {
636 KxCfRefIter {
637 raw: self.raw,
638 pos: self.start,
639 remaining: self.k,
640 f: self.f,
641 }
642 }
643
644 #[inline]
646 pub fn as_vec(&self) -> Vec<Cow<'a, str>> {
647 self.iter().collect()
648 }
649
650 #[inline]
653 pub fn to_owned(&self) -> KxCf {
654 self.iter().map(Cow::into_owned).collect()
655 }
656}
657
658impl<'a> Iterator for KxCfRefIter<'a> {
659 type Item = Cow<'a, str>;
660
661 fn next(&mut self) -> Option<Self::Item> {
662 if self.remaining == 0 {
663 return None;
664 }
665 self.remaining -= 1;
666 let end = std::cmp::min(self.pos + self.f, self.raw.len());
667 let slice = self.raw.get(self.pos..end).unwrap_or(&[]);
668 self.pos = end;
669 Some(bytes_to_cow_str(slice))
670 }
671}
672
673impl<'a> IntoIterator for &'a KxCfRef<'a> {
674 type Item = Cow<'a, str>;
675 type IntoIter = KxCfRefIter<'a>;
676
677 fn into_iter(self) -> Self::IntoIter {
678 self.iter()
679 }
680}
681
682#[inline(always)]
686pub(crate) fn bytes_to_cow_str(data: &[u8]) -> Cow<'_, str> {
687 match std::str::from_utf8(data) {
688 Ok(s) => Cow::Borrowed(s),
689 Err(_) => Cow::Owned(data.iter().map(|&x| x as char).collect()),
690 }
691}
692
693#[inline(always)]
695pub(crate) fn bytes_to_string(data: &[u8]) -> String {
696 bytes_to_cow_str(data).into_owned()
697}