#[cfg(feature = "compression")]
use super::PreparedDictionary;
use crate::shared::decode_dictionary::Prefixes;
#[derive(Clone, Copy, Debug)]
pub enum DictionaryAttachment<'a> {
Raw(&'a [u8]),
#[cfg(feature = "experimental")]
Serialized(&'a [u8]),
}
#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
pub struct DecodeDictionaryLimits {
pub max_source_bytes: Option<u64>,
pub max_owned_bytes: Option<usize>,
}
#[derive(Debug)]
pub struct DecodeDictionary {
prefixes: Prefixes,
}
impl DecodeDictionary {
pub fn new(
attachments: &[DictionaryAttachment<'_>],
limits: DecodeDictionaryLimits,
) -> Result<Self, DecodeDictionaryError> {
Ok(Self {
prefixes: Prefixes::build(attachments, limits)?,
})
}
pub const fn attachment_count(&self) -> usize {
self.prefixes.count()
}
pub const fn retained_bytes(&self) -> usize {
self.prefixes.retained_bytes()
}
}
#[derive(Clone, Copy, Debug)]
pub enum DictionaryRef<'a> {
#[cfg(feature = "compression")]
Prepared(&'a PreparedDictionary),
DecodeOnly(&'a DecodeDictionary),
}
#[cfg(feature = "compression")]
impl<'a> From<&'a PreparedDictionary> for DictionaryRef<'a> {
fn from(value: &'a PreparedDictionary) -> Self {
Self::Prepared(value)
}
}
impl<'a> From<&'a DecodeDictionary> for DictionaryRef<'a> {
fn from(value: &'a DecodeDictionary) -> Self {
Self::DecodeOnly(value)
}
}
impl DictionaryRef<'_> {
#[cfg(feature = "experimental")]
pub(crate) fn custom_word(
self,
address: u64,
length: usize,
context: usize,
scratch: &mut [u8; crate::shared::dictionary::transform::SCRATCH_BYTES],
) -> Option<Result<usize, crate::DecodeError>> {
match self {
#[cfg(feature = "compression")]
Self::Prepared(value) => value
.inner()
.static_index
.as_ref()
.map(|index| index.decode_word(address, length, context, scratch)),
Self::DecodeOnly(value) => value
.prefixes
.description
.as_ref()
.map(|description| description.resolve(address, length, context, scratch)),
}
}
pub(crate) fn prefix_len(self) -> u64 {
match self {
#[cfg(feature = "compression")]
Self::Prepared(value) => value.inner().dictionaries().prefix().total_len(),
Self::DecodeOnly(value) => value.prefixes.total(),
}
}
}
impl<'a> DictionaryRef<'a> {
pub(crate) fn prefix_run(self, offset: u64) -> &'a [u8] {
match self {
#[cfg(feature = "compression")]
Self::Prepared(value) => value.inner().dictionaries().prefix().run_from(offset),
Self::DecodeOnly(value) => value.prefixes.run_from(offset),
}
}
}
#[derive(Debug, thiserror::Error)]
#[non_exhaustive]
pub enum DecodeDictionaryError {
#[cfg(feature = "experimental")]
#[error("invalid serialized decode dictionary")]
InvalidSerializedDictionary,
#[cfg(feature = "experimental")]
#[error("conflicting custom static dictionaries")]
ConflictingStaticDictionaries,
#[error("more than fifteen dictionary prefix attachments")]
TooManyAttachments,
#[error("dictionary source exceeds {limit} bytes")]
SourceLimitExceeded {
limit: u64,
},
#[error("dictionary storage exceeds {limit} bytes")]
MemoryLimitExceeded {
limit: usize,
},
#[error("dictionary allocation failed")]
AllocationFailed,
#[error("dictionary size overflow")]
SizeOverflow,
}