thin-provisioning-tools/src/pdata/array_block.rs
2021-03-03 09:48:15 +00:00

71 lines
1.6 KiB
Rust

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<V>(r: IResult<&[u8], V>) -> Result<(&[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,
})
}
//------------------------------------------