use super::primitive_read::*;
use smart_default::SmartDefault;
use std::borrow::Cow;
#[cfg(feature = "serialize")]
use serde::Serialize;
#[cfg_attr(feature = "serialize", derive(Serialize))]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ByteOrder {
LittleEndian,
BigEndian,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum CompressType {
Uncompressed,
#[cfg(feature = "gzip")]
GzipCompressed,
#[cfg(feature = "bzip")]
BzipCompressed,
#[cfg(feature = "zipfile")]
ZipCompressed,
}
pub type B1 = [u8; 1];
pub type C1 = char;
pub type U1 = u8;
pub type U2 = u16;
pub type U4 = u32;
pub type U8 = u64;
pub type I1 = i8;
pub type I2 = i16;
pub type I4 = i32;
pub type R4 = f32;
pub type R8 = f64;
pub type Cn = String;
pub type Cf = String;
pub type Sn = String;
pub type Bn = Vec<u8>;
#[cfg_attr(feature = "serialize", derive(Serialize))]
#[derive(SmartDefault, Debug, Clone, PartialEq, Eq)]
pub struct Dn {
pub bit_count: u16,
pub bit_data: Vec<u8>,
}
pub type KxCn = Vec<Cn>;
pub type KxSn = Vec<Sn>;
pub type KxCf = Vec<Cf>;
pub type KxU1 = Vec<U1>;
pub type KxU2 = Vec<U2>;
pub type KxU4 = Vec<U4>;
pub type KxU8 = Vec<U8>;
pub type KxR4 = Vec<R4>;
pub type KxN1 = Vec<U1>;
#[cfg_attr(feature = "serialize", derive(Serialize))]
#[derive(SmartDefault, Debug, Clone, PartialEq, Eq)]
pub enum KxUf {
#[default]
F1(KxU1),
F2(KxU2),
F4(KxU4),
F8(KxU8),
}
#[cfg_attr(feature = "serialize", derive(Serialize))]
#[derive(Debug, Clone, PartialEq)]
pub enum V1 {
B0,
U1(U1),
U2(U2),
U4(U4),
I1(I1),
I2(I2),
I4(I4),
R4(R4),
R8(R8),
Cn(Cn),
Bn(Bn),
Dn(Dn),
N1(U1),
Invalid,
}
pub type Vn = Vec<V1>;
pub(crate) const VIEW_ABSENT_OFT: u16 = u16::MAX;
#[inline]
pub(crate) fn validate_offset(off: u16) -> Option<usize> {
if off == VIEW_ABSENT_OFT {
None
} else {
Some(off as usize)
}
}
#[derive(SmartDefault, Clone, Copy, Debug)]
pub struct CnRef<'a>(&'a [u8]);
#[derive(SmartDefault, Clone, Copy, Debug)]
pub struct SnRef<'a>(&'a [u8]);
#[derive(SmartDefault, Clone, Copy, Debug)]
pub struct BnRef<'a>(&'a [u8]);
#[derive(SmartDefault, Clone, Copy, Debug)]
pub struct DnRef<'a> {
bit_count: u16,
bit_data: &'a [u8],
}
#[derive(Clone, Copy, Default)]
pub struct KxCnRef<'a> {
raw: &'a [u8],
start: usize,
k: usize,
}
pub struct KxCnRefIter<'a> {
raw: &'a [u8],
pos: usize,
remaining: usize,
}
#[derive(SmartDefault, Clone, Copy)]
pub struct KxSnRef<'a> {
raw: &'a [u8],
start: usize,
k: usize,
#[default(ByteOrder::LittleEndian)]
order: ByteOrder,
}
pub struct KxSnRefIter<'a> {
raw: &'a [u8],
pos: usize,
remaining: usize,
order: ByteOrder,
}
#[derive(Clone, Copy, Default)]
pub struct KxCfRef<'a> {
raw: &'a [u8],
start: usize,
k: usize,
f: usize,
}
pub struct KxCfRefIter<'a> {
raw: &'a [u8],
pos: usize,
remaining: usize,
f: usize,
}
impl<'a> CnRef<'a> {
#[inline]
pub(crate) fn read_at(raw: &'a [u8], off: u16) -> Option<Self> {
let p = validate_offset(off)?;
let cnt = *raw.get(p)? as usize;
let start = p + 1;
let end = std::cmp::min(start + cnt, raw.len()); Some(CnRef(&raw[start..end]))
}
#[inline]
pub fn as_bytes(&self) -> &'a [u8] {
self.0
}
#[inline]
pub fn as_str(&self) -> Cow<'a, str> {
bytes_to_cow_str(self.0)
}
pub fn to_owned(&self) -> Cn {
bytes_to_string(self.0)
}
}
impl<'a> SnRef<'a> {
#[inline]
pub(crate) fn read_at(raw: &'a [u8], off: u16, order: &ByteOrder) -> Option<Self> {
let p = validate_offset(off)?;
let mut cp = p;
let cnt = read_u2(raw, &mut cp, order) as usize;
let start = cp;
let end = std::cmp::min(start + cnt, raw.len());
Some(SnRef(raw.get(start..end).unwrap_or(&[])))
}
#[inline]
pub fn as_bytes(&self) -> &'a [u8] {
self.0
}
#[inline]
pub fn as_str(&self) -> Cow<'a, str> {
bytes_to_cow_str(self.0)
}
pub fn to_owned(&self) -> Sn {
bytes_to_string(self.0)
}
}
impl<'a> BnRef<'a> {
#[inline]
pub(crate) fn read_at(raw: &'a [u8], off: u16) -> Option<Self> {
let p = validate_offset(off)?;
let cnt = *raw.get(p)? as usize;
let start = p + 1;
let end = std::cmp::min(start + cnt, raw.len());
Some(BnRef(&raw[start..end]))
}
#[inline]
pub fn as_bytes(&self) -> &'a [u8] {
self.0
}
#[inline]
pub fn is_empty(&self) -> bool {
self.0.is_empty()
}
#[inline]
pub fn len(&self) -> usize {
self.0.len()
}
pub fn to_owned(&self) -> Bn {
self.0.to_vec()
}
}
impl<'a> DnRef<'a> {
#[inline]
pub(crate) fn read_at(raw: &'a [u8], off: u16, order: &ByteOrder) -> Option<Self> {
let p = validate_offset(off)?;
let mut cp = p;
let bitcount = read_u2(raw, &mut cp, order);
let bytecount = (bitcount as usize).div_ceil(8);
let start = cp;
let end = std::cmp::min(start + bytecount, raw.len());
Some(DnRef {
bit_count: bitcount,
bit_data: raw.get(start..end).unwrap_or(&[]),
})
}
#[inline]
pub fn bit_count(&self) -> u16 {
self.bit_count
}
#[inline]
pub fn as_bytes(&self) -> &'a [u8] {
self.bit_data
}
#[inline]
pub fn is_empty(&self) -> bool {
self.bit_data.is_empty()
}
#[inline]
pub fn len(&self) -> usize {
self.bit_data.len()
}
pub fn to_owned(&self) -> Dn {
Dn {
bit_count: self.bit_count,
bit_data: self.bit_data.to_vec(),
}
}
}
impl<'a> KxCnRef<'a> {
#[inline]
pub fn new(raw: &'a [u8], start: usize, k: usize) -> Self {
KxCnRef { raw, start, k }
}
#[inline]
pub fn len(&self) -> usize {
self.k
}
#[inline]
pub fn is_empty(&self) -> bool {
self.k == 0
}
#[inline]
pub fn get_str(&self, i: usize) -> Option<Cow<'a, str>> {
self.get_bytes(i).map(bytes_to_cow_str)
}
#[inline]
pub fn get_bytes(&self, i: usize) -> Option<&'a [u8]> {
if i >= self.k {
return None;
}
let mut pos = self.start;
for _ in 0..i {
let cnt = *self.raw.get(pos)? as usize;
pos = std::cmp::min(pos + 1 + cnt, self.raw.len());
}
let cnt = *self.raw.get(pos)? as usize;
let start = pos + 1;
let end = std::cmp::min(start + cnt, self.raw.len());
Some(&self.raw[start..end])
}
#[inline]
pub fn iter(&self) -> KxCnRefIter<'a> {
KxCnRefIter {
raw: self.raw,
pos: self.start,
remaining: self.k,
}
}
#[inline]
pub fn as_vec(&self) -> Vec<Cow<'a, str>> {
self.iter().collect()
}
#[inline]
pub fn to_owned(&self) -> KxCn {
self.iter().map(Cow::into_owned).collect()
}
}
impl<'a> Iterator for KxCnRefIter<'a> {
type Item = Cow<'a, str>;
fn next(&mut self) -> Option<Self::Item> {
if self.remaining == 0 {
return None;
}
self.remaining -= 1;
let cnt = *self.raw.get(self.pos)? as usize;
self.pos += 1;
let end = std::cmp::min(self.pos + cnt, self.raw.len());
let slice = &self.raw[self.pos..end];
self.pos = end;
Some(bytes_to_cow_str(slice))
}
}
impl<'a> IntoIterator for &'a KxCnRef<'a> {
type Item = Cow<'a, str>;
type IntoIter = KxCnRefIter<'a>;
fn into_iter(self) -> Self::IntoIter {
self.iter()
}
}
impl<'a> KxSnRef<'a> {
#[inline]
pub fn new(raw: &'a [u8], start: usize, k: usize, order: ByteOrder) -> Self {
KxSnRef {
raw,
start,
k,
order,
}
}
#[inline]
pub fn len(&self) -> usize {
self.k
}
#[inline]
pub fn is_empty(&self) -> bool {
self.k == 0
}
#[inline]
pub fn get_str(&self, i: usize) -> Option<Cow<'a, str>> {
self.get_bytes(i).map(bytes_to_cow_str)
}
#[inline]
pub fn get_bytes(&self, i: usize) -> Option<&'a [u8]> {
if i >= self.k {
return None;
}
let mut pos = self.start;
for _ in 0..i {
let mut cp = pos;
let cnt = read_u2(self.raw, &mut cp, &self.order) as usize;
pos = std::cmp::min(cp + cnt, self.raw.len());
}
let mut cp = pos;
let cnt = read_u2(self.raw, &mut cp, &self.order) as usize;
let start = cp;
let end = std::cmp::min(start + cnt, self.raw.len());
Some(self.raw.get(start..end).unwrap_or(&[]))
}
#[inline]
pub fn iter(&self) -> KxSnRefIter<'a> {
KxSnRefIter {
raw: self.raw,
pos: self.start,
remaining: self.k,
order: self.order,
}
}
#[inline]
pub fn as_vec(&self) -> Vec<Cow<'a, str>> {
self.iter().collect()
}
#[inline]
pub fn to_owned(&self) -> KxSn {
self.iter().map(Cow::into_owned).collect()
}
}
impl<'a> Iterator for KxSnRefIter<'a> {
type Item = Cow<'a, str>;
fn next(&mut self) -> Option<Self::Item> {
if self.remaining == 0 {
return None;
}
self.remaining -= 1;
let mut cp = self.pos;
let cnt = read_u2(self.raw, &mut cp, &self.order) as usize;
self.pos = cp;
let end = std::cmp::min(self.pos + cnt, self.raw.len());
let slice = self.raw.get(self.pos..end).unwrap_or(&[]);
self.pos = end;
Some(bytes_to_cow_str(slice))
}
}
impl<'a> IntoIterator for &'a KxSnRef<'a> {
type Item = Cow<'a, str>;
type IntoIter = KxSnRefIter<'a>;
fn into_iter(self) -> Self::IntoIter {
self.iter()
}
}
impl<'a> KxCfRef<'a> {
#[inline]
pub fn new(raw: &'a [u8], start: usize, k: usize, f: usize) -> Self {
KxCfRef { raw, start, k, f }
}
#[inline]
pub fn len(&self) -> usize {
self.k
}
#[inline]
pub fn is_empty(&self) -> bool {
self.k == 0
}
#[inline]
pub fn get_str(&self, i: usize) -> Option<Cow<'a, str>> {
self.get_bytes(i).map(bytes_to_cow_str)
}
#[inline]
pub fn get_bytes(&self, i: usize) -> Option<&'a [u8]> {
if i >= self.k {
return None;
}
let start = self.start + i * self.f;
let end = std::cmp::min(start + self.f, self.raw.len());
self.raw.get(start..end)
}
#[inline]
pub fn iter(&self) -> KxCfRefIter<'a> {
KxCfRefIter {
raw: self.raw,
pos: self.start,
remaining: self.k,
f: self.f,
}
}
#[inline]
pub fn as_vec(&self) -> Vec<Cow<'a, str>> {
self.iter().collect()
}
#[inline]
pub fn to_owned(&self) -> KxCf {
self.iter().map(Cow::into_owned).collect()
}
}
impl<'a> Iterator for KxCfRefIter<'a> {
type Item = Cow<'a, str>;
fn next(&mut self) -> Option<Self::Item> {
if self.remaining == 0 {
return None;
}
self.remaining -= 1;
let end = std::cmp::min(self.pos + self.f, self.raw.len());
let slice = self.raw.get(self.pos..end).unwrap_or(&[]);
self.pos = end;
Some(bytes_to_cow_str(slice))
}
}
impl<'a> IntoIterator for &'a KxCfRef<'a> {
type Item = Cow<'a, str>;
type IntoIter = KxCfRefIter<'a>;
fn into_iter(self) -> Self::IntoIter {
self.iter()
}
}
#[inline(always)]
pub(crate) fn bytes_to_cow_str(data: &[u8]) -> Cow<'_, str> {
match std::str::from_utf8(data) {
Ok(s) => Cow::Borrowed(s),
Err(_) => Cow::Owned(data.iter().map(|&x| x as char).collect()),
}
}
#[inline(always)]
pub(crate) fn bytes_to_string(data: &[u8]) -> String {
bytes_to_cow_str(data).into_owned()
}