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