use alloc::string::ToString;
use super::DictError;
#[cfg(feature = "decompression")]
use super::{Dict, DictId};
use crate::shared::dictwire::WireError;
#[cfg(feature = "decompression")]
use crate::shared::sha256;
impl From<WireError> for DictError {
fn from(error: WireError) -> Self {
match error {
WireError::TooManyDicts(count) => Self::TooManyDicts { count },
WireError::ContentTooLarge => Self::ContentTooLarge,
other => Self::Malformed(other.to_string()),
}
}
}
#[cfg(feature = "decompression")]
pub(crate) fn check_unique(dicts: &[Dict]) -> Result<(), DictError> {
let mut seen: alloc::collections::BTreeMap<DictId, [u8; 32]> =
alloc::collections::BTreeMap::new();
for dict in dicts {
let hash = sha256::digest(dict.content());
if *seen.entry(dict.id()).or_insert(hash) != hash {
return Err(DictError::ConflictingId(dict.id()));
}
}
Ok(())
}
#[cfg(feature = "decompression")]
#[derive(Debug)]
pub(crate) enum Materialized {
#[cfg(feature = "zstd")]
Zstd(mzstd::dictionary::DecodeDictionary),
}
#[cfg(feature = "decompression")]
pub(crate) fn materialize_decode(dict: &Dict) -> Result<Materialized, DictError> {
#[cfg(feature = "zstd")]
if dict.codec() == super::DictCodec::ZSTD {
let content =
crate::shared::dictwire::parse_zstd_content(dict.content()).ok_or_else(|| {
DictError::Materialization("failed to parse trained zstd dict content".into())
})?;
let ddict = mzstd::dictionary::DecodeDictionary::new(
content.raw,
mzstd::dictionary::DictionaryContent::Auto,
)
.map_err(|error| DictError::Materialization(error.to_string()))?;
return Ok(Materialized::Zstd(ddict));
}
Err(DictError::NoMaterializer {
codec: dict.codec(),
})
}