#[cfg(feature = "write")]
mod write;
use crate::ebook::element::{Attributes, AttributesData, Href, TextDirection};
use crate::epub::metadata::{
EpubMetaEntry, EpubMetaEntryData, EpubRefinements, EpubRefinementsData, EpubVersion,
};
use crate::util::collection::{Keyed, KeyedVec};
use crate::util::uri;
#[cfg(feature = "write")]
pub use write::{EpubPackageMut, PrefixesMutIter};
#[derive(Debug, PartialEq)]
pub(super) struct EpubPackageData {
pub(super) location: String,
pub(super) version: EpubVersionData,
pub(super) unique_identifier: String,
pub(super) prefixes: Prefixes,
pub(super) language: Option<String>,
pub(super) text_direction: TextDirection,
pub(super) attributes: AttributesData,
}
#[derive(Debug, PartialEq)]
pub(super) struct EpubVersionData {
pub(super) raw: String,
pub(super) parsed: EpubVersion,
}
impl From<EpubVersion> for EpubVersionData {
fn from(parsed: EpubVersion) -> Self {
Self {
raw: parsed.to_string(),
parsed,
}
}
}
impl<'ebook> From<&'ebook EpubPackageData> for EpubPackageMetaContext<'ebook> {
fn from(value: &'ebook EpubPackageData) -> Self {
Self::new(value)
}
}
#[derive(Copy, Clone, Debug)]
pub(super) struct EpubPackageMetaContext<'ebook>(Option<&'ebook EpubPackageData>);
impl<'ebook> EpubPackageMetaContext<'ebook> {
#[cfg(feature = "write")]
pub(super) const EMPTY: EpubPackageMetaContext<'static> = EpubPackageMetaContext(None);
pub(super) fn new(package: &'ebook EpubPackageData) -> Self {
Self(Some(package))
}
pub(super) fn package_language(&self) -> Option<&'ebook str> {
self.0?.language.as_deref()
}
pub(super) fn package_text_direction(&self) -> TextDirection {
self.0
.as_ref()
.map_or(TextDirection::Auto, |pkg| pkg.text_direction)
}
pub(super) fn create_entry(
self,
data: &'ebook EpubMetaEntryData,
index: usize,
) -> EpubMetaEntry<'ebook> {
EpubMetaEntry::new(self, None, data, index)
}
pub(super) fn create_refining_entry(
self,
parent_id: Option<&'ebook str>,
data: &'ebook EpubMetaEntryData,
index: usize,
) -> EpubMetaEntry<'ebook> {
EpubMetaEntry::new(self, parent_id, data, index)
}
pub(super) fn create_refinements(
self,
parent_id: Option<&'ebook str>,
data: &'ebook EpubRefinementsData,
) -> EpubRefinements<'ebook> {
EpubRefinements::new(self, parent_id, data)
}
}
#[derive(Copy, Clone, Debug, PartialEq)]
pub struct EpubPackage<'ebook>(&'ebook EpubPackageData);
impl<'ebook> EpubPackage<'ebook> {
pub(super) fn new(data: &'ebook EpubPackageData) -> Self {
Self(data)
}
pub fn location(&self) -> Href<'ebook> {
Href::new(&self.0.location)
}
pub fn directory(&self) -> Href<'ebook> {
Href::new(uri::parent(&self.0.location))
}
pub fn version(&self) -> EpubVersion {
self.0.version.parsed
}
pub fn version_str(&self) -> &'ebook str {
self.0.version.raw.as_str()
}
pub fn unique_identifier(&self) -> &'ebook str {
&self.0.unique_identifier
}
pub fn text_direction(&self) -> TextDirection {
self.0.text_direction
}
pub fn xml_language(&self) -> Option<&'ebook str> {
self.0.language.as_deref()
}
pub fn prefixes(&self) -> &'ebook Prefixes {
&self.0.prefixes
}
pub fn attributes(&self) -> &'ebook Attributes {
&self.0.attributes
}
}
#[derive(Debug, PartialEq)]
pub struct Prefixes(KeyedVec<Prefix>);
impl Prefixes {
pub(super) const EMPTY: Self = Self::new(Vec::new());
pub(super) const fn new(prefixes: Vec<Prefix>) -> Self {
Self(KeyedVec(prefixes))
}
pub fn len(&self) -> usize {
self.0.len()
}
pub fn is_empty(&self) -> bool {
self.0.is_empty()
}
pub fn get(&self, index: usize) -> Option<&Prefix> {
self.0.get(index)
}
pub fn iter(&self) -> PrefixesIter<'_> {
PrefixesIter(self.0.0.iter())
}
pub fn by_name(&self, name: &str) -> Option<&Prefix> {
self.0.by_key(name)
}
pub fn get_uri(&self, name: &str) -> Option<&str> {
self.0.by_key(name).map(|prefix| prefix.uri.as_str())
}
pub fn has_name(&self, name: &str) -> bool {
self.0.has_key(name)
}
}
impl<'ebook> IntoIterator for &'ebook Prefixes {
type Item = &'ebook Prefix;
type IntoIter = PrefixesIter<'ebook>;
fn into_iter(self) -> Self::IntoIter {
self.iter()
}
}
#[derive(Clone, Debug)]
pub struct PrefixesIter<'ebook>(std::slice::Iter<'ebook, Prefix>);
impl<'ebook> Iterator for PrefixesIter<'ebook> {
type Item = &'ebook Prefix;
fn next(&mut self) -> Option<Self::Item> {
self.0.next()
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.0.size_hint()
}
}
#[derive(Clone, Debug, Hash, PartialEq, Eq)]
pub struct Prefix {
name: String,
uri: String,
}
impl Prefix {
pub fn create(name: impl Into<String>, uri: impl Into<String>) -> Self {
Self {
name: name.into(),
uri: uri.into(),
}
}
pub fn name(&self) -> &str {
&self.name
}
pub fn uri(&self) -> &str {
&self.uri
}
}
impl Keyed for Prefix {
type Key = str;
fn key(&self) -> &Self::Key {
&self.name
}
}