use crate::primitive::*;
use crate::{code, unpack, value, value::Value, UnpackError};
use std::io;
pub fn unpack_bin_data<R: io::Read>(reader: &mut R, len: usize) -> Result<Vec<u8>, UnpackError> {
let mut buf = Vec::with_capacity(len);
buf.resize(len as usize, 0u8);
read_data(reader, &mut buf[..])?;
Ok(buf)
}
pub fn unpack_ary_data<R: io::Read>(reader: &mut R, len: usize) -> Result<Vec<Value>, UnpackError> {
let mut vec = Vec::with_capacity(len);
for _ in 0..len {
vec.push(unpack_value(reader)?);
}
Ok(vec)
}
pub fn unpack_str_data<R: io::Read>(
reader: &mut R,
len: usize,
) -> Result<value::Utf8String, UnpackError> {
let buf = unpack_bin_data(reader, len)?;
Ok(value::Utf8String::from(buf))
}
pub fn unpack_map_data<R: io::Read>(
reader: &mut R,
len: usize,
) -> Result<Vec<(Value, Value)>, UnpackError> {
let mut vec = Vec::with_capacity(len);
for _ in 0..len {
vec.push((unpack_value(reader)?, unpack_value(reader)?));
}
Ok(vec)
}
fn unpack_ext_type_data<R: io::Read>(
reader: &mut R,
len: usize,
) -> Result<(i8, Vec<u8>), UnpackError> {
let ty = read_data_i8(reader)?;
let vec = unpack_bin_data(reader, len)?;
Ok((ty, vec))
}
pub fn unpack_bin<R>(reader: &mut R) -> Result<Vec<u8>, UnpackError>
where
R: io::Read,
{
let len = unpack::unpack_bin_header(reader)?;
unpack_bin_data(reader, len)
}
pub fn unpack_value<R>(reader: &mut R) -> Result<Value, UnpackError>
where
R: io::Read,
{
use code::Code;
let val = match read_code(reader)? {
Code::Nil => Value::Nil,
Code::True => Value::from(true),
Code::False => Value::from(false),
Code::PosInt(v) => Value::from(v),
Code::Uint8 => Value::from(read_data_u8(reader)?),
Code::Uint16 => Value::from(read_data_u16(reader)?),
Code::Uint32 => Value::from(read_data_u32(reader)?),
Code::Uint64 => Value::from(read_data_u64(reader)?),
Code::NegInt(v) => Value::from(v),
Code::Int8 => Value::from(read_data_i8(reader)?),
Code::Int16 => Value::from(read_data_i16(reader)?),
Code::Int32 => Value::from(read_data_i32(reader)?),
Code::Int64 => Value::from(read_data_i64(reader)?),
Code::Float32 => Value::from(read_data_f32(reader)?),
Code::Float64 => Value::from(read_data_f64(reader)?),
Code::Bin8 => {
let len = usize::from(read_data_u8(reader)?);
Value::Binary(unpack_bin_data(reader, len)?)
}
Code::Bin16 => {
let len = usize::from(read_data_u16(reader)?);
Value::Binary(unpack_bin_data(reader, len)?)
}
Code::Bin32 => {
let len = read_data_u32(reader)? as usize;
Value::Binary(unpack_bin_data(reader, len)?)
}
Code::FixStr(len) => Value::String(unpack_str_data(reader, usize::from(len))?),
Code::Str8 => {
let len = usize::from(read_data_u8(reader)?);
Value::String(unpack_str_data(reader, len)?)
}
Code::Str16 => {
let len = usize::from(read_data_u16(reader)?);
Value::String(unpack_str_data(reader, len)?)
}
Code::Str32 => {
let len = read_data_u32(reader)?;
Value::String(unpack_str_data(reader, len as usize)?)
}
Code::FixArray(len) => Value::Array(unpack_ary_data(reader, len as usize)?),
Code::Array16 => {
let len = usize::from(read_data_u16(reader)?);
Value::Array(unpack_ary_data(reader, len)?)
}
Code::Array32 => {
let len = read_data_u32(reader)? as usize;
Value::Array(unpack_ary_data(reader, len)?)
}
Code::FixMap(len) => Value::Map(unpack_map_data(reader, len as usize)?),
Code::Map16 => {
let len = usize::from(read_data_u16(reader)?);
Value::Map(unpack_map_data(reader, len)?)
}
Code::Map32 => {
let len = read_data_u16(reader)? as usize;
Value::Map(unpack_map_data(reader, len)?)
}
Code::FixExt1 => {
let (ty, vec) = unpack_ext_type_data(reader, 1)?;
Value::Extension(ty, vec)
}
Code::FixExt2 => {
let (ty, vec) = unpack_ext_type_data(reader, 2)?;
Value::Extension(ty, vec)
}
Code::FixExt4 => {
let (ty, vec) = unpack_ext_type_data(reader, 4)?;
Value::Extension(ty, vec)
}
Code::FixExt8 => {
let (ty, vec) = unpack_ext_type_data(reader, 8)?;
Value::Extension(ty, vec)
}
Code::FixExt16 => {
let (ty, vec) = unpack_ext_type_data(reader, 16)?;
Value::Extension(ty, vec)
}
Code::Ext8 => {
let len = usize::from(read_data_u8(reader)?);
let (ty, vec) = unpack_ext_type_data(reader, len)?;
Value::Extension(ty, vec)
}
Code::Ext16 => {
let len = usize::from(read_data_u16(reader)?);
let (ty, vec) = unpack_ext_type_data(reader, len)?;
Value::Extension(ty, vec)
}
Code::Ext32 => {
let len = read_data_u32(reader)? as usize;
let (ty, vec) = unpack_ext_type_data(reader, len)?;
Value::Extension(ty, vec)
}
Code::Reserved => unreachable!(),
};
Ok(val)
}