implementing TreeItem and parsing for extentdata

- implementing extentdata as an enum of either Inline + data bytes or not
inline (preallocated and whatever)
- accessor for name component in ItemWithName<T>
This commit is contained in:
Janis 2023-04-02 00:26:52 +02:00
parent 5a9918285f
commit 6148e1b089

View file

@ -229,8 +229,29 @@ macro_rules! impl_parse_try_from_ctx {
};
}
impl_parse_try_from_ctx!(Chunk, Header, Key, RootItem, INodeItem, INodeRef, DirItem);
impl_try_from_ctx!(Key, Chunk, Header, Superblock, RootItem, INodeItem, INodeRef, DirItem);
impl_parse_try_from_ctx!(
Chunk,
Header,
Key,
RootItem,
INodeItem,
INodeRef,
DirItem,
ExtentData1,
ExtentData2
);
impl_try_from_ctx!(
Key,
Chunk,
Header,
Superblock,
RootItem,
INodeItem,
INodeRef,
DirItem,
ExtentData1,
ExtentData2
);
const MAX_LABEL_SIZE: usize = 0x100;
const SYS_CHUNK_ARRAY_SIZE: usize = 0x800;
@ -294,31 +315,71 @@ pub struct ChunkItemStripe {
dev_uuid: Uuid,
}
#[repr(C, packed(1))]
#[derive(Debug, Clone, Copy, Pod, Zeroable)]
pub struct ExtentData {
generation: u64,
decoded_size: u64,
compression: u8,
encryption: u8,
encoding: u16,
ty: u8,
data: [u8; 1],
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
pub enum ExtentDataType {
Inline,
Regular,
PreAlloc,
}
#[derive(Debug, Clone)]
pub enum ExtentData {
Inline { header: ExtentData1, data: Vec<u8> },
Other(ExtentData2),
}
impl Parseable for ExtentData {
fn parse(bytes: &[u8]) -> Result<Self> {
let header = ExtentData1::parse(bytes)?;
let extent = match header.ty() {
ExtentDataType::Inline => {
let data = bytes[size_of::<ExtentData1>()..].to_vec();
Self::Inline { header, data }
}
_ => Self::Other(ExtentData2::parse(bytes)?),
};
Ok(extent)
}
}
#[repr(C, packed(1))]
#[derive(Debug, Clone, Copy, Pod, Zeroable)]
#[derive(Debug, Clone, Copy, FromBytes, AsBytes)]
pub struct ExtentData1 {
generation: U64<LE>,
decoded_size: U64<LE>,
compression: u8,
encryption: u8,
encoding: U16<LE>,
ty: u8,
}
impl ExtentData1 {
pub fn ty(&self) -> ExtentDataType {
match self.ty {
0 => ExtentDataType::Inline,
1 => ExtentDataType::Regular,
2 => ExtentDataType::PreAlloc,
_ => panic!("extentdatatype of invalid"),
}
}
}
#[repr(C, packed(1))]
#[derive(Debug, Clone, Copy, FromBytes, AsBytes)]
pub struct ExtentData2 {
address: u64,
size: u64,
offset: u64,
num_bytes: u64,
header: ExtentData1,
address: U64<LE>,
size: U64<LE>,
offset: U64<LE>,
num_bytes: U64<LE>,
}
#[repr(C, packed(1))]
#[derive(Debug, Clone, Copy, FromBytes, AsBytes)]
pub struct INodeRef {
index: U64<LE>,
pub index: U64<LE>,
name_len: U16<LE>,
}
@ -878,6 +939,11 @@ where
pub fn item(&self) -> &I {
&self.inner
}
pub fn name(&self) -> &Vec<u8> {
&self.name
}
pub fn name_as_str(&self) -> core::result::Result<&str, core::str::Utf8Error> {
core::str::from_utf8(&self.name)
}
@ -907,8 +973,10 @@ pub struct InodeRef {
}
#[repr(C, packed)]
#[derive(Debug, Clone, PartialEq, Eq, Copy, FromBytes, AsBytes)]
#[derive(Derivative, Clone, PartialEq, Eq, Copy, FromBytes, AsBytes)]
#[derivative(Debug)]
pub struct Header {
#[derivative(Debug = "ignore")]
pub csum: [u8; 32],
pub fsid: Uuid,
/// Which block this node is supposed to live in
@ -946,6 +1014,7 @@ use alloc::vec::Vec;
pub enum TreeItem {
Chunk(Chunk),
Root(RootItem),
ExtentData(ExtentData),
DirItem(Vec<DirItemEntry>),
DirIndex(DirItemEntry),
INodeItem(INodeItem),
@ -989,6 +1058,12 @@ impl From<INodeRefEntry> for TreeItem {
}
}
impl From<ExtentData> for TreeItem {
fn from(value: ExtentData) -> Self {
Self::ExtentData(value)
}
}
impl TreeItem {
pub fn parse(item: &Item, bytes: &[u8]) -> Result<Self> {
Ok(match item.key.ty() {
@ -998,20 +1073,13 @@ impl TreeItem {
ObjectType::DirIndex => DirItemEntry::parse(bytes)?.into(),
ObjectType::INodeItem => INodeItem::parse(bytes)?.into(),
ObjectType::INodeRef => INodeRefEntry::parse(bytes)?.into(),
ObjectType::ExtentData => ExtentData::parse(bytes)?.into(),
_ => TreeItem::Unimplemented,
})
}
pub fn as_dir_item(&self) -> Option<&Vec<DirItemEntry>> {
if let Self::DirItem(v) = self {
Some(v)
} else {
None
}
}
pub fn as_dir_index(&self) -> Option<&DirItemEntry> {
if let Self::DirIndex(v) = self {
pub fn as_extent_data(&self) -> Option<&ExtentData> {
if let Self::ExtentData(v) = self {
Some(v)
} else {
None
@ -1035,6 +1103,38 @@ impl TreeItem {
None
}
}
pub fn as_dir_item(&self) -> Option<&Vec<DirItemEntry>> {
if let Self::DirItem(v) = self {
Some(v)
} else {
None
}
}
pub fn as_dir_index(&self) -> Option<&DirItemEntry> {
if let Self::DirIndex(v) = self {
Some(v)
} else {
None
}
}
pub fn as_inode_ref(&self) -> Option<&INodeRefEntry> {
if let Self::INodeRef(v) = self {
Some(v)
} else {
None
}
}
pub fn as_inode_item(&self) -> Option<&INodeItem> {
if let Self::INodeItem(v) = self {
Some(v)
} else {
None
}
}
}
#[derive(Debug, Clone)]