use crate::ebook::manifest::ManifestEntry;
use crate::ebook::resource::Resource;
use crate::util::Sealed;
use std::fmt::Display;
pub trait Spine<'ebook>: Sealed {
fn page_direction(&self) -> PageDirection;
fn len(&self) -> usize;
fn get(&self, index: usize) -> Option<impl SpineEntry<'ebook> + 'ebook>;
fn iter(&self) -> impl Iterator<Item = impl SpineEntry<'ebook> + 'ebook> + 'ebook;
fn is_empty(&self) -> bool {
self.len() == 0
}
}
pub trait SpineEntry<'ebook>: Sealed {
fn order(&self) -> usize;
fn manifest_entry(&self) -> Option<impl ManifestEntry<'ebook> + 'ebook>;
fn resource(&self) -> Option<Resource<'ebook>> {
self.manifest_entry().map(|entry| entry.resource())
}
}
#[non_exhaustive]
#[derive(Copy, Clone, Debug, Default, Hash, PartialEq, Eq)]
pub enum PageDirection {
LeftToRight,
RightToLeft,
#[default]
Default,
}
impl PageDirection {
const DEFAULT: &'static str = "default";
const LEFT_TO_RIGHT: &'static str = "ltr";
const RIGHT_TO_LEFT: &'static str = "rtl";
const LEFT_TO_RIGHT_BYTES: &'static [u8] = Self::LEFT_TO_RIGHT.as_bytes();
const RIGHT_TO_LEFT_BYTES: &'static [u8] = Self::RIGHT_TO_LEFT.as_bytes();
pub(crate) fn from_bytes(bytes: impl AsRef<[u8]>) -> Self {
match bytes.as_ref() {
Self::LEFT_TO_RIGHT_BYTES => Self::LeftToRight,
Self::RIGHT_TO_LEFT_BYTES => Self::RightToLeft,
_ => Self::Default,
}
}
pub fn is_ltr(&self) -> bool {
matches!(self, Self::LeftToRight)
}
pub fn is_rtl(&self) -> bool {
matches!(self, Self::RightToLeft)
}
pub fn is_default(&self) -> bool {
matches!(self, Self::Default)
}
pub fn as_str(&self) -> &'static str {
match self {
Self::LeftToRight => Self::LEFT_TO_RIGHT,
Self::RightToLeft => Self::RIGHT_TO_LEFT,
Self::Default => Self::DEFAULT,
}
}
}
impl Display for PageDirection {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_str(self.as_str())
}
}
#[cfg(test)]
mod tests {
use super::PageDirection;
#[test]
fn test_page_direction_from_bytes() {
let expected = [
(PageDirection::LeftToRight, "ltr"),
(PageDirection::RightToLeft, "rtl"),
(PageDirection::Default, ""),
(PageDirection::Default, "auto"),
(PageDirection::Default, "default"),
(PageDirection::Default, "LTR"),
(PageDirection::Default, "left-to-right"),
];
for (expect, input) in expected {
assert_eq!(expect, PageDirection::from_bytes(input));
}
}
#[test]
fn test_page_direction_display() {
let expected = [
("ltr", PageDirection::LeftToRight),
("rtl", PageDirection::RightToLeft),
("default", PageDirection::Default),
];
for (expect, input) in expected {
assert_eq!(expect, input.to_string());
}
}
}