jubako 0.4.0

The reference implementation of the Jubako container format
Documentation
use super::super::{PropertyName, VariantName};
use super::properties::Properties;
use crate::bases::Serializable;
use crate::bases::*;
use crate::creator::directory_pack::EntryTrait;
use crate::creator::Result;
use std::collections::HashMap;

#[derive(Debug)]
pub(crate) struct Entry<PN: PropertyName, VN: VariantName> {
    pub common: Properties<PN>,
    pub variants: Vec<Properties<PN>>,
    pub variants_map: HashMap<VN, VariantIdx>,
    pub entry_size: u16,
}

impl<PN: PropertyName, VN: VariantName> Entry<PN, VN> {
    pub fn serialize_entry(
        &self,
        entry: &dyn EntryTrait<PN, VN>,
        ser: &mut Serializer,
    ) -> Result<usize> {
        assert!(self.variants.is_empty() == entry.variant_name().is_none());
        let written = if self.variants.is_empty() {
            Properties::serialize_entry(self.common.iter(), None, entry, ser)?
        } else {
            let variant_id = self.variants_map[&entry.variant_name().unwrap()];
            let mut keys = self
                .common
                .iter()
                .chain(self.variants[variant_id.into_usize()].iter());
            Properties::serialize_entry(&mut keys, Some(variant_id), entry, ser)?
        };
        assert_eq!(written, self.entry_size as usize);
        Ok(written)
    }

    fn key_count(&self) -> Count<u8> {
        (self.common.len() as u8 + self.variants.iter().map(|v| v.len() as u8).sum::<u8>()).into()
    }
}

impl<PN: PropertyName, VN: VariantName> Serializable for Entry<PN, VN> {
    fn serialize(&self, ser: &mut Serializer) -> IoResult<usize> {
        let mut written = 0;
        written += ser.write_u16(self.entry_size)?;
        written += ser.write_u8(self.variants.len() as u8)?;
        written += self.key_count().serialize(ser)?;
        written += self.common.serialize(ser)?;
        for variant in &self.variants {
            written += variant.serialize(ser)?;
        }
        Ok(written)
    }
}