libwaj 0.4.1

The library to handle waj file, the pack format for web site.
Documentation
use super::entry::*;
use super::entry_type::EntryType;
use super::AllProperties;
use crate::error::{self, WajFormatError};
use jbk::reader::builder::PropertyBuilderTrait;
use jbk::reader::ByteSlice;

pub trait Builder {
    type Entry;

    fn new(properties: &AllProperties) -> Self;
    fn create_entry(&self, idx: jbk::EntryIdx, reader: &ByteSlice) -> jbk::Result<Self::Entry>;
}

impl Builder for () {
    type Entry = ();
    fn new(_properties: &AllProperties) -> Self {}
    fn create_entry(&self, _idx: jbk::EntryIdx, _reader: &ByteSlice) -> jbk::Result<Self::Entry> {
        Ok(())
    }
}

pub trait FullBuilderTrait {
    type Entry: EntryDef;

    fn new(properties: &AllProperties) -> Self;
    fn create_content(
        &self,
        idx: jbk::EntryIdx,
        reader: &ByteSlice,
    ) -> jbk::Result<<Self::Entry as EntryDef>::Content>;
    fn create_redirect(
        &self,
        idx: jbk::EntryIdx,
        reader: &ByteSlice,
    ) -> jbk::Result<<Self::Entry as EntryDef>::Redirect>;
}

impl<C, R> FullBuilderTrait for (C, R)
where
    C: Builder,
    R: Builder,
{
    type Entry = (C::Entry, R::Entry);

    fn new(properties: &AllProperties) -> Self {
        let content_builder = C::new(properties);
        let redirect_builder = R::new(properties);
        (content_builder, redirect_builder)
    }

    fn create_content(
        &self,
        idx: jbk::EntryIdx,
        reader: &ByteSlice,
    ) -> jbk::Result<<Self::Entry as EntryDef>::Content> {
        self.0.create_entry(idx, reader)
    }

    fn create_redirect(
        &self,
        idx: jbk::EntryIdx,
        reader: &ByteSlice,
    ) -> jbk::Result<<Self::Entry as EntryDef>::Redirect> {
        self.1.create_entry(idx, reader)
    }
}

pub(crate) struct RealBuilder<B: FullBuilderTrait> {
    store: jbk::reader::EntryStore,
    variant_id_property: jbk::reader::builder::VariantIdBuilder<EntryType>,
    builder: B,
}

impl<B> RealBuilder<B>
where
    B: FullBuilderTrait,
{
    pub fn new(properties: &AllProperties) -> Self {
        let builder = B::new(properties);
        Self {
            store: properties.store.clone(),
            variant_id_property: properties.variant_id_property.clone(),
            builder,
        }
    }
}

impl<B> jbk::reader::builder::BuilderTrait for RealBuilder<B>
where
    B: FullBuilderTrait,
{
    type Entry = Entry<B::Entry>;
    type Error = error::BaseError;

    fn create_entry(&self, idx: jbk::EntryIdx) -> Result<Option<Self::Entry>, Self::Error> {
        self.store
            .get_entry_reader(idx)
            .map(|reader| {
                let entry_type = self.variant_id_property.create(&reader)?;
                Ok(match entry_type {
                    Some(EntryType::Content) => {
                        let entry = self.builder.create_content(idx, &reader)?;
                        Entry::Content(entry)
                    }
                    Some(EntryType::Redirect) => {
                        let entry = self.builder.create_redirect(idx, &reader)?;
                        Entry::Redirect(entry)
                    }
                    None => {
                        return Err(error::BaseError::WajFormatError(WajFormatError(
                            "Unknow variant",
                        )))
                    }
                })
            })
            .transpose()
    }
}