use std::convert::From;
use std::default::Default;
use std::fmt::Debug;
use std::mem;
use std::ops::Deref;
use crate::{
binary::{Any, Deserialize, Number, Serialize},
error::{DaptResult, Error},
};
pub const TYPE_REFERENCE: u8 = 0;
pub const TYPE_MAP: u8 = 1;
pub const TYPE_ARRAY: u8 = 2;
pub const TYPE_KEYVAL: u8 = 3;
const REFERENCE_LENGTH: usize = 5;
pub const MAX_REFERENCE_DEPTH: isize = 20;
const TYPE_OFFSET: usize = 0;
const TYPE_WIDTH: usize = 1;
const TYPE_OFFSET_END: usize = TYPE_OFFSET + TYPE_WIDTH;
const LENGTH_OFFSET: usize = TYPE_OFFSET_END;
const LENGTH_WIDTH: usize = 2;
const LENGTH_OFFSET_END: usize = LENGTH_OFFSET + LENGTH_WIDTH;
const REFERENCE_OFFSET: usize = LENGTH_OFFSET_END;
const REFERENCE_WIDTH: usize = 4;
const REFERENCE_OFFSET_END: usize = REFERENCE_OFFSET + REFERENCE_WIDTH;
const PARENT_OFFSET: usize = REFERENCE_OFFSET_END;
const PARENT_WIDTH: usize = 4;
const PARENT_OFFSET_END: usize = PARENT_OFFSET + PARENT_WIDTH;
const CONTENT_OFFSET: usize = PARENT_OFFSET_END;
const PTR_OFFSET: usize = TYPE_OFFSET_END;
const PTR_WIDTH: usize = 4;
const PTR_OFFSET_END: usize = PTR_OFFSET + PTR_WIDTH;
const ADD_TOKEN_HEADER_LENGTH: usize = CONTENT_OFFSET;
const INITAL_BINARY_SIZE: usize = 1024;
#[derive(Clone)]
pub struct Binary(Vec<u8>);
impl Debug for Binary {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let mut head = 0;
loop {
let token = BToken::from(head);
if token.get_type(&self) == TYPE_REFERENCE {
let bref = BReference::from(token);
bref.dump(&self, f)?;
head += REFERENCE_LENGTH;
} else {
token.dump(&self, f)?;
head += token.get_length(self);
}
if head >= self.0.len() {
break;
}
}
Ok(())
}
}
impl Binary {
fn grow(&mut self, size: usize) -> (usize, &mut [u8]) {
let index = self.0.len();
self.0.resize(index + size, 0);
(index, self.at_mut(index, size))
}
fn copy(&mut self, b: BToken, delta: usize) -> (usize, &mut [u8]) {
let index = self.0.len();
let size = b.get_length(self);
for i in 0..size {
self.0.push(self.0[*b + i]);
}
let b = BToken::from(index);
b.set_length(self, size + delta);
BReference::from(b.get_reference(self)).set_index(self, index);
let (_, buf) = self.grow(delta);
(index, buf)
}
fn at(&self, index: usize, width: usize) -> &[u8] {
self.0.get(index..index + width).unwrap()
}
fn at_mut(&mut self, index: usize, width: usize) -> &mut [u8] {
self.0.get_mut(index..index + width).unwrap()
}
pub fn token_at(&self, index: BReference) -> Option<BToken> {
index.resolve(self, MAX_REFERENCE_DEPTH)
}
pub fn add<T: Serialize>(&mut self, parent: Option<BReference>, content: T) -> BReference {
let size = content.size_of();
let (bref, tok) = BToken::new(parent, size, 0, self);
let t = content.serialize(self.at_mut(*tok + CONTENT_OFFSET, size));
tok.set_type(self, t);
bref
}
pub fn add_any(&mut self, parent: Option<BReference>, content: Any) -> BReference {
match content {
Any::U8(val) => self.add(parent, val),
Any::U16(val) => self.add(parent, val),
Any::U32(val) => self.add(parent, val),
Any::U64(val) => self.add(parent, val),
Any::U128(val) => self.add(parent, val),
Any::USize(val) => self.add(parent, val),
Any::I8(val) => self.add(parent, val),
Any::I16(val) => self.add(parent, val),
Any::I32(val) => self.add(parent, val),
Any::I64(val) => self.add(parent, val),
Any::I128(val) => self.add(parent, val),
Any::ISize(val) => self.add(parent, val),
Any::F32(val) => self.add(parent, val),
Any::F64(val) => self.add(parent, val),
Any::Str(val) => self.add(parent, val),
Any::String(val) => self.add(parent, val),
Any::Bool(val) => self.add(parent, val),
Any::Char(val) => self.add(parent, val),
Any::Bytes(val) => self.add(parent, val),
Any::VecBytes(val) => self.add(parent, val),
Any::Null => self.add(parent, ()),
Any::Array(val) => {
let mut children: Vec<BReference> = Vec::with_capacity(val.len());
for v in val {
children.push(self.add_any(parent, v));
}
let (bref, _) = BArray::new(parent, &children[..], self);
bref
}
Any::Map(val) => {
let mut children: Vec<BReference> = Vec::with_capacity(val.len());
for (k, v) in val {
let child = self.add_any(parent, v);
let (bref, _token) = BKeyValue::new(parent, child, k, self);
children.push(bref);
}
let (bref, _) = BMap::new(parent, &children[..], self);
bref
}
Any::StringMap(val) => {
let mut children: Vec<BReference> = Vec::with_capacity(val.len());
for (k, v) in val {
let child = self.add_any(parent, v);
let (bref, _token) = BKeyValue::new(parent, child, k.as_str(), self);
children.push(bref);
}
let (bref, _) = BMap::new(parent, &children[..], self);
bref
}
}
}
pub fn get<'a, T: Deserialize<'a>>(&'a self, index: BReference) -> Option<T::Item> {
let token = index.val_at(self)?;
if token.get_type(self) != T::type_of() {
return None;
}
Some(T::deserialize(token.get_content(self)))
}
pub fn get_key<'a>(&'a self, index: BReference) -> Option<&'a str> {
Some(index.key_at(self)?.key(self))
}
pub fn str<'a>(&'a self, index: BReference) -> Option<&'a str> {
self.get::<&'a str>(index)
}
pub fn number(&self, index: BReference) -> DaptResult<Number> {
let token = index.val_at(self).ok_or(Error::InvalidIndex(
"invalid index when finding number".into(),
))?;
Number::new(self, token)
}
pub fn any(&self, index: BReference) -> Option<Any> {
let token = index.val_at(self)?;
Any::new(self, token)
}
}
impl Default for Binary {
fn default() -> Self {
let mut b = Vec::with_capacity(INITAL_BINARY_SIZE);
b.push(TYPE_REFERENCE);
b.resize(REFERENCE_LENGTH, 0);
Binary(b)
}
}
#[derive(PartialEq, Debug, Copy, Clone)]
pub struct BReference(usize);
impl BReference {
fn new(bin: &mut Binary) -> BReference {
let (index, buf) = bin.grow(REFERENCE_LENGTH);
let t = buf.first_mut().expect("breference buf empty! can't fill.");
*t = TYPE_REFERENCE;
let u = (index + REFERENCE_LENGTH) as u32;
u.serialize(buf.get_mut(PTR_OFFSET..PTR_OFFSET_END).unwrap());
BReference(index)
}
fn get_index(&self, bin: &Binary) -> Option<BToken> {
let buf = bin.at(self.0 + PTR_OFFSET, PTR_WIDTH);
let num = u32::deserialize(buf);
if num == 0 {
None
} else {
Some(BToken::from(num))
}
}
pub fn set_index(&self, bin: &mut Binary, index: usize) {
(index as u32).serialize(bin.at_mut(self.0 + PTR_OFFSET, PTR_WIDTH));
}
pub fn resolve(&self, bin: &Binary, max_depth: isize) -> Option<BToken> {
if max_depth <= 0 {
return None;
}
let tok = self.get_index(bin)?;
if tok.get_type(bin) == TYPE_REFERENCE {
return BReference::from(tok).resolve(bin, max_depth - 1);
}
Some(tok)
}
pub fn val_at(&self, bin: &Binary) -> Option<BToken> {
let token = self.resolve(bin, MAX_REFERENCE_DEPTH)?;
match token.get_type(bin) {
TYPE_KEYVAL => {
let key_value: BKeyValue = token.try_into().ok()?;
key_value.child(bin)?.val_at(bin)
}
_ => Some(token),
}
}
pub fn key_at(&self, bin: &Binary) -> Option<BKeyValue> {
let token = self.resolve(bin, MAX_REFERENCE_DEPTH)?;
match token.get_type(bin) {
TYPE_KEYVAL => Some(BKeyValue::from(token)),
_ => token.get_parent(bin)?.key_at(bin),
}
}
pub fn token_at(&self, bin: &Binary) -> Option<BToken> {
self.resolve(bin, MAX_REFERENCE_DEPTH)
}
pub fn walk<'a, F>(&self, bin: &'a Binary, f: &mut F) -> bool
where
F: FnMut(BReference) -> bool,
{
let t = match self.val_at(bin) {
None => return true,
Some(t) => t,
};
match t.get_type(bin) {
TYPE_ARRAY => {
if !f(*self) {
return false;
}
let bcoll = BArray::from(t);
for i in 0..bcoll.length(bin) {
let b = bcoll.child_index(bin, i).unwrap();
if !b.walk(bin, f) {
return false;
}
}
true
}
TYPE_MAP => {
if !f(*self) {
return false;
}
let bcoll = BMap::from(t);
for i in 0..bcoll.length(bin) {
let b = bcoll.child_index(bin, i).unwrap();
if !b.walk(bin, f) {
return false;
}
}
true
}
_ => f(*self),
}
}
pub fn dump<'a>(
&self,
bin: &'a Binary,
f: &mut std::fmt::Formatter<'_>,
) -> Result<(), std::fmt::Error> {
write!(
f,
"// {} BReference {:?}\n",
self.0,
bin.at(self.0 + TYPE_OFFSET, TYPE_WIDTH)
)?;
write!(
f,
"{:?} // Reference {:?}\n",
bin.at(self.0 + PTR_OFFSET, PTR_WIDTH),
self.get_index(bin),
)?;
write!(f, "\n")?;
Ok(())
}
}
impl From<BToken> for BReference {
fn from(tok: BToken) -> Self {
BReference(tok.0)
}
}
impl From<usize> for BReference {
fn from(index: usize) -> Self {
BReference(index)
}
}
impl From<u32> for BReference {
fn from(index: u32) -> Self {
BReference(index as usize)
}
}
impl From<i32> for BReference {
fn from(index: i32) -> Self {
BReference(index as usize)
}
}
impl Deref for BReference {
type Target = usize;
fn deref(&self) -> &Self::Target {
&self.0
}
}
#[derive(PartialEq, Debug, Clone, Copy)]
pub struct BToken(usize);
impl From<usize> for BToken {
fn from(index: usize) -> Self {
BToken(index)
}
}
impl From<u32> for BToken {
fn from(index: u32) -> Self {
BToken(index as usize)
}
}
impl From<BReference> for BToken {
fn from(bref: BReference) -> Self {
BToken(bref.0)
}
}
impl From<BMap> for BToken {
fn from(b: BMap) -> Self {
BToken(b.0)
}
}
impl From<BArray> for BToken {
fn from(b: BArray) -> Self {
BToken(b.0)
}
}
impl From<BKeyValue> for BToken {
fn from(b: BKeyValue) -> Self {
BToken(b.0)
}
}
impl Deref for BToken {
type Target = usize;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl BToken {
fn new(
parent_index: Option<BReference>,
content_length: usize,
tpe: u8,
bin: &mut Binary,
) -> (BReference, BToken) {
let bref = BReference::new(bin);
let (index, buf) = bin.grow(ADD_TOKEN_HEADER_LENGTH + content_length);
let t = buf.first_mut().unwrap();
*t = tpe;
let size = (ADD_TOKEN_HEADER_LENGTH + content_length) as u16;
size.serialize(
buf.get_mut(LENGTH_OFFSET..LENGTH_OFFSET_END)
.expect("btoken buf not large enough"),
);
(*bref as u32).serialize(
buf.get_mut(REFERENCE_OFFSET..REFERENCE_OFFSET_END)
.expect("btoken buf not large enough"),
);
let parent_index = parent_index.unwrap_or(BReference(0));
(*parent_index as u32).serialize(
buf.get_mut(PARENT_OFFSET..PARENT_OFFSET_END)
.expect("btoken not large enough"),
);
(bref, BToken(index))
}
pub fn get_parent(&self, bin: &Binary) -> Option<BReference> {
let result = u32::deserialize(bin.at(**self + PARENT_OFFSET, PARENT_WIDTH));
if result == 0 {
None
} else {
Some(BReference::from(result))
}
}
pub fn set_parent(&self, bin: &mut Binary, bref: BReference) {
(*bref as u32).serialize(bin.at_mut(**self + PARENT_OFFSET, PARENT_WIDTH));
}
pub fn get_reference(&self, bin: &Binary) -> BReference {
BReference::from(u32::deserialize(
bin.at(**self + REFERENCE_OFFSET, REFERENCE_WIDTH),
))
}
pub fn set_reference(&self, bin: &mut Binary, bref: BReference) {
(*bref as u32).serialize(bin.at_mut(**self + REFERENCE_OFFSET, REFERENCE_WIDTH));
}
pub fn get_type(&self, bin: &Binary) -> u8 {
bin.at(**self, TYPE_WIDTH)[0]
}
pub fn set_type(&self, bin: &mut Binary, t: u8) {
bin.at_mut(**self, TYPE_WIDTH)[0] = t;
}
pub fn get_length(&self, bin: &Binary) -> usize {
u16::deserialize(bin.at(**self + LENGTH_OFFSET, LENGTH_WIDTH)) as usize
}
pub fn set_length(&self, bin: &mut Binary, size: usize) {
(size as u16).serialize(bin.at_mut(**self + LENGTH_OFFSET, LENGTH_WIDTH));
}
pub fn get_content<'a>(&self, bin: &'a Binary) -> &'a [u8] {
let length = self.get_length(bin) - CONTENT_OFFSET;
bin.at(**self + CONTENT_OFFSET, length)
}
pub fn is_type(&self, bin: &Binary, t: u8) -> bool {
self.get_type(bin) == t
}
pub fn dump<'a>(
&self,
bin: &'a Binary,
f: &mut std::fmt::Formatter<'_>,
) -> Result<(), std::fmt::Error> {
write!(
f,
"// {} BToken {:?}\n",
self.0,
bin.at(self.0 + TYPE_OFFSET, TYPE_WIDTH)
)?;
write!(
f,
"{:?} // Length: {}\n",
bin.at(self.0 + LENGTH_OFFSET, LENGTH_WIDTH),
self.get_length(bin),
)?;
write!(
f,
"{:?} // Reference: {}\n",
bin.at(self.0 + REFERENCE_OFFSET, REFERENCE_WIDTH),
*self.get_reference(bin),
)?;
write!(
f,
"{:?} // Parent: {:?}\n",
bin.at(self.0 + PARENT_OFFSET, PARENT_WIDTH),
self.get_parent(bin),
)?;
match self.get_type(bin) {
TYPE_ARRAY => BArray::from(*self).dump(bin, f),
TYPE_MAP => BMap::from(*self).dump(bin, f),
TYPE_KEYVAL => BKeyValue::from(*self).dump(bin, f),
_ => write!(
f,
"{:?} // Content: {:?}\n",
bin.at(
self.0 + CONTENT_OFFSET,
self.get_length(bin) - CONTENT_OFFSET
),
bin.any(self.get_reference(bin))
),
}?;
write!(f, "\n")
}
}
#[derive(PartialEq, Debug, Clone, Copy)]
pub struct BMap(usize);
impl From<BToken> for BMap {
fn from(b: BToken) -> Self {
BMap(b.0)
}
}
impl Deref for BMap {
type Target = usize;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl BMap {
pub fn new(
parent_index: Option<BReference>,
children: &[BReference],
bin: &mut Binary,
) -> (BReference, BMap) {
let size = mem::size_of::<u32>();
let (bref, token) = BToken::new(parent_index, size * children.len(), TYPE_MAP, bin);
for (i, v) in children.iter().enumerate() {
let child_content_index = *token + CONTENT_OFFSET + (i * size);
(**v as u32).serialize(bin.at_mut(child_content_index, 4));
v.resolve(&bin, MAX_REFERENCE_DEPTH)
.unwrap()
.set_parent(bin, bref);
}
(bref, token.into())
}
pub fn child_index(&self, bin: &Binary, index: usize) -> Option<BReference> {
if index >= self.length(bin) {
return None;
}
let index = **self + CONTENT_OFFSET + (index * mem::size_of::<u32>());
let child_index = u32::deserialize(bin.at(index, mem::size_of::<u32>()));
Some(BReference::from(child_index))
}
pub fn child_indexes(&self, bin: &Binary, ptrs: &mut [BReference]) {
for i in 0..self.length(bin) {
let child_content_index = self.child_index(bin, i);
match child_content_index {
None => return,
Some(c) => ptrs[i] = c,
}
}
}
pub fn child_key(&self, key: &str, bin: &Binary) -> Option<BReference> {
for i in 0.. {
let child_content_index = self.child_index(bin, i)?;
let child: BKeyValue = child_content_index.key_at(bin)?;
if child.key(bin) == key {
return Some(child_content_index);
}
}
None
}
pub fn length(&self, bin: &Binary) -> usize {
(BToken::from(*self).get_length(bin) - CONTENT_OFFSET) / mem::size_of::<u32>()
}
pub fn add_child(&self, child: BReference, bin: &mut Binary) {
let (_index, buf) = bin.copy(BToken::from(*self), mem::size_of::<u32>());
(*child as u32).serialize(buf);
}
pub fn dump<'a>(
&self,
bin: &'a Binary,
f: &mut std::fmt::Formatter<'_>,
) -> Result<(), std::fmt::Error> {
write!(f, "// BMap Content {:?}\n", self.0,)?;
for i in 0..self.length(bin) {
let index = **self + CONTENT_OFFSET + (i * mem::size_of::<u32>());
write!(
f,
"{:?} // Child: {:?}\n",
bin.at(index, mem::size_of::<u32>()),
self.child_index(bin, i).unwrap()
)?;
}
write!(f, "\n")
}
}
#[derive(PartialEq, Debug, Clone, Copy)]
pub struct BKeyValue(usize);
impl<'a> From<BToken> for BKeyValue {
fn from(b: BToken) -> Self {
BKeyValue(b.0)
}
}
impl Deref for BKeyValue {
type Target = usize;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl BKeyValue {
pub fn new(
parent_index: Option<BReference>,
child: BReference,
key: &str,
bin: &mut Binary,
) -> (BReference, BKeyValue) {
let size = mem::size_of::<u32>() + key.len();
let (bref, token) = BToken::new(parent_index, size, TYPE_KEYVAL, bin);
(*child as u32).serialize(bin.at_mut(*token + CONTENT_OFFSET, PTR_WIDTH));
if let Some(child) = child.resolve(bin, MAX_REFERENCE_DEPTH) {
child.set_parent(bin, bref);
}
key.serialize(bin.at_mut(*token + CONTENT_OFFSET + mem::size_of::<u32>(), key.len()));
(bref, token.into())
}
pub fn child(&self, bin: &Binary) -> Option<BReference> {
match u32::deserialize(bin.at(**self + CONTENT_OFFSET, mem::size_of::<u32>())) {
0 => None,
v => Some(BReference::from(v)),
}
}
pub fn key<'a>(&self, bin: &'a Binary) -> &'a str {
let header = CONTENT_OFFSET + mem::size_of::<u32>();
<&'a str as Deserialize>::deserialize(bin.at(
**self + header,
BToken::from(*self).get_length(bin) - header,
))
}
pub fn set_child(&self, child: BReference, bin: &mut Binary) {
(*child as u32).serialize(bin.at_mut(**self + CONTENT_OFFSET, mem::size_of::<u32>()));
}
pub fn dump<'a>(
&self,
bin: &'a Binary,
f: &mut std::fmt::Formatter<'_>,
) -> Result<(), std::fmt::Error> {
write!(f, "// BKeyValue Content {:?}\n", self.0,)?;
write!(
f,
"{:?} // Child: {:?}\n",
bin.at(**self + CONTENT_OFFSET, mem::size_of::<u32>()),
self.child(bin)
)?;
write!(
f,
"{:?} // Key: {:?}\n",
bin.at(
**self + CONTENT_OFFSET + mem::size_of::<u32>(),
BToken::from(*self).get_length(bin) - CONTENT_OFFSET - mem::size_of::<u32>()
),
self.key(bin)
)?;
write!(f, "\n")
}
}
#[derive(PartialEq, Debug, Clone, Copy)]
pub struct BArray(usize);
impl From<BToken> for BArray {
fn from(b: BToken) -> Self {
BArray(b.0)
}
}
impl Deref for BArray {
type Target = usize;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl BArray {
pub fn new(
parent_index: Option<BReference>,
children: &[BReference],
bin: &mut Binary,
) -> (BReference, BArray) {
let size = mem::size_of::<u32>();
let (bref, token) = BToken::new(parent_index, size * children.len(), TYPE_ARRAY, bin);
for (i, v) in children.iter().enumerate() {
let child_content_index = *token + CONTENT_OFFSET + (i * size);
(**v as u32).serialize(bin.at_mut(child_content_index, size));
v.resolve(bin, MAX_REFERENCE_DEPTH)
.unwrap()
.set_parent(bin, bref);
}
(bref, token.into())
}
pub fn child_index(&self, bin: &Binary, index: usize) -> Option<BReference> {
if index >= self.length(bin) {
return None;
}
let index = **self + CONTENT_OFFSET + (index * mem::size_of::<u32>());
let child_index = u32::deserialize(bin.at(index, mem::size_of::<u32>()));
Some(BReference::from(child_index))
}
pub fn child_indexes(&self, bin: &Binary, ptrs: &mut [BReference]) {
for i in 0..self.length(bin) {
let child = self.child_index(bin, i);
match child {
None => return,
Some(c) => ptrs[i] = c,
}
}
}
pub fn length(&self, bin: &Binary) -> usize {
(BToken::from(*self).get_length(bin) - CONTENT_OFFSET) / mem::size_of::<u32>()
}
pub fn dump<'a>(
&self,
bin: &'a Binary,
f: &mut std::fmt::Formatter<'_>,
) -> Result<(), std::fmt::Error> {
write!(f, "\tBArray Content {:?}\n", self.0,)?;
for i in 0..self.length(bin) {
let index = **self + CONTENT_OFFSET + (i * mem::size_of::<u32>());
write!(
f,
"\t\t{:?} Child: {:?}\n",
bin.at(index, mem::size_of::<u32>()),
self.child_index(bin, i).unwrap()
)?;
}
write!(f, "\t>\n")
}
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn test_breference() {
let mut bin = Binary::default();
let bref = BReference::new(&mut bin);
assert_eq!(bref.get_index(&bin).unwrap(), BToken(10));
}
#[test]
fn test_btoken() {
let mut bin = Binary::default();
let (_bref, tok) = BToken::new(Some(BReference(2)), 0, 1, &mut bin);
assert_eq!(tok.get_type(&bin), 1);
assert_eq!(tok.get_parent(&bin), Some(BReference(2)));
assert_eq!(tok.get_reference(&bin), BReference(5));
}
macro_rules! test_binary_obj {
($type:ty, $value:expr) => {{
let mut b = Binary::default();
let val: $type = $value;
let i = b.add(None, val);
let new_val: $type = b.get::<$type>(i).unwrap();
assert_eq!(val, new_val);
}};
}
macro_rules! test_string_obj {
($value:expr) => {{
let mut b = Binary::default();
let val = String::from($value);
let i = b.add(None, val.as_str());
let new_val: &str = b.get::<&str>(i).unwrap();
assert_eq!(val.as_str(), new_val);
}};
}
#[test]
fn test_binary_numbers() {
test_binary_obj!(u8, 100);
test_binary_obj!(u16, 100);
test_binary_obj!(u32, 100);
test_binary_obj!(u64, 100);
}
#[test]
fn test_binary_strings() {
test_string_obj!("hello");
test_string_obj!("This is a very long string that is quite long");
}
#[test]
fn test_collection() {
let mut children: Vec<BReference> = vec![];
let mut b = Binary::default();
for i in 0..10 {
children.push(b.add(None, i as usize));
}
let (_bref, array) = BArray::new(None, &children[..], &mut b);
for i in 0..array.length(&b) {
assert_eq!(
i,
b.get::<usize>(array.child_index(&b, i).unwrap()).unwrap()
)
}
}
#[test]
fn test_object() {
let mut children: Vec<BReference> = vec![];
let mut b = Binary::default();
for i in 0..10 {
let bref = b.add(None, i);
let (bref, _token) = BKeyValue::new(None, bref, &format!("child_{i}"), &mut b);
children.push(bref);
}
let (_bref, map) = BMap::new(None, &children, &mut b);
for i in 0..map.length(&b) {
let child_index = map.child_key(&format!("child_{i}"), &b).unwrap();
let child_val: usize = b.number(child_index).unwrap().into();
assert_eq!(child_val, i);
}
}
macro_rules! test_any_string {
($value:expr, $val:expr) => {{
let mut b = Binary::default();
let i = b.add(None, $value);
let new_val: String = b.any(i).unwrap().into();
assert_eq!($val, new_val);
}};
}
#[test]
fn test_any() {
test_any_string!("something", "something");
test_any_string!(8, "8");
test_any_string!(5000, "5000");
test_any_string!(9238492834 as u64, "9238492834");
}
}