Skip to content

Commit

Permalink
Deserialize branch (#374)
Browse files Browse the repository at this point in the history
  • Loading branch information
richardpringle authored Nov 29, 2023
1 parent 61420a3 commit 31a57de
Show file tree
Hide file tree
Showing 2 changed files with 101 additions and 101 deletions.
99 changes: 7 additions & 92 deletions firewood/src/merkle/node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -340,13 +340,17 @@ use type_id::NodeTypeId;

impl Storable for Node {
fn deserialize<T: CachedStore>(addr: usize, mem: &T) -> Result<Self, ShaleError> {
let mut offset = addr;

let meta_raw =
mem.get_view(addr, Meta::SIZE as u64)
mem.get_view(offset, Meta::SIZE as u64)
.ok_or(ShaleError::InvalidCacheView {
offset: addr,
offset,
size: Meta::SIZE as u64,
})?;

offset += Meta::SIZE;

let attrs = NodeAttributes::from_bits_retain(meta_raw.as_deref()[TRIE_HASH_LEN]);

let root_hash = if attrs.contains(NodeAttributes::ROOT_HASH_VALID) {
Expand All @@ -368,96 +372,7 @@ impl Storable for Node {

match meta_raw.as_deref()[TRIE_HASH_LEN + 1].try_into()? {
NodeTypeId::Branch => {
// TODO: add path
// TODO: figure out what this size is?
let branch_header_size = BranchNode::MAX_CHILDREN as u64 * 8 + 4;
let node_raw = mem.get_view(addr + Meta::SIZE, branch_header_size).ok_or(
ShaleError::InvalidCacheView {
offset: addr + Meta::SIZE,
size: branch_header_size,
},
)?;

let mut cur = Cursor::new(node_raw.as_deref());
let mut chd = [None; BranchNode::MAX_CHILDREN];
let mut buff = [0; 8];

for chd in chd.iter_mut() {
cur.read_exact(&mut buff)?;
let addr = usize::from_le_bytes(buff);
if addr != 0 {
*chd = Some(DiskAddress::from(addr))
}
}

cur.read_exact(&mut buff[..4])?;

let raw_len = u32::from_le_bytes(buff[..4].try_into().expect("invalid slice"));

let value = if raw_len == u32::MAX {
None
} else {
let raw_len = raw_len as u64;

Some(Data(
mem.get_view(addr + Meta::SIZE + branch_header_size as usize, raw_len)
.ok_or(ShaleError::InvalidCacheView {
offset: addr + Meta::SIZE + branch_header_size as usize,
size: raw_len,
})?
.as_deref(),
))
};

let mut chd_encoded: [Option<Vec<u8>>; BranchNode::MAX_CHILDREN] =
Default::default();

let offset = if raw_len == u32::MAX {
addr + Meta::SIZE + branch_header_size as usize
} else {
addr + Meta::SIZE + branch_header_size as usize + raw_len as usize
};

let mut cur_encoded_len = 0;

for chd_encoded in chd_encoded.iter_mut() {
let mut buff = [0_u8; 1];
let len_raw = mem.get_view(offset + cur_encoded_len, 1).ok_or(
ShaleError::InvalidCacheView {
offset: offset + cur_encoded_len,
size: 1,
},
)?;

cur = Cursor::new(len_raw.as_deref());
cur.read_exact(&mut buff)?;

let len = buff[0] as u64;
cur_encoded_len += 1;

if len != 0 {
let encoded_raw = mem.get_view(offset + cur_encoded_len, len).ok_or(
ShaleError::InvalidCacheView {
offset: offset + cur_encoded_len,
size: len,
},
)?;

let encoded: Vec<u8> = encoded_raw.as_deref()[0..].to_vec();
*chd_encoded = Some(encoded);
cur_encoded_len += len as usize
}
}

let inner = NodeType::Branch(
BranchNode {
// path: vec![].into(),
children: chd,
value,
children_encoded: chd_encoded,
}
.into(),
);
let inner = NodeType::Branch(Box::new(BranchNode::deserialize(offset, mem)?));

Ok(Self::new_from_hash(
root_hash,
Expand Down
103 changes: 94 additions & 9 deletions firewood/src/merkle/node/branch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,13 @@
use super::{Data, Encoded, Node};
use crate::{
merkle::{PartialPath, TRIE_HASH_LEN},
shale::ShaleStore,
shale::{DiskAddress, Storable},
shale::{ShaleError, ShaleStore},
};
use bincode::{Error, Options};
use std::{
fmt::{Debug, Error as FmtError, Formatter},
io::{Cursor, Write},
io::{Cursor, Read, Write},
mem::size_of,
ops::Deref,
};
Expand Down Expand Up @@ -232,13 +232,98 @@ impl Storable for BranchNode {
}

fn deserialize<T: crate::shale::CachedStore>(
_addr: usize,
_mem: &T,
) -> Result<Self, crate::shale::ShaleError>
where
Self: Sized,
{
todo!()
mut addr: usize,
mem: &T,
) -> Result<Self, crate::shale::ShaleError> {
const DATA_LEN_SIZE: usize = size_of::<DataLen>();
const BRANCH_HEADER_SIZE: u64 =
BranchNode::MAX_CHILDREN as u64 * DiskAddress::MSIZE + DATA_LEN_SIZE as u64;

let node_raw =
mem.get_view(addr, BRANCH_HEADER_SIZE)
.ok_or(ShaleError::InvalidCacheView {
offset: addr,
size: BRANCH_HEADER_SIZE,
})?;

addr += BRANCH_HEADER_SIZE as usize;

let mut cursor = Cursor::new(node_raw.as_deref());
let mut children = [None; BranchNode::MAX_CHILDREN];
let mut buf = [0u8; DiskAddress::MSIZE as usize];

for child in &mut children {
cursor.read_exact(&mut buf)?;
*child = Some(usize::from_le_bytes(buf))
.filter(|addr| *addr != 0)
.map(DiskAddress::from);
}

let raw_len = {
let mut buf = [0; DATA_LEN_SIZE];
cursor.read_exact(&mut buf)?;
Some(DataLen::from_le_bytes(buf))
.filter(|len| *len != DataLen::MAX)
.map(|len| len as u64)
};

let value = match raw_len {
Some(len) => {
let data = mem
.get_view(addr, len)
.ok_or(ShaleError::InvalidCacheView {
offset: addr,
size: len,
})?;

addr += len as usize;

Some(Data(data.as_deref()))
}
None => None,
};

let mut children_encoded: [Option<Vec<u8>>; BranchNode::MAX_CHILDREN] = Default::default();

for child in &mut children_encoded {
const ENCODED_CHILD_LEN_SIZE: u64 = size_of::<EncodedChildLen>() as u64;

let len = mem
.get_view(addr, ENCODED_CHILD_LEN_SIZE)
.ok_or(ShaleError::InvalidCacheView {
offset: addr,
size: ENCODED_CHILD_LEN_SIZE,
})?
.as_deref()[0] as u64;

addr += ENCODED_CHILD_LEN_SIZE as usize;

if len == 0 {
continue;
}

let encoded = mem
.get_view(addr, len)
.ok_or(ShaleError::InvalidCacheView {
offset: addr,
size: len,
})?
.as_deref();

addr += len as usize;

*child = Some(encoded);
}

let node = BranchNode {
// TODO: add path
// path: Vec::new().into(),
children,
value,
children_encoded,
};

Ok(node)
}
}

Expand Down

0 comments on commit 31a57de

Please sign in to comment.