use core::fmt;
use core::fmt::Display;
#[cfg(feature = "std")]
use std::error;
use crate::phys::{
BinaryDecodeError, BinaryDecoder, BinaryEncodeError, BinaryEncoder, SECTOR_SHIFT,
};
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum ZapCaseNormalization {
None = 0x00,
Upper = 0x02,
Lower = 0x04,
}
impl ZapCaseNormalization {
const MASK_ALL: u64 = 0x02 | 0x04;
}
impl From<ZapCaseNormalization> for u64 {
fn from(val: ZapCaseNormalization) -> u64 {
val as u64
}
}
impl Display for ZapCaseNormalization {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
ZapCaseNormalization::None => write!(f, "None"),
ZapCaseNormalization::Upper => write!(f, "Upper"),
ZapCaseNormalization::Lower => write!(f, "Lower"),
}
}
}
impl TryFrom<u64> for ZapCaseNormalization {
type Error = ZapCaseNormalizationError;
fn try_from(case_normalization: u64) -> Result<Self, Self::Error> {
match case_normalization {
0x00 => Ok(ZapCaseNormalization::None),
0x02 => Ok(ZapCaseNormalization::Upper),
0x04 => Ok(ZapCaseNormalization::Lower),
_ => Err(ZapCaseNormalizationError::Unknown { case_normalization }),
}
}
}
#[derive(Debug)]
pub enum ZapCaseNormalizationError {
Unknown {
case_normalization: u64,
},
}
impl fmt::Display for ZapCaseNormalizationError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
ZapCaseNormalizationError::Unknown { case_normalization } => {
write!(f, "Unknown ZapCaseNormalization {case_normalization}")
}
}
}
}
#[cfg(feature = "std")]
impl error::Error for ZapCaseNormalizationError {
fn source(&self) -> Option<&(dyn error::Error + 'static)> {
None
}
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum ZapUnicodeNormalization {
None = 0x00,
NFD = 0x10,
NFKD = 0x20,
NFC = 0x50,
NFKC = 0x60,
}
impl ZapUnicodeNormalization {
const MASK_ALL: u64 = 0x10 | 0x20 | 0x50 | 0x60;
}
impl From<ZapUnicodeNormalization> for u64 {
fn from(val: ZapUnicodeNormalization) -> u64 {
val as u64
}
}
impl Display for ZapUnicodeNormalization {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
ZapUnicodeNormalization::None => write!(f, "None"),
ZapUnicodeNormalization::NFD => write!(f, "NFD"),
ZapUnicodeNormalization::NFKD => write!(f, "NFKD"),
ZapUnicodeNormalization::NFC => write!(f, "NFC"),
ZapUnicodeNormalization::NFKC => write!(f, "NFKC"),
}
}
}
impl TryFrom<u64> for ZapUnicodeNormalization {
type Error = ZapUnicodeNormalizationError;
fn try_from(unicode_normalization: u64) -> Result<Self, Self::Error> {
match unicode_normalization {
0x00 => Ok(ZapUnicodeNormalization::None),
0x10 => Ok(ZapUnicodeNormalization::NFD),
0x20 => Ok(ZapUnicodeNormalization::NFKD),
0x50 => Ok(ZapUnicodeNormalization::NFC),
0x60 => Ok(ZapUnicodeNormalization::NFKC),
_ => Err(ZapUnicodeNormalizationError::Unknown {
unicode_normalization,
}),
}
}
}
#[derive(Debug)]
pub enum ZapUnicodeNormalizationError {
Unknown {
unicode_normalization: u64,
},
}
impl fmt::Display for ZapUnicodeNormalizationError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
ZapUnicodeNormalizationError::Unknown {
unicode_normalization,
} => {
write!(f, "Unknown ZapUnicodeNormalization {unicode_normalization}")
}
}
}
}
#[cfg(feature = "std")]
impl error::Error for ZapUnicodeNormalizationError {
fn source(&self) -> Option<&(dyn error::Error + 'static)> {
None
}
}
#[derive(Debug)]
pub struct ZapMicroHeader {
pub salt: u64,
pub case_normalization: ZapCaseNormalization,
pub unicode_normalization: ZapUnicodeNormalization,
}
impl ZapMicroHeader {
pub const SIZE: usize = 64;
pub const BLOCK_TYPE: u64 = 0x8000000000000003;
const PADDING_SIZE: usize = 40;
const NORMALIZATION_MASK: u64 =
ZapCaseNormalization::MASK_ALL | ZapUnicodeNormalization::MASK_ALL;
pub fn from_decoder(
decoder: &mut dyn BinaryDecoder<'_>,
) -> Result<ZapMicroHeader, ZapMicroHeaderDecodeError> {
let block_type = decoder.get_u64()?;
if block_type != ZapMicroHeader::BLOCK_TYPE {
return Err(ZapMicroHeaderDecodeError::BlockType { block_type });
}
let salt = decoder.get_u64()?;
let normalization = decoder.get_u64()?;
if (normalization & ZapMicroHeader::NORMALIZATION_MASK) != normalization {
return Err(ZapMicroHeaderDecodeError::Normalization { normalization });
}
let case_normalization =
ZapCaseNormalization::try_from(normalization & ZapCaseNormalization::MASK_ALL)?;
let unicode_normalization =
ZapUnicodeNormalization::try_from(normalization & ZapUnicodeNormalization::MASK_ALL)?;
decoder.skip_zeros(ZapMicroHeader::PADDING_SIZE)?;
Ok(ZapMicroHeader {
salt,
case_normalization,
unicode_normalization,
})
}
pub fn to_encoder(
&self,
encoder: &mut dyn BinaryEncoder<'_>,
) -> Result<(), ZapMicroHeaderEncodeError> {
encoder.put_u64(ZapMicroHeader::BLOCK_TYPE)?;
encoder.put_u64(self.salt)?;
let normalization =
u64::from(self.case_normalization) | u64::from(self.unicode_normalization);
encoder.put_u64(normalization)?;
encoder.put_zeros(ZapMicroHeader::PADDING_SIZE)?;
Ok(())
}
}
#[derive(Debug)]
pub enum ZapMicroHeaderDecodeError {
Binary {
err: BinaryDecodeError,
},
BlockType {
block_type: u64,
},
CaseNormalization {
err: ZapCaseNormalizationError,
},
Normalization {
normalization: u64,
},
UnicodeNormalization {
err: ZapUnicodeNormalizationError,
},
}
impl From<BinaryDecodeError> for ZapMicroHeaderDecodeError {
fn from(err: BinaryDecodeError) -> Self {
ZapMicroHeaderDecodeError::Binary { err }
}
}
impl From<ZapCaseNormalizationError> for ZapMicroHeaderDecodeError {
fn from(err: ZapCaseNormalizationError) -> Self {
ZapMicroHeaderDecodeError::CaseNormalization { err }
}
}
impl From<ZapUnicodeNormalizationError> for ZapMicroHeaderDecodeError {
fn from(err: ZapUnicodeNormalizationError) -> Self {
ZapMicroHeaderDecodeError::UnicodeNormalization { err }
}
}
impl fmt::Display for ZapMicroHeaderDecodeError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
ZapMicroHeaderDecodeError::Binary { err } => {
write!(f, "ZapMicroHeader decode error | {err}")
}
ZapMicroHeaderDecodeError::BlockType { block_type } => {
write!(
f,
"ZapMicroHeader decode error, invalid block_type {block_type}"
)
}
ZapMicroHeaderDecodeError::CaseNormalization { err } => {
write!(f, "ZapMicroHeader decode error | {err}")
}
ZapMicroHeaderDecodeError::Normalization { normalization } => {
write!(
f,
"ZapMicroHeader decode error, unknown normalization {normalization}"
)
}
ZapMicroHeaderDecodeError::UnicodeNormalization { err } => {
write!(f, "ZapMicroHeader decode error | {err}")
}
}
}
}
#[cfg(feature = "std")]
impl error::Error for ZapMicroHeaderDecodeError {
fn source(&self) -> Option<&(dyn error::Error + 'static)> {
match self {
ZapMicroHeaderDecodeError::Binary { err } => Some(err),
ZapMicroHeaderDecodeError::CaseNormalization { err } => Some(err),
ZapMicroHeaderDecodeError::UnicodeNormalization { err } => Some(err),
_ => None,
}
}
}
#[derive(Debug)]
pub enum ZapMicroHeaderEncodeError {
Binary {
err: BinaryEncodeError,
},
}
impl From<BinaryEncodeError> for ZapMicroHeaderEncodeError {
fn from(err: BinaryEncodeError) -> Self {
ZapMicroHeaderEncodeError::Binary { err }
}
}
impl fmt::Display for ZapMicroHeaderEncodeError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
ZapMicroHeaderEncodeError::Binary { err } => {
write!(f, "ZapMicroHeader encode error | {err}")
}
}
}
}
#[cfg(feature = "std")]
impl error::Error for ZapMicroHeaderEncodeError {
fn source(&self) -> Option<&(dyn error::Error + 'static)> {
match self {
ZapMicroHeaderEncodeError::Binary { err } => Some(err),
}
}
}
#[derive(Debug)]
pub struct ZapMicroEntry {
pub cd: u32,
pub name: [u8; ZapMicroEntry::NAME_MAX],
pub value: u64,
}
impl ZapMicroEntry {
pub const SIZE: usize = 64;
pub const NAME_MAX: usize = 49;
const PADDING_SIZE: usize = 2;
pub fn from_decoder(
decoder: &mut dyn BinaryDecoder<'_>,
) -> Result<Option<ZapMicroEntry>, ZapMicroEntryDecodeError> {
if decoder.is_skip_zeros(ZapMicroEntry::SIZE)? {
return Ok(None);
}
let value = decoder.get_u64()?;
let cd = decoder.get_u32()?;
decoder.skip_zeros(ZapMicroEntry::PADDING_SIZE)?;
let name = decoder.get_bytes_n(ZapMicroEntry::NAME_MAX + 1)?;
let mut null_found = false;
for byte in name {
if *byte == 0 {
null_found = true;
break;
}
}
if !null_found {
return Err(ZapMicroEntryDecodeError::NameNotNullTerminated {});
}
Ok(Some(ZapMicroEntry {
cd,
name: name[0..ZapMicroEntry::NAME_MAX].try_into().unwrap(),
value,
}))
}
pub fn to_encoder(
&self,
encoder: &mut dyn BinaryEncoder<'_>,
) -> Result<(), ZapMicroEntryEncodeError> {
encoder.put_u64(self.value)?;
encoder.put_u32(self.cd)?;
encoder.put_zeros(ZapMicroEntry::PADDING_SIZE)?;
encoder.put_bytes(&self.name)?;
encoder.put_u8(0)?;
Ok(())
}
pub fn empty_to_encoder(
encoder: &mut dyn BinaryEncoder<'_>,
) -> Result<(), ZapMicroEntryEncodeError> {
Ok(encoder.put_zeros(ZapMicroEntry::SIZE)?)
}
pub fn option_to_encoder(
ptr: &Option<ZapMicroEntry>,
encoder: &mut dyn BinaryEncoder<'_>,
) -> Result<(), ZapMicroEntryEncodeError> {
match ptr {
Some(v) => v.to_encoder(encoder),
None => Ok(ZapMicroEntry::empty_to_encoder(encoder)?),
}
}
}
pub struct ZapMicroEntryRef<'a> {
pub cd: u32,
pub name: &'a str,
pub value: u64,
}
impl ZapMicroEntryRef<'_> {
pub const SIZE: usize = 64;
pub const NAME_MAX: usize = 49;
const PADDING_SIZE: usize = 2;
pub fn from_decoder<'a>(
decoder: &mut dyn BinaryDecoder<'a>,
) -> Result<Option<ZapMicroEntryRef<'a>>, ZapMicroEntryDecodeError> {
if decoder.is_skip_zeros(ZapMicroEntryRef::SIZE)? {
return Ok(None);
}
let value = decoder.get_u64()?;
let cd = decoder.get_u32()?;
decoder.skip_zeros(ZapMicroEntryRef::PADDING_SIZE)?;
let name = decoder.get_bytes_n(ZapMicroEntryRef::NAME_MAX + 1)?;
let mut null_found = false;
let mut length = 0;
for byte in name {
if *byte == 0 {
null_found = true;
break;
}
length += 1;
}
if !null_found {
return Err(ZapMicroEntryDecodeError::NameNotNullTerminated {});
}
let data = &name[0..length];
let name = match core::str::from_utf8(data) {
Ok(v) => v,
Err(err) => return Err(ZapMicroEntryDecodeError::InvalidStr { err }),
};
Ok(Some(ZapMicroEntryRef { cd, name, value }))
}
pub fn to_encoder(
&self,
encoder: &mut dyn BinaryEncoder<'_>,
) -> Result<(), ZapMicroEntryEncodeError> {
encoder.put_u64(self.value)?;
encoder.put_u32(self.cd)?;
encoder.put_zeros(ZapMicroEntryRef::PADDING_SIZE)?;
let length = self.name.len();
if length > ZapMicroEntryRef::NAME_MAX {
return Err(ZapMicroEntryEncodeError::NameTooLong { length });
}
encoder.put_bytes(self.name.as_bytes())?;
encoder.put_zeros((ZapMicroEntryRef::NAME_MAX + 1) - length)?;
encoder.put_u8(0)?;
Ok(())
}
pub fn empty_to_encoder(
encoder: &mut dyn BinaryEncoder<'_>,
) -> Result<(), ZapMicroEntryEncodeError> {
Ok(encoder.put_zeros(ZapMicroEntryRef::SIZE)?)
}
pub fn option_to_encoder(
ptr: &Option<ZapMicroEntryRef<'_>>,
encoder: &mut dyn BinaryEncoder<'_>,
) -> Result<(), ZapMicroEntryEncodeError> {
match ptr {
Some(v) => v.to_encoder(encoder),
None => Ok(ZapMicroEntryRef::empty_to_encoder(encoder)?),
}
}
}
#[derive(Debug)]
pub enum ZapMicroEntryDecodeError {
Binary {
err: BinaryDecodeError,
},
NameNotNullTerminated {},
InvalidStr {
err: core::str::Utf8Error,
},
}
impl From<BinaryDecodeError> for ZapMicroEntryDecodeError {
fn from(err: BinaryDecodeError) -> Self {
ZapMicroEntryDecodeError::Binary { err }
}
}
impl fmt::Display for ZapMicroEntryDecodeError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
ZapMicroEntryDecodeError::Binary { err } => {
write!(f, "ZapMicroEntry decode error | {err}")
}
ZapMicroEntryDecodeError::NameNotNullTerminated {} => {
write!(f, "ZapMicroEntry decode error, name is not NULL terminated")
}
ZapMicroEntryDecodeError::InvalidStr { err } => {
write!(f, "ZapMicroEntry decode error, invalid UTF8 str | {err}")
}
}
}
}
#[cfg(feature = "std")]
impl error::Error for ZapMicroEntryDecodeError {
fn source(&self) -> Option<&(dyn error::Error + 'static)> {
match self {
ZapMicroEntryDecodeError::Binary { err } => Some(err),
ZapMicroEntryDecodeError::InvalidStr { err } => Some(err),
ZapMicroEntryDecodeError::NameNotNullTerminated {} => None,
}
}
}
#[derive(Debug)]
pub enum ZapMicroEntryEncodeError {
Binary {
err: BinaryEncodeError,
},
NameTooLong {
length: usize,
},
}
impl From<BinaryEncodeError> for ZapMicroEntryEncodeError {
fn from(err: BinaryEncodeError) -> Self {
ZapMicroEntryEncodeError::Binary { err }
}
}
impl fmt::Display for ZapMicroEntryEncodeError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
ZapMicroEntryEncodeError::Binary { err } => {
write!(f, "ZapMicroEntry encode error | {err}")
}
ZapMicroEntryEncodeError::NameTooLong { length } => write!(
f,
"ZapMicroEntry encode error, name is too long: {length} > {}",
ZapMicroEntry::NAME_MAX,
),
}
}
}
#[cfg(feature = "std")]
impl error::Error for ZapMicroEntryEncodeError {
fn source(&self) -> Option<&(dyn error::Error + 'static)> {
match self {
ZapMicroEntryEncodeError::Binary { err } => Some(err),
ZapMicroEntryEncodeError::NameTooLong { .. } => None,
}
}
}
pub struct ZapMicroIterator<'a, 'b> {
pub header: ZapMicroHeader,
decoder: &'b mut dyn BinaryDecoder<'a>,
}
impl ZapMicroIterator<'_, '_> {
pub fn from_decoder<'a, 'b>(
decoder: &'b mut dyn BinaryDecoder<'a>,
) -> Result<ZapMicroIterator<'a, 'b>, ZapMicroIteratorError> {
let header = ZapMicroHeader::from_decoder(decoder)?;
if !decoder.len().is_multiple_of(ZapMicroEntry::SIZE) {
return Err(ZapMicroIteratorError::Size {
size: decoder.len(),
});
}
Ok(ZapMicroIterator { header, decoder })
}
}
impl<'a, 'b> Iterator for ZapMicroIterator<'a, 'b> {
type Item = Result<ZapMicroEntryRef<'a>, ZapMicroEntryDecodeError>;
fn next(&mut self) -> Option<<Self as Iterator>::Item> {
while !self.decoder.is_empty() {
let entry_opt = match ZapMicroEntryRef::from_decoder(self.decoder) {
Ok(v) => v,
Err(e) => return Some(Err(e)),
};
match entry_opt {
Some(entry) => return Some(Ok(entry)),
None => continue,
};
}
None
}
}
#[derive(Debug)]
pub enum ZapMicroIteratorError {
Binary {
err: BinaryDecodeError,
},
Size {
size: usize,
},
ZapMicroHeader {
err: ZapMicroHeaderDecodeError,
},
}
impl From<BinaryDecodeError> for ZapMicroIteratorError {
fn from(err: BinaryDecodeError) -> Self {
ZapMicroIteratorError::Binary { err }
}
}
impl From<ZapMicroHeaderDecodeError> for ZapMicroIteratorError {
fn from(err: ZapMicroHeaderDecodeError) -> Self {
ZapMicroIteratorError::ZapMicroHeader { err }
}
}
impl fmt::Display for ZapMicroIteratorError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
ZapMicroIteratorError::Binary { err } => {
write!(f, "ZapMicroIterator decode error | {err}")
}
ZapMicroIteratorError::Size { size } => {
write!(
f,
"ZapMicroIterator decode error, entries size {size} is not a multiple of {}",
ZapMicroEntry::SIZE
)
}
ZapMicroIteratorError::ZapMicroHeader { err } => {
write!(f, "ZapMicroIterator decode error | {err}")
}
}
}
}
#[cfg(feature = "std")]
impl error::Error for ZapMicroIteratorError {
fn source(&self) -> Option<&(dyn error::Error + 'static)> {
match self {
ZapMicroIteratorError::Binary { err } => Some(err),
ZapMicroIteratorError::Size { .. } => None,
ZapMicroIteratorError::ZapMicroHeader { err } => Some(err),
}
}
}
#[derive(Debug)]
pub struct ZapMegaPointerTable {
pub starting_block: u64,
pub blocks: u64,
pub hash_bits: u64,
pub next_block: u64,
pub blocks_copied: u64,
}
impl ZapMegaPointerTable {
pub const SIZE: usize = 40;
pub fn from_decoder(
decoder: &mut dyn BinaryDecoder<'_>,
) -> Result<ZapMegaPointerTable, ZapMegaPointerTableDecodeError> {
Ok(ZapMegaPointerTable {
starting_block: decoder.get_u64()?,
blocks: decoder.get_u64()?,
hash_bits: decoder.get_u64()?,
next_block: decoder.get_u64()?,
blocks_copied: decoder.get_u64()?,
})
}
pub fn to_encoder(
&self,
encoder: &mut dyn BinaryEncoder<'_>,
) -> Result<(), ZapMegaPointerTableEncodeError> {
encoder.put_u64(self.starting_block)?;
encoder.put_u64(self.blocks)?;
encoder.put_u64(self.hash_bits)?;
encoder.put_u64(self.next_block)?;
encoder.put_u64(self.blocks_copied)?;
Ok(())
}
}
#[derive(Debug)]
pub enum ZapMegaPointerTableDecodeError {
Binary {
err: BinaryDecodeError,
},
}
impl From<BinaryDecodeError> for ZapMegaPointerTableDecodeError {
fn from(err: BinaryDecodeError) -> Self {
ZapMegaPointerTableDecodeError::Binary { err }
}
}
impl fmt::Display for ZapMegaPointerTableDecodeError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
ZapMegaPointerTableDecodeError::Binary { err } => {
write!(f, "ZapMegaPointerTable decode error | {err}")
}
}
}
}
#[cfg(feature = "std")]
impl error::Error for ZapMegaPointerTableDecodeError {
fn source(&self) -> Option<&(dyn error::Error + 'static)> {
match self {
ZapMegaPointerTableDecodeError::Binary { err } => Some(err),
}
}
}
#[derive(Debug)]
pub enum ZapMegaPointerTableEncodeError {
Binary {
err: BinaryEncodeError,
},
}
impl From<BinaryEncodeError> for ZapMegaPointerTableEncodeError {
fn from(err: BinaryEncodeError) -> Self {
ZapMegaPointerTableEncodeError::Binary { err }
}
}
impl fmt::Display for ZapMegaPointerTableEncodeError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
ZapMegaPointerTableEncodeError::Binary { err } => {
write!(f, "ZapMegaPointerTable encode error | {err}")
}
}
}
}
#[cfg(feature = "std")]
impl error::Error for ZapMegaPointerTableEncodeError {
fn source(&self) -> Option<&(dyn error::Error + 'static)> {
match self {
ZapMegaPointerTableEncodeError::Binary { err } => Some(err),
}
}
}
#[derive(Debug)]
pub struct ZapMegaHeader {
pub table: ZapMegaPointerTable,
pub next_free_block: u64,
pub number_of_leafs: u64,
pub number_of_entries: u64,
pub salt: u64,
pub case_normalization: ZapCaseNormalization,
pub unicode_normalization: ZapUnicodeNormalization,
pub hash_bits_48: bool,
pub key_u64: bool,
pub pre_hashed_key: bool,
}
impl ZapMegaHeader {
pub const SIZE: usize = 104;
pub const BLOCK_TYPE: u64 = 0x8000000000000001;
pub const MAGIC: u64 = 0x00000002f52ab2ab;
const FLAG_HASH_BITS_48: u64 = 1 << 0;
const FLAG_KEY_U64: u64 = 1 << 1;
const FLAG_PRE_HASHED_KEY: u64 = 1 << 2;
const FLAG_ALL: u64 = ZapMegaHeader::FLAG_HASH_BITS_48
| ZapMegaHeader::FLAG_KEY_U64
| ZapMegaHeader::FLAG_PRE_HASHED_KEY;
pub fn from_decoder(
decoder: &mut dyn BinaryDecoder<'_>,
) -> Result<ZapMegaHeader, ZapMegaHeaderDecodeError> {
let block_type = decoder.get_u64()?;
if block_type != ZapMegaHeader::BLOCK_TYPE {
return Err(ZapMegaHeaderDecodeError::BlockType { block_type });
}
let magic = decoder.get_u64()?;
if magic != ZapMegaHeader::MAGIC {
return Err(ZapMegaHeaderDecodeError::Magic { magic });
}
let table = ZapMegaPointerTable::from_decoder(decoder)?;
let next_free_block = decoder.get_u64()?;
let number_of_leafs = decoder.get_u64()?;
let number_of_entries = decoder.get_u64()?;
let salt = decoder.get_u64()?;
let normalization = decoder.get_u64()?;
if (normalization & ZapMicroHeader::NORMALIZATION_MASK) != normalization {
return Err(ZapMegaHeaderDecodeError::Normalization { normalization });
}
let case_normalization =
ZapCaseNormalization::try_from(normalization & ZapCaseNormalization::MASK_ALL)?;
let unicode_normalization =
ZapUnicodeNormalization::try_from(normalization & ZapUnicodeNormalization::MASK_ALL)?;
let flags = decoder.get_u64()?;
if (flags & ZapMegaHeader::FLAG_ALL) != flags {
return Err(ZapMegaHeaderDecodeError::Flags { flags });
}
Ok(ZapMegaHeader {
table,
next_free_block,
number_of_leafs,
number_of_entries,
salt,
case_normalization,
unicode_normalization,
hash_bits_48: (flags & ZapMegaHeader::FLAG_HASH_BITS_48) != 0,
key_u64: (flags & ZapMegaHeader::FLAG_KEY_U64) != 0,
pre_hashed_key: (flags & ZapMegaHeader::FLAG_PRE_HASHED_KEY) != 0,
})
}
pub fn to_encoder(
&self,
encoder: &mut dyn BinaryEncoder<'_>,
) -> Result<(), ZapMegaHeaderEncodeError> {
encoder.put_u64(ZapMegaHeader::BLOCK_TYPE)?;
encoder.put_u64(ZapMegaHeader::MAGIC)?;
self.table.to_encoder(encoder)?;
encoder.put_u64(self.next_free_block)?;
encoder.put_u64(self.number_of_leafs)?;
encoder.put_u64(self.number_of_entries)?;
encoder.put_u64(self.salt)?;
let normalization =
u64::from(self.case_normalization) | u64::from(self.unicode_normalization);
encoder.put_u64(normalization)?;
let flags = (if self.hash_bits_48 {
ZapMegaHeader::FLAG_HASH_BITS_48
} else {
0
} | if self.key_u64 {
ZapMegaHeader::FLAG_KEY_U64
} else {
0
} | if self.pre_hashed_key {
ZapMegaHeader::FLAG_PRE_HASHED_KEY
} else {
0
});
encoder.put_u64(flags)?;
Ok(())
}
pub fn get_padding_size_and_embedded_leaf_pointer_count(
block_size: usize,
) -> Result<(usize, usize), ZapMegaHeaderDecodeError> {
if block_size < (1 << SECTOR_SHIFT) || !block_size.is_power_of_two() {
return Err(ZapMegaHeaderDecodeError::BlockSize { block_size });
}
let half = block_size / 2;
let padding = half - ZapMegaHeader::SIZE;
let leaves = half / 8;
Ok((padding, leaves))
}
}
#[derive(Debug)]
pub enum ZapMegaHeaderDecodeError {
Binary {
err: BinaryDecodeError,
},
BlockSize {
block_size: usize,
},
BlockType {
block_type: u64,
},
CaseNormalization {
err: ZapCaseNormalizationError,
},
Flags {
flags: u64,
},
Magic {
magic: u64,
},
Normalization {
normalization: u64,
},
UnicodeNormalization {
err: ZapUnicodeNormalizationError,
},
ZapMegaPointerTable {
err: ZapMegaPointerTableDecodeError,
},
}
impl From<BinaryDecodeError> for ZapMegaHeaderDecodeError {
fn from(err: BinaryDecodeError) -> Self {
ZapMegaHeaderDecodeError::Binary { err }
}
}
impl From<ZapCaseNormalizationError> for ZapMegaHeaderDecodeError {
fn from(err: ZapCaseNormalizationError) -> Self {
ZapMegaHeaderDecodeError::CaseNormalization { err }
}
}
impl From<ZapMegaPointerTableDecodeError> for ZapMegaHeaderDecodeError {
fn from(err: ZapMegaPointerTableDecodeError) -> Self {
ZapMegaHeaderDecodeError::ZapMegaPointerTable { err }
}
}
impl From<ZapUnicodeNormalizationError> for ZapMegaHeaderDecodeError {
fn from(err: ZapUnicodeNormalizationError) -> Self {
ZapMegaHeaderDecodeError::UnicodeNormalization { err }
}
}
impl fmt::Display for ZapMegaHeaderDecodeError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
ZapMegaHeaderDecodeError::Binary { err } => {
write!(f, "ZapMegaHeader decode error | {err}")
}
ZapMegaHeaderDecodeError::BlockSize { block_size } => {
write!(
f,
"ZapMegaHeader decode error, invalid block size {block_size}"
)
}
ZapMegaHeaderDecodeError::BlockType { block_type } => {
write!(
f,
"ZapMegaHeader decode error, invalid block type {block_type}"
)
}
ZapMegaHeaderDecodeError::CaseNormalization { err } => {
write!(f, "ZapMegaHeader decode error | {err}")
}
ZapMegaHeaderDecodeError::Flags { flags } => {
write!(f, "ZapMegaHeader decode error unknown flags {flags:#016x}")
}
ZapMegaHeaderDecodeError::Magic { magic } => {
write!(f, "ZapMegaHeader decode error, invalid magic {magic}")
}
ZapMegaHeaderDecodeError::Normalization { normalization } => {
write!(
f,
"ZapMegaHeader decode error, unknown normalization {normalization}"
)
}
ZapMegaHeaderDecodeError::UnicodeNormalization { err } => {
write!(f, "ZapMegaHeader decode error | {err}")
}
ZapMegaHeaderDecodeError::ZapMegaPointerTable { err } => {
write!(f, "ZapMegaHeader decode error | {err}")
}
}
}
}
#[cfg(feature = "std")]
impl error::Error for ZapMegaHeaderDecodeError {
fn source(&self) -> Option<&(dyn error::Error + 'static)> {
match self {
ZapMegaHeaderDecodeError::Binary { err } => Some(err),
ZapMegaHeaderDecodeError::CaseNormalization { err } => Some(err),
ZapMegaHeaderDecodeError::UnicodeNormalization { err } => Some(err),
ZapMegaHeaderDecodeError::ZapMegaPointerTable { err } => Some(err),
_ => None,
}
}
}
#[derive(Debug)]
pub enum ZapMegaHeaderEncodeError {
Binary {
err: BinaryEncodeError,
},
ZapMegaPointerTable {
err: ZapMegaPointerTableEncodeError,
},
}
impl From<BinaryEncodeError> for ZapMegaHeaderEncodeError {
fn from(err: BinaryEncodeError) -> Self {
ZapMegaHeaderEncodeError::Binary { err }
}
}
impl From<ZapMegaPointerTableEncodeError> for ZapMegaHeaderEncodeError {
fn from(value: ZapMegaPointerTableEncodeError) -> Self {
ZapMegaHeaderEncodeError::ZapMegaPointerTable { err: value }
}
}
impl fmt::Display for ZapMegaHeaderEncodeError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
ZapMegaHeaderEncodeError::Binary { err } => {
write!(f, "ZapMegaHeader encode error | {err}")
}
ZapMegaHeaderEncodeError::ZapMegaPointerTable { err } => {
write!(f, "ZapMegaHeader encode error | {err}")
}
}
}
}
#[cfg(feature = "std")]
impl error::Error for ZapMegaHeaderEncodeError {
fn source(&self) -> Option<&(dyn error::Error + 'static)> {
match self {
ZapMegaHeaderEncodeError::Binary { err } => Some(err),
ZapMegaHeaderEncodeError::ZapMegaPointerTable { err } => Some(err),
}
}
}
#[derive(Debug)]
pub enum ZapHeader {
Mega(ZapMegaHeader),
Micro(ZapMicroHeader),
}
impl ZapHeader {
pub fn from_decoder(
decoder: &mut dyn BinaryDecoder<'_>,
) -> Result<ZapHeader, ZapHeaderDecodeError> {
let block_type = decoder.get_u64()?;
decoder.rewind(8)?;
match block_type {
ZapMegaHeader::BLOCK_TYPE => Ok(ZapHeader::Mega(ZapMegaHeader::from_decoder(decoder)?)),
ZapMicroHeader::BLOCK_TYPE => {
Ok(ZapHeader::Micro(ZapMicroHeader::from_decoder(decoder)?))
}
_ => Err(ZapHeaderDecodeError::BlockType { block_type }),
}
}
pub fn to_encoder(
&self,
encoder: &mut dyn BinaryEncoder<'_>,
) -> Result<(), ZapHeaderEncodeError> {
match self {
ZapHeader::Mega(header) => header.to_encoder(encoder)?,
ZapHeader::Micro(header) => header.to_encoder(encoder)?,
}
Ok(())
}
}
#[derive(Debug)]
pub enum ZapHeaderDecodeError {
Binary {
err: BinaryDecodeError,
},
BlockType {
block_type: u64,
},
ZapMegaHeader {
err: ZapMegaHeaderDecodeError,
},
ZapMicroHeader {
err: ZapMicroHeaderDecodeError,
},
}
impl From<BinaryDecodeError> for ZapHeaderDecodeError {
fn from(err: BinaryDecodeError) -> Self {
ZapHeaderDecodeError::Binary { err }
}
}
impl From<ZapMegaHeaderDecodeError> for ZapHeaderDecodeError {
fn from(err: ZapMegaHeaderDecodeError) -> Self {
ZapHeaderDecodeError::ZapMegaHeader { err }
}
}
impl From<ZapMicroHeaderDecodeError> for ZapHeaderDecodeError {
fn from(err: ZapMicroHeaderDecodeError) -> Self {
ZapHeaderDecodeError::ZapMicroHeader { err }
}
}
impl fmt::Display for ZapHeaderDecodeError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
ZapHeaderDecodeError::Binary { err } => {
write!(f, "ZapHeader decode error | {err}")
}
ZapHeaderDecodeError::BlockType { block_type } => {
write!(f, "ZapHeader decode error, unknown block type {block_type}")
}
ZapHeaderDecodeError::ZapMicroHeader { err } => {
write!(f, "ZapHeader decode error | {err}")
}
ZapHeaderDecodeError::ZapMegaHeader { err } => {
write!(f, "ZapHeader decode error | {err}")
}
}
}
}
#[cfg(feature = "std")]
impl error::Error for ZapHeaderDecodeError {
fn source(&self) -> Option<&(dyn error::Error + 'static)> {
match self {
ZapHeaderDecodeError::Binary { err } => Some(err),
ZapHeaderDecodeError::ZapMegaHeader { err } => Some(err),
ZapHeaderDecodeError::ZapMicroHeader { err } => Some(err),
_ => None,
}
}
}
#[derive(Debug)]
pub enum ZapHeaderEncodeError {
ZapMegaHeader {
err: ZapMegaHeaderEncodeError,
},
ZapMicroHeader {
err: ZapMicroHeaderEncodeError,
},
}
impl From<ZapMegaHeaderEncodeError> for ZapHeaderEncodeError {
fn from(err: ZapMegaHeaderEncodeError) -> Self {
ZapHeaderEncodeError::ZapMegaHeader { err }
}
}
impl From<ZapMicroHeaderEncodeError> for ZapHeaderEncodeError {
fn from(err: ZapMicroHeaderEncodeError) -> Self {
ZapHeaderEncodeError::ZapMicroHeader { err }
}
}
impl fmt::Display for ZapHeaderEncodeError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
ZapHeaderEncodeError::ZapMicroHeader { err } => {
write!(f, "ZapHeader encode error | {err}")
}
ZapHeaderEncodeError::ZapMegaHeader { err } => {
write!(f, "ZapHeader encode error | {err}")
}
}
}
}
#[cfg(feature = "std")]
impl error::Error for ZapHeaderEncodeError {
fn source(&self) -> Option<&(dyn error::Error + 'static)> {
match self {
ZapHeaderEncodeError::ZapMegaHeader { err } => Some(err),
ZapHeaderEncodeError::ZapMicroHeader { err } => Some(err),
}
}
}
const ZAP_LEAF_EOL: u16 = 0xffff;
const ZAP_LEAF_HEADER_FLAG_CD_SORTED_MASK: u8 = 1;
const ZAP_LEAF_HEADER_FLAG_ALL: u8 = ZAP_LEAF_HEADER_FLAG_CD_SORTED_MASK;
#[derive(Debug)]
pub struct ZapLeafHeader {
pub hash_prefix: u64,
pub hash_prefix_len: u16,
pub number_of_free_chunks: u16,
pub number_of_entries: u16,
pub next_free_chunk: Option<u16>,
pub cd_sorted: bool,
}
impl ZapLeafHeader {
pub const SIZE: usize = 48;
pub const BLOCK_TYPE: u64 = 0x8000000000000000;
pub const MAGIC: u32 = 0x02AB1EAF;
const PADDING_SIZE_A: usize = 8;
const PADDING_SIZE_B: usize = 11;
pub fn from_decoder(
decoder: &mut dyn BinaryDecoder<'_>,
) -> Result<ZapLeafHeader, ZapLeafHeaderDecodeError> {
let block_type = decoder.get_u64()?;
if block_type != ZapLeafHeader::BLOCK_TYPE {
return Err(ZapLeafHeaderDecodeError::BlockType { block_type });
}
decoder.skip_zeros(ZapLeafHeader::PADDING_SIZE_A)?;
let hash_prefix = decoder.get_u64()?;
let magic = decoder.get_u32()?;
if magic != ZapLeafHeader::MAGIC {
return Err(ZapLeafHeaderDecodeError::Magic { magic });
}
let number_of_free_chunks = decoder.get_u16()?;
let number_of_entries = decoder.get_u16()?;
let hash_prefix_len = decoder.get_u16()?;
let next_free_chunk = match decoder.get_u16()? {
ZAP_LEAF_EOL => None,
v => Some(v),
};
let flags = decoder.get_u8()?;
if (flags & ZAP_LEAF_HEADER_FLAG_ALL) != flags {
return Err(ZapLeafHeaderDecodeError::Flags { flags });
}
decoder.skip_zeros(ZapLeafHeader::PADDING_SIZE_B)?;
Ok(ZapLeafHeader {
hash_prefix,
number_of_free_chunks,
number_of_entries,
hash_prefix_len,
next_free_chunk,
cd_sorted: (flags & ZAP_LEAF_HEADER_FLAG_CD_SORTED_MASK) != 0,
})
}
pub fn to_encoder(
&self,
encoder: &mut dyn BinaryEncoder<'_>,
) -> Result<(), ZapLeafHeaderEncodeError> {
encoder.put_u64(ZapLeafHeader::BLOCK_TYPE)?;
encoder.put_zeros(ZapLeafHeader::PADDING_SIZE_A)?;
encoder.put_u64(self.hash_prefix)?;
encoder.put_u32(ZapLeafHeader::MAGIC)?;
encoder.put_u16(self.number_of_free_chunks)?;
encoder.put_u16(self.number_of_entries)?;
encoder.put_u16(self.hash_prefix_len)?;
encoder.put_u16(self.next_free_chunk.unwrap_or(ZAP_LEAF_EOL))?;
let flags = if self.cd_sorted {
ZAP_LEAF_HEADER_FLAG_CD_SORTED_MASK
} else {
0
};
encoder.put_u8(flags)?;
encoder.put_zeros(ZapLeafHeader::PADDING_SIZE_B)?;
Ok(())
}
pub fn get_entries_and_chunks_counts(
block_size: usize,
) -> Result<(usize, usize), ZapMegaHeaderDecodeError> {
if block_size < (1 << SECTOR_SHIFT) || !block_size.is_power_of_two() {
return Err(ZapMegaHeaderDecodeError::BlockSize { block_size });
}
let entries_count = block_size >> 5;
let chunks_count =
(block_size - (ZapLeafHeader::SIZE + 2 * entries_count)) / ZapLeafChunk::SIZE;
debug_assert!(
ZapLeafHeader::SIZE + 2 * entries_count + chunks_count * ZapLeafChunk::SIZE
== block_size
);
Ok((entries_count, chunks_count))
}
}
#[derive(Debug)]
pub enum ZapLeafHeaderDecodeError {
Binary {
err: BinaryDecodeError,
},
BlockSize {
block_size: usize,
},
BlockType {
block_type: u64,
},
Flags {
flags: u8,
},
Magic {
magic: u32,
},
}
impl From<BinaryDecodeError> for ZapLeafHeaderDecodeError {
fn from(err: BinaryDecodeError) -> Self {
ZapLeafHeaderDecodeError::Binary { err }
}
}
impl fmt::Display for ZapLeafHeaderDecodeError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
ZapLeafHeaderDecodeError::BlockSize { block_size } => {
write!(
f,
"ZapLeafHeader decode error, invalid block size {block_size}"
)
}
ZapLeafHeaderDecodeError::BlockType { block_type } => {
write!(
f,
"ZapLeafHeader decode error, invalid block type {block_type}"
)
}
ZapLeafHeaderDecodeError::Binary { err } => {
write!(f, "ZapLeafHeader decode error | {err}")
}
ZapLeafHeaderDecodeError::Flags { flags } => {
write!(f, "ZapLeafHeader decode error, unknown flags {flags}")
}
ZapLeafHeaderDecodeError::Magic { magic } => {
write!(f, "ZapLeafHeader decode error, invalid magic {magic}")
}
}
}
}
#[cfg(feature = "std")]
impl error::Error for ZapLeafHeaderDecodeError {
fn source(&self) -> Option<&(dyn error::Error + 'static)> {
match self {
ZapLeafHeaderDecodeError::Binary { err } => Some(err),
_ => None,
}
}
}
#[derive(Debug)]
pub enum ZapLeafHeaderEncodeError {
Binary {
err: BinaryEncodeError,
},
}
impl From<BinaryEncodeError> for ZapLeafHeaderEncodeError {
fn from(err: BinaryEncodeError) -> Self {
ZapLeafHeaderEncodeError::Binary { err }
}
}
impl fmt::Display for ZapLeafHeaderEncodeError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
ZapLeafHeaderEncodeError::Binary { err } => {
write!(f, "ZapLeafHeader encode error | {err}")
}
}
}
}
#[cfg(feature = "std")]
impl error::Error for ZapLeafHeaderEncodeError {
fn source(&self) -> Option<&(dyn error::Error + 'static)> {
match self {
ZapLeafHeaderEncodeError::Binary { err } => Some(err),
}
}
}
#[derive(Debug)]
pub struct ZapLeafChunkData {
pub data: [u8; ZapLeafChunkData::ZAP_LEAF_DATA_SIZE],
pub next: Option<u16>,
}
impl ZapLeafChunkData {
pub const CHUNK_TYPE: u8 = 251;
pub const ZAP_LEAF_DATA_SIZE: usize = 21;
pub fn from_decoder(
decoder: &mut dyn BinaryDecoder<'_>,
) -> Result<ZapLeafChunkData, ZapLeafChunkDecodeError> {
let chunk_type = decoder.get_u8()?;
if chunk_type != ZapLeafChunkData::CHUNK_TYPE {
return Err(ZapLeafChunkDecodeError::ChunkType { chunk_type });
}
let data = decoder.get_bytes_n(ZapLeafChunkData::ZAP_LEAF_DATA_SIZE)?;
let next = match decoder.get_u16()? {
ZAP_LEAF_EOL => None,
v => Some(v),
};
Ok(ZapLeafChunkData {
data: data.try_into().unwrap(),
next,
})
}
pub fn to_encoder(
&self,
encoder: &mut dyn BinaryEncoder<'_>,
) -> Result<(), ZapLeafChunkEncodeError> {
encoder.put_u8(ZapLeafChunkData::CHUNK_TYPE)?;
encoder.put_bytes(&self.data)?;
encoder.put_u16(self.next.unwrap_or(ZAP_LEAF_EOL))?;
Ok(())
}
}
#[derive(Debug)]
pub struct ZapLeafChunkEntry {
pub hash: u64,
pub cd: u32,
pub name_chunk: u16,
pub name_length: u16,
pub value_chunk: u16,
pub value_length: u16,
pub value_int_size: u8,
pub next: Option<u16>,
}
impl ZapLeafChunkEntry {
pub const CHUNK_TYPE: u8 = 252;
pub fn from_decoder(
decoder: &mut dyn BinaryDecoder<'_>,
) -> Result<ZapLeafChunkEntry, ZapLeafChunkDecodeError> {
let chunk_type = decoder.get_u8()?;
if chunk_type != ZapLeafChunkEntry::CHUNK_TYPE {
return Err(ZapLeafChunkDecodeError::ChunkType { chunk_type });
}
let value_int_size = decoder.get_u8()?;
let next = match decoder.get_u16()? {
ZAP_LEAF_EOL => None,
v => Some(v),
};
let name_chunk = decoder.get_u16()?;
let name_length = decoder.get_u16()?;
let value_chunk = decoder.get_u16()?;
let value_length = decoder.get_u16()?;
let cd = decoder.get_u32()?;
let hash = decoder.get_u64()?;
Ok(ZapLeafChunkEntry {
hash,
cd,
name_chunk,
name_length,
value_chunk,
value_length,
value_int_size,
next,
})
}
pub fn to_encoder(
&self,
encoder: &mut dyn BinaryEncoder<'_>,
) -> Result<(), ZapLeafChunkEncodeError> {
encoder.put_u8(ZapLeafChunkEntry::CHUNK_TYPE)?;
encoder.put_u8(self.value_int_size)?;
encoder.put_u16(self.next.unwrap_or(ZAP_LEAF_EOL))?;
encoder.put_u16(self.name_chunk)?;
encoder.put_u16(self.name_length)?;
encoder.put_u16(self.value_chunk)?;
encoder.put_u16(self.value_length)?;
encoder.put_u32(self.cd)?;
encoder.put_u64(self.hash)?;
Ok(())
}
}
#[derive(Debug)]
pub struct ZapLeafChunkFree {
next: Option<u16>,
}
impl ZapLeafChunkFree {
pub const CHUNK_TYPE: u8 = 253;
pub fn from_decoder(
decoder: &mut dyn BinaryDecoder<'_>,
) -> Result<ZapLeafChunkFree, ZapLeafChunkDecodeError> {
let chunk_type = decoder.get_u8()?;
if chunk_type != ZapLeafChunkFree::CHUNK_TYPE {
return Err(ZapLeafChunkDecodeError::ChunkType { chunk_type });
}
decoder.skip(ZapLeafChunkData::ZAP_LEAF_DATA_SIZE)?;
let next = match decoder.get_u16()? {
ZAP_LEAF_EOL => None,
v => Some(v),
};
Ok(ZapLeafChunkFree { next })
}
pub fn to_encoder(
&self,
encoder: &mut dyn BinaryEncoder<'_>,
) -> Result<(), ZapLeafChunkEncodeError> {
encoder.put_u8(ZapLeafChunkFree::CHUNK_TYPE)?;
encoder.put_zeros(ZapLeafChunkData::ZAP_LEAF_DATA_SIZE)?;
encoder.put_u16(self.next.unwrap_or(ZAP_LEAF_EOL))?;
Ok(())
}
}
#[derive(Debug)]
pub enum ZapLeafChunk {
Array(ZapLeafChunkData),
Entry(ZapLeafChunkEntry),
Free(ZapLeafChunkFree),
}
impl ZapLeafChunk {
pub const SIZE: usize = 24;
pub fn from_decoder(
decoder: &mut dyn BinaryDecoder<'_>,
) -> Result<ZapLeafChunk, ZapLeafChunkDecodeError> {
let chunk_type = decoder.get_u8()?;
decoder.rewind(1)?;
match chunk_type {
ZapLeafChunkData::CHUNK_TYPE => Ok(ZapLeafChunk::Array(
ZapLeafChunkData::from_decoder(decoder)?,
)),
ZapLeafChunkEntry::CHUNK_TYPE => Ok(ZapLeafChunk::Entry(
ZapLeafChunkEntry::from_decoder(decoder)?,
)),
ZapLeafChunkFree::CHUNK_TYPE => {
Ok(ZapLeafChunk::Free(ZapLeafChunkFree::from_decoder(decoder)?))
}
_ => Err(ZapLeafChunkDecodeError::ChunkType { chunk_type }),
}
}
pub fn to_encoder(
&self,
encoder: &mut dyn BinaryEncoder<'_>,
) -> Result<(), ZapLeafChunkEncodeError> {
match self {
ZapLeafChunk::Array(array) => array.to_encoder(encoder),
ZapLeafChunk::Entry(entry) => entry.to_encoder(encoder),
ZapLeafChunk::Free(free) => free.to_encoder(encoder),
}
}
}
#[derive(Debug)]
pub enum ZapLeafChunkDecodeError {
Binary {
err: BinaryDecodeError,
},
ChunkType {
chunk_type: u8,
},
}
impl From<BinaryDecodeError> for ZapLeafChunkDecodeError {
fn from(err: BinaryDecodeError) -> Self {
ZapLeafChunkDecodeError::Binary { err }
}
}
impl fmt::Display for ZapLeafChunkDecodeError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
ZapLeafChunkDecodeError::Binary { err } => {
write!(f, "ZapLeafChunk decode error | {err}")
}
ZapLeafChunkDecodeError::ChunkType { chunk_type } => {
write!(
f,
"ZapLeafChunk decode error, unknown chunk type {chunk_type}"
)
}
}
}
}
#[cfg(feature = "std")]
impl error::Error for ZapLeafChunkDecodeError {
fn source(&self) -> Option<&(dyn error::Error + 'static)> {
match self {
ZapLeafChunkDecodeError::Binary { err } => Some(err),
ZapLeafChunkDecodeError::ChunkType { chunk_type: _ } => None,
}
}
}
#[derive(Debug)]
pub enum ZapLeafChunkEncodeError {
Binary {
err: BinaryEncodeError,
},
}
impl From<BinaryEncodeError> for ZapLeafChunkEncodeError {
fn from(err: BinaryEncodeError) -> Self {
ZapLeafChunkEncodeError::Binary { err }
}
}
impl fmt::Display for ZapLeafChunkEncodeError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
ZapLeafChunkEncodeError::Binary { err } => {
write!(f, "ZapLeafChunk encode error | {err}")
}
}
}
}
#[cfg(feature = "std")]
impl error::Error for ZapLeafChunkEncodeError {
fn source(&self) -> Option<&(dyn error::Error + 'static)> {
match self {
ZapLeafChunkEncodeError::Binary { err } => Some(err),
}
}
}