297 lines
9.8 KiB
Rust
297 lines
9.8 KiB
Rust
use crate::{
|
|
runtime,
|
|
runtime::{
|
|
Reference,
|
|
kind_hasinner, type_hasinner, type_inner, type_outer,
|
|
type_key, type_innerkey, SparseHeader,
|
|
},
|
|
tag,
|
|
Type,
|
|
util::*,
|
|
};
|
|
use crate::kind;
|
|
use crate::{
|
|
Varying,
|
|
Boolean,
|
|
Natural, Integer,
|
|
Block, Sequence,
|
|
Array, List,
|
|
Record,
|
|
};
|
|
use crate::util;
|
|
|
|
pub fn encode_tag(addr:Reference) -> Vec<u8>
|
|
{
|
|
let mut type_id = addr.class;
|
|
let mut result = Vec::<u8>::new();
|
|
let mut remaining :usize = 1;
|
|
while remaining > 0 {
|
|
result.append(&mut util::pack_natural(unsafe {type_key(type_id)} as u64));
|
|
|
|
remaining -= 1;
|
|
if remaining == 0 {
|
|
remaining += unsafe {type_hasinner(type_id)};
|
|
}
|
|
type_id = unsafe {type_inner(type_id)};
|
|
}
|
|
return result;
|
|
}
|
|
|
|
pub fn encode_data(addr:Reference) -> Vec<u8>
|
|
{
|
|
let mut result = Vec::<u8>::new();
|
|
match unsafe {type_key(addr.class)} {
|
|
tag::VARYING => {
|
|
let data = Varying::from(addr).unwrap();
|
|
result.append(&mut encode(data.get()));
|
|
}
|
|
tag::BOOLEAN => {
|
|
result.append(&mut util::pack_natural(Boolean::from(addr).unwrap().get() as u64));
|
|
}
|
|
tag::NATURAL => {
|
|
result.append(&mut util::pack_natural(Natural::from(addr).unwrap().get() as u64));
|
|
}
|
|
tag::INTEGER => {
|
|
result.append(&mut &mut util::pack_integer(Integer::from(addr).unwrap().get() as i64));
|
|
}
|
|
tag::BLOCK => {
|
|
result.append(&mut Block::from(addr).unwrap().get());
|
|
}
|
|
tag::SEQUENCE => {
|
|
let data = Sequence::from(addr).unwrap();
|
|
result.append(&mut util::pack_natural(data.size() as u64));
|
|
result.append(&mut data.get_raw());
|
|
}
|
|
tag::ARRAY => {
|
|
let data = Array::from(addr).unwrap();
|
|
for i in 0..data.length() {
|
|
if unsafe {type_innerkey(addr.class)} == tag::VARYING {
|
|
result.append(&mut encode(data.at(i)));
|
|
}
|
|
else {
|
|
result.append(&mut encode_data(data.at(i)));
|
|
}
|
|
}
|
|
}
|
|
tag::LIST => {
|
|
let data = List::from(addr).unwrap();
|
|
result.append(&mut util::pack_natural(data.length() as u64));
|
|
for i in 0..data.length() {
|
|
if unsafe {type_innerkey(addr.class)} == tag::VARYING {
|
|
result.append(&mut encode(data.at(i)));
|
|
}
|
|
else {
|
|
result.append(&mut encode_data(data.at(i)));
|
|
}
|
|
}
|
|
}
|
|
tag::SPARSE => {
|
|
let data = crate::Sparse::from(addr).unwrap();
|
|
|
|
let header_length = unsafe {runtime::sparse_header_length(addr)};
|
|
|
|
result.append(&mut util::pack_natural(header_length as u64));
|
|
|
|
for i in 0..header_length {
|
|
let header = unsafe {runtime::sparse_header_data(addr, i)};
|
|
result.append(&mut util::pack_natural(header.start as u64));
|
|
result.append(&mut util::pack_natural(header.length as u64));
|
|
result.append(&mut util::pack_natural(header.index as u64));
|
|
}
|
|
|
|
for i in 0..data.length() {
|
|
if unsafe {type_innerkey(addr.class)} == tag::VARYING {
|
|
result.append(&mut encode(data.at(i)));
|
|
}
|
|
else {
|
|
result.append(&mut encode_data(data.at(i)));
|
|
}
|
|
}
|
|
}
|
|
tag::RECORD => {
|
|
let data = Record::from(addr).unwrap();
|
|
for i in 0..data.length() {
|
|
if kind(data.kindof(i)) == tag::VARYING {
|
|
result.append(&mut encode(data.at(i)));
|
|
}
|
|
else {
|
|
result.append(&mut encode_data(data.at(i)));
|
|
}
|
|
}
|
|
}
|
|
_ => { }
|
|
}
|
|
return result;
|
|
}
|
|
|
|
pub fn encode(addr:Reference) -> Vec<u8>
|
|
{
|
|
let mut result = encode_tag(addr);
|
|
result.append(&mut encode_data(addr));
|
|
return result;
|
|
}
|
|
|
|
pub fn decode_tag(data:&Vec<u8>, index:&mut usize) -> Result<usize,()>
|
|
{
|
|
let mut tags = Vec::<usize>::new();
|
|
let mut remaining :usize = 1;
|
|
while remaining > 0 && *index < data.len() {
|
|
let kind = util::unpack_natural(&data, index) as usize;
|
|
tags.push(kind);
|
|
|
|
remaining -= 1;
|
|
if remaining == 0 {
|
|
remaining += unsafe {kind_hasinner(kind)};
|
|
}
|
|
}
|
|
let mut type_id = 0;
|
|
for i in (0..tags.len()).rev() {
|
|
type_id = unsafe {type_outer(type_id, tags[i])};
|
|
}
|
|
|
|
return if remaining == 0 { Ok(type_id) }
|
|
else { Err(()) }
|
|
}
|
|
|
|
pub fn decode_data(data:&Vec<u8>, type_id:usize, index:&mut usize) -> Result<Type,()>
|
|
{
|
|
match unsafe {type_key(type_id)} {
|
|
tag::VARYING => {
|
|
return match decode(data, index) {
|
|
Ok(value) => {
|
|
Ok(Type::Varying(Varying::with(value.get())))
|
|
}
|
|
Err(_) => Err(()),
|
|
}
|
|
}
|
|
tag::BOOLEAN => {
|
|
return Ok(Type::Boolean(Boolean::with(unpack_natural(data, index) == 1)));
|
|
}
|
|
tag::NATURAL => {
|
|
return Ok(Type::Natural(Natural::with(unpack_natural(data, index))));
|
|
}
|
|
tag::INTEGER => {
|
|
return Ok(Type::Integer(Integer::with(unpack_integer(data, index))));
|
|
}
|
|
tag::BLOCK => {
|
|
let size = unsafe {type_innerkey(type_id)};
|
|
let mut bytes = Vec::<u8>::with_capacity(size);
|
|
if *index + size <= data.len() {
|
|
for _ in 0..size {
|
|
bytes.push(data[*index]);
|
|
*index += 1;
|
|
}
|
|
}
|
|
return Ok(Type::Block(Block::with(size, bytes)));
|
|
}
|
|
tag::SEQUENCE => {
|
|
let size = unpack_natural(data, index) as usize;
|
|
let mut bytes = Vec::<u8>::with_capacity(size);
|
|
if *index + size <= data.len() {
|
|
for _ in 0..size {
|
|
bytes.push(data[*index]);
|
|
*index += 1;
|
|
}
|
|
}
|
|
return Ok(Type::Sequence(Sequence::with_raw(bytes)));
|
|
}
|
|
tag::ARRAY => {
|
|
let length = unsafe {type_innerkey(type_id)};
|
|
let inner = unsafe {type_inner(type_inner(type_id))};
|
|
|
|
let mut result = Array::new(length, inner);
|
|
for i in 0..length {
|
|
match if unsafe {type_key(inner)} == tag::VARYING {
|
|
decode(data, index)
|
|
} else {
|
|
decode_data(data, inner, index)
|
|
} {
|
|
Ok(data) => { result.set(i, data.get()); }
|
|
Err(_) => { return Err(()); }
|
|
}
|
|
}
|
|
|
|
return Ok(Type::Array(result));
|
|
}
|
|
tag::LIST => {
|
|
let inner = unsafe {type_inner(type_id)};
|
|
let length = util::unpack_natural(data, index) as usize;
|
|
|
|
let mut result = List::new(inner);
|
|
result.reserve(length);
|
|
|
|
for _ in 0..length {
|
|
match if unsafe {type_key(inner)} == tag::VARYING {
|
|
decode(data, index)
|
|
} else {
|
|
decode_data(data, inner, index)
|
|
} {
|
|
Ok(data) => { result.append(data.get()); }
|
|
Err(_) => { return Err(()); }
|
|
}
|
|
}
|
|
|
|
return Ok(Type::List(result));
|
|
}
|
|
tag::SPARSE => {
|
|
let inner = unsafe {type_inner(type_id)};
|
|
let mut result = crate::Sparse::new(inner);
|
|
|
|
let header_length = util::unpack_natural(data, index) as usize;
|
|
let mut headers = Vec::<SparseHeader>::with_capacity(header_length);
|
|
|
|
for _ in 0..header_length {
|
|
headers.push(runtime::SparseHeader {
|
|
start:util::unpack_natural(data, index) as usize,
|
|
length:util::unpack_natural(data, index) as usize,
|
|
index:util::unpack_natural(data, index) as usize,
|
|
});
|
|
}
|
|
|
|
for header in headers {
|
|
for i in 0..header.length {
|
|
match if unsafe {type_key(inner)} == tag::VARYING {
|
|
decode(data, index)
|
|
} else {
|
|
decode_data(data, inner, index)
|
|
} {
|
|
Ok(data) => {
|
|
result.set(header.start + i, data.get());
|
|
}
|
|
Err(_) => { return Err(()); }
|
|
}
|
|
}
|
|
}
|
|
|
|
return Ok(Type::Sparse(result));
|
|
}
|
|
tag::RECORD => {
|
|
return match Record::new(unsafe {type_innerkey(type_id)}) {
|
|
Ok(mut value) => {
|
|
for i in 0..value.length() {
|
|
match decode_data(data, value.kindof(i), index) {
|
|
Ok(refer) => {
|
|
value.set_at(i, refer.get());
|
|
}
|
|
Err(_) => return Err(())
|
|
}
|
|
}
|
|
Ok(Type::Record(value))
|
|
}
|
|
Err(_) => Err(()),
|
|
}
|
|
}
|
|
_ => { }
|
|
}
|
|
|
|
return Err(());
|
|
}
|
|
|
|
pub fn decode(data:&Vec<u8>, index:&mut usize) -> Result<Type,()>
|
|
{
|
|
return match decode_tag(data, index) {
|
|
Ok(type_id) => decode_data(data, type_id, index),
|
|
_ => Err(()),
|
|
}
|
|
}
|