use crate::internal::encodings::varint::decode_prefix_varint;
use crate::prelude::*;
use std::collections::HashMap;
use std::convert::{TryFrom, TryInto};
#[derive(Debug)]
pub enum DynRootBranch<'a> {
Object {
fields: HashMap<Ident<'a>, DynRootBranch<'a>>,
},
Tuple {
fields: Vec<DynRootBranch<'a>>,
},
Enum {
discriminant: Ident<'a>,
value: Box<DynRootBranch<'a>>,
},
Array0,
Array1(Box<DynRootBranch<'a>>),
Array {
len: usize,
values: DynArrayBranch<'a>,
},
Integer(RootInteger),
Boolean(bool),
Float(RootFloat),
Void,
String(&'a str),
Map0,
Map1 {
key: Box<DynRootBranch<'a>>,
value: Box<DynRootBranch<'a>>,
},
Map {
len: usize,
keys: DynArrayBranch<'a>,
values: DynArrayBranch<'a>,
},
}
pub fn read_next_root<'a>(bytes: &'a [u8], offset: &'_ mut usize, lens: &'_ mut usize) -> ReadResult<DynRootBranch<'a>> {
let id = RootTypeId::read_next(bytes, offset)?;
fn read_tuple<'a>(num_fields: usize, bytes: &'a [u8], offset: &'_ mut usize, lens: &'_ mut usize) -> ReadResult<DynRootBranch<'a>> {
let mut fields = Vec::with_capacity(num_fields);
for _ in 0..num_fields {
let child = read_next_root(bytes, offset, lens)?;
fields.push(child);
}
Ok(DynRootBranch::Tuple { fields })
}
fn read_array<'a>(len: usize, bytes: &'a [u8], offset: &'_ mut usize, lens: &'_ mut usize) -> ReadResult<DynRootBranch<'a>> {
let values = read_next_array(bytes, offset, lens)?;
Ok(DynRootBranch::Array { len, values })
}
fn read_obj<'a>(num_fields: usize, bytes: &'a [u8], offset: &'_ mut usize, lens: &'_ mut usize) -> ReadResult<DynRootBranch<'a>> {
let mut fields = HashMap::with_capacity(num_fields);
for _ in 0..num_fields {
let name = crate::internal::read_ident(bytes, offset)?;
let child = read_next_root(bytes, offset, lens)?;
fields.insert(name, child);
}
Ok(DynRootBranch::Object { fields })
}
fn read_str<'a>(len: usize, bytes: &'a [u8], offset: &'_ mut usize) -> ReadResult<DynRootBranch<'a>> {
let bytes = read_bytes(len, bytes, offset)?;
let s = std::str::from_utf8(bytes)?;
Ok(DynRootBranch::String(s))
}
use RootTypeId::*;
let branch = match id {
Void => DynRootBranch::Void,
Tuple2 => read_tuple(2, bytes, offset, lens)?,
Tuple3 => read_tuple(3, bytes, offset, lens)?,
Tuple4 => read_tuple(4, bytes, offset, lens)?,
Tuple5 => read_tuple(5, bytes, offset, lens)?,
Tuple6 => read_tuple(6, bytes, offset, lens)?,
Tuple7 => read_tuple(7, bytes, offset, lens)?,
Tuple8 => read_tuple(8, bytes, offset, lens)?,
TupleN => read_tuple(decode_prefix_varint(bytes, offset)? as usize + 9, bytes, offset, lens)?,
Array0 => DynRootBranch::Array0,
Array1 => DynRootBranch::Array1(Box::new(read_next_root(bytes, offset, lens)?)),
ArrayN => read_array(read_usize(bytes, offset)?, bytes, offset, lens)?,
Map => {
let len = read_usize(bytes, offset)?;
match len {
0 => DynRootBranch::Map0,
1 => {
let key = read_next_root(bytes, offset, lens)?.into();
let value = read_next_root(bytes, offset, lens)?.into();
DynRootBranch::Map1 { key, value }
}
_ => {
let keys = read_next_array(bytes, offset, lens)?;
let values = read_next_array(bytes, offset, lens)?;
DynRootBranch::Map { len, keys, values }
}
}
}
Obj0 => read_obj(0, bytes, offset, lens)?,
Obj1 => read_obj(1, bytes, offset, lens)?,
Obj2 => read_obj(2, bytes, offset, lens)?,
Obj3 => read_obj(3, bytes, offset, lens)?,
Obj4 => read_obj(4, bytes, offset, lens)?,
Obj5 => read_obj(5, bytes, offset, lens)?,
Obj6 => read_obj(6, bytes, offset, lens)?,
Obj7 => read_obj(7, bytes, offset, lens)?,
Obj8 => read_obj(8, bytes, offset, lens)?,
ObjN => read_obj(decode_prefix_varint(bytes, offset)? as usize + 9, bytes, offset, lens)?,
Enum => {
let discriminant = read_ident(bytes, offset)?;
let value = read_next_root(bytes, offset, lens)?.into();
DynRootBranch::Enum { discriminant, value }
}
True => DynRootBranch::Boolean(true),
False => DynRootBranch::Boolean(false),
IntU64 => DynRootBranch::Integer(RootInteger::new(bytes, offset, 8, false)?),
IntU56 => DynRootBranch::Integer(RootInteger::new(bytes, offset, 7, false)?),
IntU48 => DynRootBranch::Integer(RootInteger::new(bytes, offset, 6, false)?),
IntU40 => DynRootBranch::Integer(RootInteger::new(bytes, offset, 5, false)?),
IntU32 => DynRootBranch::Integer(RootInteger::new(bytes, offset, 4, false)?),
IntU24 => DynRootBranch::Integer(RootInteger::new(bytes, offset, 3, false)?),
IntU16 => DynRootBranch::Integer(RootInteger::new(bytes, offset, 2, false)?),
IntU8 => DynRootBranch::Integer(RootInteger::new(bytes, offset, 1, false)?),
IntS64 => DynRootBranch::Integer(RootInteger::new(bytes, offset, 8, true)?),
IntS56 => DynRootBranch::Integer(RootInteger::new(bytes, offset, 7, true)?),
IntS48 => DynRootBranch::Integer(RootInteger::new(bytes, offset, 6, true)?),
IntS40 => DynRootBranch::Integer(RootInteger::new(bytes, offset, 5, true)?),
IntS32 => DynRootBranch::Integer(RootInteger::new(bytes, offset, 4, true)?),
IntS24 => DynRootBranch::Integer(RootInteger::new(bytes, offset, 3, true)?),
IntS16 => DynRootBranch::Integer(RootInteger::new(bytes, offset, 2, true)?),
IntS8 => DynRootBranch::Integer(RootInteger::new(bytes, offset, 1, true)?),
Zero => DynRootBranch::Integer(RootInteger::U(0)),
One => DynRootBranch::Integer(RootInteger::U(1)),
NegOne => DynRootBranch::Integer(RootInteger::S(-1)),
F32 => DynRootBranch::Float(RootFloat::F32(f32::from_le_bytes(read_bytes(4, bytes, offset)?.try_into().unwrap()))),
F64 => DynRootBranch::Float(RootFloat::F64(f64::from_le_bytes(read_bytes(8, bytes, offset)?.try_into().unwrap()))),
NaN => DynRootBranch::Float(RootFloat::NaN),
Str0 => read_str(0, bytes, offset)?,
Str1 => read_str(1, bytes, offset)?,
Str2 => read_str(2, bytes, offset)?,
Str3 => read_str(3, bytes, offset)?,
Str => read_str(decode_prefix_varint(bytes, offset)? as usize, bytes, offset)?,
};
Ok(branch)
}
impl<'a> Default for DynRootBranch<'a> {
fn default() -> Self {
DynRootBranch::Void
}
}
#[derive(Debug)]
pub enum RootInteger {
S(i64),
U(u64),
}
impl_type_id!(RootTypeId, [
Array0: 1,
Array1: 2,
ArrayN: 3,
True: 4,
False: 5,
IntU64: 6,
IntU56: 7,
IntU48: 8,
IntU40: 9,
IntU32: 10,
IntU24: 11,
IntU16: 12,
IntU8: 13,
IntS64: 14,
IntS56: 15,
IntS48: 16,
IntS40: 17,
IntS32: 18,
IntS24: 19,
IntS16: 20,
IntS8: 21,
Zero: 22,
One: 23,
NegOne: 24,
F32: 25,
F64: 26,
NaN: 27,
Str0: 28,
Str1: 29,
Str2: 30,
Str3: 31,
Str: 32,
Enum: 33,
Map: 34,
]);
impl RootInteger {
#[inline(always)]
pub fn new(bytes: &[u8], offset: &mut usize, len: usize, signed: bool) -> ReadResult<Self> {
let bytes = read_bytes(len, bytes, offset)?;
let ok = match (len, signed) {
(1, true) => Self::S((bytes[0] as i8).into()),
(1, false) => Self::U(bytes[0].into()),
(2, true) => Self::S(i16::from_le_bytes(bytes.try_into().unwrap()).into()),
(2, false) => Self::U(u16::from_le_bytes(bytes.try_into().unwrap()).into()),
(4, true) => Self::S(i32::from_le_bytes(bytes.try_into().unwrap()).into()),
(4, false) => Self::U(u32::from_le_bytes(bytes.try_into().unwrap()).into()),
(8, true) => Self::S(i64::from_le_bytes(bytes.try_into().unwrap()).into()),
(8, false) => Self::U(u64::from_le_bytes(bytes.try_into().unwrap()).into()),
_ => unreachable!(),
};
Ok(ok)
}
}
#[derive(Debug)]
pub enum RootFloat {
F64(f64),
F32(f32),
NaN,
}