use std::io::{self, Read, Seek, SeekFrom};
use crate::builder::BookBuilder;
use crate::errors::MetadataError;
use crate::persistence::datablock::DataBlocksReader;
use crate::{metadata, page, persistence, toc, MetadataEntry};
pub struct Book<I> {
pub(crate) data_blocks: DataBlocksReader<I>,
pub(crate) num_pages: usize,
pub(crate) metadata_pos: usize,
pub(crate) page_index: page::Index,
}
impl Book<()> {
pub fn builder() -> BookBuilder {
BookBuilder::new()
}
}
impl<I: Read + Seek> Book<I> {
pub fn load(input: I) -> Result<Self, persistence::PersistenceError> {
persistence::load(input)
}
pub fn num_pages(&self) -> usize {
self.num_pages
}
pub fn metadata(
&mut self,
) -> io::Result<impl Iterator<Item = Result<MetadataEntry, MetadataError>> + '_> {
let input_len = self.data_blocks.input_stream_len();
let input = self.data_blocks.input_stream();
input.seek(SeekFrom::Start(self.metadata_pos as u64))?;
Ok(metadata::load(input, input_len))
}
pub fn pages(&mut self) -> impl Iterator<Item = Result<page::Page, page::PageError>> + '_ {
self.page_index.pages_iter(&mut self.data_blocks)
}
pub fn get_page_by_id(&mut self, page_id: page::PageId) -> Result<page::Page, page::PageError> {
self.page_index.get_by_id(&mut self.data_blocks, page_id)
}
pub fn toc(&mut self) -> Result<impl Iterator<Item = crate::TocEntry> + '_, toc::TocError> {
let toc = toc::BookToc::new(&mut self.data_blocks, &self.page_index)?;
Ok(toc.into_iter())
}
}