[array (rust)] Implement array basis
This commit is contained in:
parent
9733ceb949
commit
087a4711a5
39
src/pdata/array.rs
Normal file
39
src/pdata/array.rs
Normal file
@ -0,0 +1,39 @@
|
||||
use nom::{number::complete::*, IResult};
|
||||
use std::fmt;
|
||||
|
||||
use crate::pdata::unpack::*;
|
||||
|
||||
//------------------------------------------
|
||||
|
||||
// TODO: build a data structure representating an array?
|
||||
|
||||
// FIXME: rename this struct
|
||||
pub struct ArrayBlockEntry {
|
||||
pub block: u64,
|
||||
}
|
||||
|
||||
impl Unpack for ArrayBlockEntry {
|
||||
fn disk_size() -> u32 {
|
||||
8
|
||||
}
|
||||
|
||||
fn unpack(i: &[u8]) -> IResult<&[u8], ArrayBlockEntry> {
|
||||
let (i, n) = le_u64(i)?;
|
||||
let block = n;
|
||||
|
||||
Ok((
|
||||
i,
|
||||
ArrayBlockEntry {
|
||||
block,
|
||||
}
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for ArrayBlockEntry {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "{}", self.block)
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------
|
70
src/pdata/array_block.rs
Normal file
70
src/pdata/array_block.rs
Normal file
@ -0,0 +1,70 @@
|
||||
use anyhow::anyhow;
|
||||
use anyhow::Result;
|
||||
use nom::{multi::count, number::complete::*, IResult};
|
||||
|
||||
use crate::pdata::unpack::Unpack;
|
||||
|
||||
//------------------------------------------
|
||||
|
||||
pub struct ArrayBlockHeader {
|
||||
pub csum: u32,
|
||||
pub max_entries: u32,
|
||||
pub nr_entries: u32,
|
||||
pub value_size: u32,
|
||||
pub blocknr: u64,
|
||||
}
|
||||
|
||||
impl Unpack for ArrayBlockHeader {
|
||||
fn disk_size() -> u32 {
|
||||
24
|
||||
}
|
||||
|
||||
fn unpack(data: &[u8]) -> IResult<&[u8], ArrayBlockHeader> {
|
||||
let (i, csum) = le_u32(data)?;
|
||||
let (i, max_entries) = le_u32(i)?;
|
||||
let (i, nr_entries) = le_u32(i)?;
|
||||
let (i, value_size) = le_u32(i)?;
|
||||
let (i, blocknr) = le_u64(i)?;
|
||||
|
||||
Ok((
|
||||
i,
|
||||
ArrayBlockHeader {
|
||||
csum,
|
||||
max_entries,
|
||||
nr_entries,
|
||||
value_size,
|
||||
blocknr
|
||||
},
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
pub struct ArrayBlock<V: Unpack> {
|
||||
pub header: ArrayBlockHeader,
|
||||
pub values: Vec<V>,
|
||||
}
|
||||
|
||||
impl<V: Unpack> ArrayBlock<V> {
|
||||
pub fn get_header(&self) -> &ArrayBlockHeader {
|
||||
&self.header
|
||||
}
|
||||
}
|
||||
|
||||
fn convert_result<'a, V>(r: IResult<&'a [u8], V>) -> Result<(&'a [u8], V)> {
|
||||
r.map_err(|_| anyhow!("parse error"))
|
||||
}
|
||||
|
||||
pub fn unpack_array_block<V: Unpack>(
|
||||
data: &[u8],
|
||||
) -> Result<ArrayBlock<V>> {
|
||||
// TODO: collect errors
|
||||
let (i, header) = ArrayBlockHeader::unpack(data).map_err(|_e| anyhow!("Couldn't parse header"))?;
|
||||
let (_i, values) = convert_result(count(V::unpack, header.nr_entries as usize)(i))?;
|
||||
|
||||
Ok(ArrayBlock {
|
||||
header,
|
||||
values,
|
||||
})
|
||||
}
|
||||
|
||||
//------------------------------------------
|
108
src/pdata/array_walker.rs
Normal file
108
src/pdata/array_walker.rs
Normal file
@ -0,0 +1,108 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use crate::io_engine::*;
|
||||
use crate::pdata::array::*;
|
||||
use crate::pdata::array_block::*;
|
||||
use crate::pdata::btree::*;
|
||||
use crate::pdata::btree_walker::*;
|
||||
use crate::pdata::unpack::*;
|
||||
|
||||
//------------------------------------------
|
||||
|
||||
pub struct ArrayWalker {
|
||||
engine: Arc<dyn IoEngine + Send + Sync>,
|
||||
ignore_non_fatal: bool
|
||||
}
|
||||
|
||||
// FIXME: define another Result type for array visiting?
|
||||
pub trait ArrayBlockVisitor<V: Unpack> {
|
||||
fn visit(
|
||||
&self,
|
||||
index: u64,
|
||||
v: V,
|
||||
) -> anyhow::Result<()>;
|
||||
}
|
||||
|
||||
struct BlockValueVisitor<V> {
|
||||
engine: Arc<dyn IoEngine + Send + Sync>,
|
||||
array_block_visitor: Box<dyn ArrayBlockVisitor<V>>,
|
||||
}
|
||||
|
||||
impl<V: Unpack + Copy> BlockValueVisitor<V> {
|
||||
pub fn new<Visitor: 'static + ArrayBlockVisitor<V>>(
|
||||
e: Arc<dyn IoEngine + Send + Sync>,
|
||||
v: Box<Visitor>,
|
||||
) -> BlockValueVisitor<V> {
|
||||
BlockValueVisitor {
|
||||
engine: e,
|
||||
array_block_visitor: v,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn visit_array_block(
|
||||
&self,
|
||||
index: u64,
|
||||
array_block: ArrayBlock<V>,
|
||||
) {
|
||||
let begin = index * u64::from(array_block.header.nr_entries);
|
||||
for i in 0..array_block.header.nr_entries {
|
||||
self.array_block_visitor.visit(begin + u64::from(i), array_block.values[i as usize]).unwrap();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<V: Unpack + Copy> NodeVisitor<ArrayBlockEntry> for BlockValueVisitor<V> {
|
||||
// FIXME: return errors
|
||||
fn visit(
|
||||
&self,
|
||||
path: &Vec<u64>,
|
||||
_kr: &KeyRange,
|
||||
_h: &NodeHeader,
|
||||
keys: &[u64],
|
||||
values: &[ArrayBlockEntry],
|
||||
) -> Result<()> {
|
||||
for n in 0..keys.len() {
|
||||
let index = keys[n];
|
||||
let b = self.engine.read(values[n].block).map_err(|_| io_err(path))?;
|
||||
let array_block = unpack_array_block::<V>(b.get_data()).map_err(|_| io_err(path))?;
|
||||
self.visit_array_block(index, array_block);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// FIXME: stub
|
||||
fn visit_again(&self, _path: &Vec<u64>, _b: u64) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// FIXME: stub
|
||||
fn end_walk(&self) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl ArrayWalker {
|
||||
pub fn new(engine: Arc<dyn IoEngine + Send + Sync>, ignore_non_fatal: bool) -> ArrayWalker {
|
||||
let r: ArrayWalker = ArrayWalker {
|
||||
engine,
|
||||
ignore_non_fatal,
|
||||
};
|
||||
r
|
||||
}
|
||||
|
||||
// FIXME: pass the visitor by reference?
|
||||
// FIXME: redefine the Result type for array visiting?
|
||||
pub fn walk<BV, V: Copy>(&self, visitor: Box<BV>, root: u64) -> Result<()>
|
||||
where
|
||||
BV: 'static + ArrayBlockVisitor<V>,
|
||||
V: Unpack,
|
||||
{
|
||||
let w = BTreeWalker::new(self.engine.clone(), self.ignore_non_fatal);
|
||||
let mut path = Vec::new(); // FIXME: eliminate this line?
|
||||
path.push(0);
|
||||
let v = BlockValueVisitor::<V>::new(self.engine.clone(), visitor);
|
||||
w.walk(&mut path, &v, root)
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------
|
@ -1,3 +1,6 @@
|
||||
pub mod array;
|
||||
pub mod array_block;
|
||||
pub mod array_walker;
|
||||
pub mod btree;
|
||||
pub mod btree_builder;
|
||||
pub mod btree_merge;
|
||||
|
Loading…
Reference in New Issue
Block a user