use std::path::Path;
use crate::model::AnchorTarget;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[non_exhaustive]
pub enum Format {
Epub,
Azw3,
Mobi,
Kfx,
Markdown,
}
#[derive(Debug, Clone)]
pub struct Resource {
pub data: Vec<u8>,
pub media_type: &'static str,
}
#[derive(Debug, Clone, Default)]
pub struct Contributor {
pub name: String,
pub file_as: Option<String>,
pub role: Option<String>,
}
#[derive(Debug, Clone)]
pub struct CollectionInfo {
pub name: String,
pub collection_type: Option<String>,
pub position: Option<f64>,
}
#[derive(Debug, Clone, Default)]
pub struct Metadata {
pub title: String,
pub authors: Vec<String>,
pub language: String,
pub identifier: String,
pub publisher: Option<String>,
pub description: Option<String>,
pub subjects: Vec<String>,
pub date: Option<String>,
pub rights: Option<String>,
pub cover_image: Option<String>,
pub modified_date: Option<String>,
pub contributors: Vec<Contributor>,
pub title_sort: Option<String>,
pub author_sort: Option<String>,
pub collection: Option<CollectionInfo>,
pub page_progression_direction: Option<String>,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct TocEntry {
pub title: String,
pub href: String,
pub children: Vec<TocEntry>,
pub play_order: Option<usize>,
pub target: Option<AnchorTarget>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum LandmarkType {
Cover,
TitlePage,
Toc,
StartReading,
BodyMatter,
FrontMatter,
BackMatter,
Acknowledgements,
Bibliography,
Glossary,
Index,
Preface,
Endnotes,
Loi,
Lot,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Landmark {
pub landmark_type: LandmarkType,
pub href: String,
pub label: String,
}
impl Format {
pub fn from_path(path: impl AsRef<Path>) -> Option<Self> {
path.as_ref()
.extension()
.and_then(|e| e.to_str())
.and_then(|ext| match ext.to_lowercase().as_str() {
"epub" => Some(Format::Epub),
"azw3" => Some(Format::Azw3),
"mobi" | "azw" => Some(Format::Mobi),
"kfx" => Some(Format::Kfx),
"md" | "txt" => Some(Format::Markdown),
_ => None,
})
}
pub fn can_import(&self) -> bool {
matches!(
self,
Format::Epub | Format::Azw3 | Format::Mobi | Format::Kfx
)
}
pub fn can_export(&self) -> bool {
!matches!(self, Format::Mobi)
}
}
impl TocEntry {
pub fn new(title: impl Into<String>, href: impl Into<String>) -> Self {
Self {
title: title.into(),
href: href.into(),
children: Vec::new(),
play_order: None,
target: None,
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn from_path_recognises_known_extensions() {
assert_eq!(Format::from_path("book.epub"), Some(Format::Epub));
assert_eq!(Format::from_path("book.azw3"), Some(Format::Azw3));
assert_eq!(Format::from_path("book.mobi"), Some(Format::Mobi));
assert_eq!(Format::from_path("book.azw"), Some(Format::Mobi));
assert_eq!(Format::from_path("book.kfx"), Some(Format::Kfx));
assert_eq!(Format::from_path("notes.md"), Some(Format::Markdown));
assert_eq!(Format::from_path("book.AZW"), Some(Format::Mobi));
assert_eq!(Format::from_path("book.unknown"), None);
assert_eq!(Format::from_path("no_extension"), None);
}
}