use language_tags::LanguageTag;
pub use error::{Error, ErrorKind};
pub use parser::parse;
mod error;
mod parser;
pub const LINK_TYPE: &str = "simple";
pub(crate) trait FromStrOpt {
fn from_str_or_none(value: &str) -> Option<Self>
where
Self: Sized;
}
#[derive(Debug, PartialEq)]
pub struct FictionBook {
pub stylesheets: Vec<Stylesheet>,
pub description: Description,
pub body: Body,
pub extra_bodies: Vec<Body>,
pub binaries: Vec<Binary>,
}
#[derive(Debug, PartialEq)]
pub struct Stylesheet {
pub kind: String,
pub content: String,
}
#[derive(Debug, PartialEq)]
pub struct Description {
pub title_info: TitleInfo,
pub src_title_info: Option<TitleInfo>,
pub document_info: DocumentInfo,
pub publish_info: Option<PublishInfo>,
pub custom_info: Vec<CustomInfo>,
pub output: Vec<ShareInstruction>,
}
#[derive(Debug, PartialEq)]
pub struct TitleInfo {
pub genres: Vec<GenreWithMatch>,
pub authors: Vec<Author>,
pub book_title: LocalizedText,
pub annotation: Option<Annotation>,
pub keywords: Option<LocalizedText>,
pub date: Option<Date>,
pub cover_page: Option<CoverPage>,
pub lang: String,
pub src_lang: Option<String>,
pub translators: Vec<Author>,
pub sequences: Vec<Sequence>,
}
#[derive(Debug, PartialEq)]
pub struct DocumentInfo {
pub authors: Vec<Author>,
pub program_used: Option<LocalizedText>,
pub date: Date,
pub src_urls: Vec<String>,
pub src_ocr: Option<LocalizedText>,
pub id: String,
pub version: f64,
pub history: Option<Annotation>,
pub publishers: Vec<Author>,
}
#[derive(Debug, PartialEq)]
pub struct PublishInfo {
pub book_name: Option<LocalizedText>,
pub publisher: Option<LocalizedText>,
pub city: Option<LocalizedText>,
pub year: Option<i32>,
pub isbn: Option<LocalizedText>,
pub sequences: Vec<Sequence>,
}
#[derive(Debug, PartialEq)]
pub struct CustomInfo {
pub info_type: String,
pub content: LocalizedText,
}
#[derive(Debug, PartialEq)]
pub struct ShareInstruction {
pub mode: ShareMode,
pub include_all: DocGenerationInstruction,
pub price: Option<f64>,
pub currency: Option<String>,
pub elements: Vec<ShareInstructionElement>,
}
#[derive(Debug, PartialEq)]
pub enum ShareInstructionElement {
Part(PartShareInstruction),
OutputDocumentClass(OutputDocumentClass),
}
#[derive(Debug, PartialEq)]
pub enum ShareMode {
Free,
Paid,
}
impl FromStrOpt for ShareMode {
fn from_str_or_none(value: &str) -> Option<ShareMode> {
use ShareMode::*;
Some(match value {
"free" => Free,
"paid" => Paid,
_ => return None,
})
}
}
#[derive(Debug, PartialEq)]
pub struct OutputDocumentClass {
pub name: String,
pub create: Option<DocGenerationInstruction>,
pub price: Option<f64>,
pub parts: Vec<PartShareInstruction>,
}
#[derive(Debug, PartialEq)]
pub struct PartShareInstruction {
pub kind: &'static str,
pub href: String,
pub include: DocGenerationInstruction,
}
#[derive(Debug, PartialEq)]
pub enum DocGenerationInstruction {
Require,
Allow,
Deny,
}
impl FromStrOpt for DocGenerationInstruction {
fn from_str_or_none(value: &str) -> Option<DocGenerationInstruction> {
use DocGenerationInstruction::*;
Some(match value {
"require" => Require,
"allow" => Allow,
"deny" => Deny,
_ => return None,
})
}
}
#[derive(Debug, PartialEq)]
pub struct Body {
pub name: Option<String>,
pub lang: Option<LanguageTag>,
pub image: Option<Image>,
pub title: Option<Title>,
pub epigraphs: Vec<Epigraph>,
pub sections: Vec<Section>,
}
#[derive(Debug, PartialEq)]
pub struct Sequence {
pub name: String,
pub number: Option<i32>,
pub lang: Option<LanguageTag>,
pub sequences: Vec<Sequence>,
}
#[derive(Debug, PartialEq)]
pub struct CoverPage(pub Vec<InlineImage>);
#[derive(Debug, PartialEq)]
pub struct GenreWithMatch {
pub match_percentage: i32,
pub value: Genre,
}
#[derive(Debug, PartialEq)]
pub enum Author {
Verbose(VerboseAuthorDetails),
Anonymous(AnonymousAuthorDetails),
}
#[derive(Debug, PartialEq)]
pub struct VerboseAuthorDetails {
pub first_name: LocalizedText,
pub middle_name: Option<LocalizedText>,
pub last_name: LocalizedText,
pub nickname: Option<LocalizedText>,
pub home_pages: Vec<String>,
pub emails: Vec<String>,
pub id: Option<String>,
}
#[derive(Debug, PartialEq)]
pub struct AnonymousAuthorDetails {
pub nickname: LocalizedText,
pub home_pages: Vec<String>,
pub emails: Vec<String>,
pub id: Option<String>,
}
#[derive(Debug, PartialEq)]
pub struct Binary {
pub id: String,
pub content_type: String,
pub content: String,
}
#[derive(Debug, PartialEq)]
pub struct Section {
pub id: Option<String>,
pub lang: Option<LanguageTag>,
pub content: Option<SectionContent>,
}
#[derive(Debug, PartialEq)]
pub struct SectionContent {
pub title: Option<Title>,
pub epigraphs: Vec<Epigraph>,
pub image: Option<Image>,
pub annotation: Option<Annotation>,
pub value: SectionContentValue,
}
#[derive(Debug, PartialEq)]
pub enum SectionContentValue {
ChildSections(Vec<Section>),
SectionParts(SectionParts),
}
#[derive(Debug, PartialEq)]
pub struct SectionParts {
pub first: FirstSectionPart,
pub rest: Vec<RestSectionPart>,
}
#[derive(Debug, PartialEq)]
pub enum FirstSectionPart {
Paragraph(Paragraph),
Poem(Poem),
Subtitle(Paragraph),
Cite(Cite),
Table(Table),
EmptyLine,
}
#[derive(Debug, PartialEq)]
pub enum RestSectionPart {
Paragraph(Paragraph),
Poem(Poem),
Subtitle(Paragraph),
Cite(Cite),
Table(Table),
Image(Image),
EmptyLine,
}
#[derive(Debug, PartialEq)]
pub struct Annotation {
pub id: Option<String>,
pub lang: Option<LanguageTag>,
pub elements: Vec<AnnotationElement>,
}
#[derive(Debug, PartialEq)]
pub enum AnnotationElement {
Paragraph(Paragraph),
Poem(Poem),
Cite(Cite),
Subtitle(Paragraph),
Table(Table),
EmptyLine,
}
#[derive(Debug, PartialEq)]
pub struct Epigraph {
pub id: Option<String>,
pub elements: Vec<EpigraphElement>,
pub text_authors: Vec<Paragraph>,
}
#[derive(Debug, PartialEq)]
pub enum EpigraphElement {
Paragraph(Paragraph),
Poem(Poem),
Cite(Cite),
EmptyLine,
}
#[derive(Debug, PartialEq)]
pub struct Cite {
pub id: Option<String>,
pub lang: Option<LanguageTag>,
pub elements: Vec<CiteElement>,
pub text_authors: Vec<Paragraph>,
}
#[derive(Debug, PartialEq)]
pub enum CiteElement {
Paragraph(Paragraph),
Poem(Poem),
Subtitle(Paragraph),
Table(Table),
EmptyLine,
}
#[derive(Debug, PartialEq)]
pub struct Poem {
pub id: Option<String>,
pub lang: Option<LanguageTag>,
pub title: Option<Title>,
pub epigraphs: Vec<Epigraph>,
pub stanzas: Vec<PoemStanza>,
pub text_authors: Vec<Paragraph>,
pub date: Option<Date>,
}
#[derive(Debug, PartialEq)]
pub enum PoemStanza {
Subtitle(Paragraph),
Stanza(Stanza),
}
#[derive(Debug, PartialEq)]
pub struct Stanza {
pub lang: Option<LanguageTag>,
pub title: Option<Title>,
pub subtitle: Option<Paragraph>,
pub lines: Vec<Paragraph>,
}
#[derive(Debug, PartialEq)]
pub struct Title {
pub lang: Option<LanguageTag>,
pub elements: Vec<TitleElement>,
}
#[derive(Debug, PartialEq)]
pub enum TitleElement {
Paragraph(Paragraph),
EmptyLine,
}
#[derive(Debug, PartialEq)]
pub struct Paragraph {
pub id: Option<String>,
pub style: Option<String>,
pub content: Style,
}
#[derive(Debug, PartialEq)]
pub struct Table {
pub id: Option<String>,
pub style: Option<String>,
pub rows: Vec<TableRow>,
}
#[derive(Debug, PartialEq)]
pub struct TableRow {
pub align: HorizontalAlign,
pub cells: Vec<TableCellElement>,
}
#[derive(Debug, PartialEq)]
pub enum TableCellElement {
Head(TableCell),
Data(TableCell),
}
#[derive(Debug, PartialEq)]
pub struct TableCell {
pub id: Option<String>,
pub style: Option<String>,
pub column_span: Option<i32>,
pub row_span: Option<i32>,
pub horizontal_align: HorizontalAlign,
pub vertical_align: VerticalAlign,
pub content: Style,
}
#[derive(Debug, PartialEq)]
pub enum HorizontalAlign {
Left,
Right,
Center,
}
impl FromStrOpt for HorizontalAlign {
fn from_str_or_none(value: &str) -> Option<HorizontalAlign> {
use HorizontalAlign::*;
Some(match value {
"left" => Left,
"right" => Right,
"center" => Center,
_ => return None,
})
}
}
impl Default for HorizontalAlign {
fn default() -> Self {
HorizontalAlign::Left
}
}
#[derive(Debug, PartialEq)]
pub enum VerticalAlign {
Top,
Middle,
Bottom,
}
impl FromStrOpt for VerticalAlign {
fn from_str_or_none(value: &str) -> Option<VerticalAlign> {
use VerticalAlign::*;
Some(match value {
"top" => Top,
"middle" => Middle,
"bottom" => Bottom,
_ => return None,
})
}
}
impl Default for VerticalAlign {
fn default() -> Self {
VerticalAlign::Top
}
}
#[derive(Debug, PartialEq)]
pub struct NamedStyle {
pub name: String,
pub lang: Option<LanguageTag>,
pub elements: Vec<StyleElement>,
}
#[derive(Debug, PartialEq)]
pub struct Style {
pub lang: Option<LanguageTag>,
pub elements: Vec<StyleElement>,
}
#[derive(Debug, PartialEq)]
pub enum StyleElement {
Strong(Style),
Emphasis(Style),
Style(NamedStyle),
Link(Link),
Strikethrough(Style),
Subscript(Style),
Superscript(Style),
Code(Style),
Image(InlineImage),
Text(String),
}
#[derive(Debug, PartialEq)]
pub struct Link {
pub kind: Option<String>,
pub href: String,
pub elements: Vec<StyleLinkElement>,
}
#[derive(Debug, PartialEq)]
pub enum StyleLinkElement {
Strong(Vec<StyleLinkElement>),
Emphasis(Vec<StyleLinkElement>),
Style(Vec<StyleLinkElement>),
Strikethrough(Vec<StyleLinkElement>),
Subscript(Vec<StyleLinkElement>),
Superscript(Vec<StyleLinkElement>),
Code(Vec<StyleLinkElement>),
Image(InlineImage),
Text(String),
}
#[derive(Debug, PartialEq)]
pub struct Date {
pub lang: Option<LanguageTag>,
pub date: Option<chrono::NaiveDate>,
pub display_date: String,
}
#[derive(Debug, PartialEq)]
pub struct Image {
pub kind: &'static str,
pub href: Option<String>,
pub alt: Option<String>,
pub title: Option<String>,
pub id: Option<String>,
}
#[derive(Debug, PartialEq)]
pub struct InlineImage {
pub kind: &'static str,
pub href: Option<String>,
pub alt: Option<String>,
}
#[derive(Debug, PartialEq)]
pub struct LocalizedText {
pub lang: Option<LanguageTag>,
pub content: String,
}
#[derive(Debug, PartialEq)]
pub enum Genre {
Accounting,
AdvAnimal,
AdvGeo,
AdvHistory,
AdvMaritime,
AdvWestern,
Adventure,
Antique,
AntiqueAnt,
AntiqueEast,
AntiqueEuropean,
AntiqueMyths,
AntiqueRussian,
AphorismQuote,
ArchitectureBook,
AutoRegulations,
Banking,
BeginningAuthors,
ChildAdv,
ChildDet,
ChildEducation,
ChildProse,
ChildSf,
ChildTale,
ChildVerse,
Children,
CinemaTheatre,
CityFantasy,
CompDb,
CompHard,
CompOsnet,
CompProgramming,
CompSoft,
CompWww,
Computers,
Design,
DetAction,
DetClassic,
DetCrime,
DetEspionage,
DetHard,
DetHistory,
DetIrony,
DetPolice,
DetPolitical,
Detective,
DragonFantasy,
Dramaturgy,
Economics,
Essays,
FantasyFight,
ForeignAction,
ForeignAdventure,
ForeignAntique,
ForeignBusiness,
ForeignChildren,
ForeignComp,
ForeignContemporary,
ForeignContemporaryLit,
ForeignDesc,
ForeignDetective,
ForeignDramaturgy,
ForeignEdu,
ForeignFantasy,
ForeignHome,
ForeignHumor,
ForeignLanguage,
ForeignLove,
ForeignNovel,
ForeignOther,
ForeignPoetry,
ForeignProse,
ForeignPsychology,
ForeignPublicism,
ForeignReligion,
ForeignSf,
GeoGuides,
GeographyBook,
GlobalEconomy,
HistoricalFantasy,
Home,
HomeCooking,
HomeCrafts,
HomeDiy,
HomeEntertain,
HomeGarden,
HomeHealth,
HomePets,
HomeSex,
HomeSport,
Humor,
HumorAnecdote,
HumorFantasy,
HumorProse,
HumorVerse,
Industries,
JobHunting,
Literature18,
Literature19,
Literature20,
LoveContemporary,
LoveDetective,
LoveErotica,
LoveFantasy,
LoveHistory,
LoveSf,
LoveShort,
MagicianBook,
Management,
Marketing,
MilitarySpecial,
MusicDancing,
Narrative,
Newspapers,
NonfBiography,
NonfCriticism,
NonfPublicism,
Nonfiction,
OrgBehavior,
PaperWork,
PedagogyBook,
Periodic,
PersonalFinance,
Poetry,
Popadanec,
PopularBusiness,
ProseClassic,
ProseCounter,
ProseHistory,
ProseMilitary,
ProseRusClassic,
ProseSuClassics,
PsyAlassic,
PsyChilds,
PsyGeneric,
PsyPersonal,
PsySexAndFamily,
PsySocial,
PsyTheraphy,
RealEstate,
RefDict,
RefEncyc,
RefGuide,
RefRef,
Reference,
Religion,
ReligionEsoterics,
ReligionRel,
ReligionSelf,
RussianContemporary,
RussianFantasy,
SciBiology,
SciChem,
SciCulture,
SciHistory,
SciJuris,
SciLinguistic,
SciMath,
SciMedicine,
SciPhilosophy,
SciPhys,
SciPolitics,
SciReligion,
SciTech,
Science,
Sf,
SfAction,
SfCyberpunk,
SfDetective,
SfFantasy,
SfHeroic,
SfHistory,
SfHorror,
SfHumor,
SfSocial,
SfSpace,
ShortStory,
Sketch,
SmallBusiness,
SociologyBook,
Stock,
Thriller,
UpbringingBook,
VampireBook,
VisualArts,
Unrecognised,
}
impl FromStrOpt for Genre {
fn from_str_or_none(value: &str) -> Option<Self> {
use Genre::*;
Some(match value {
"accounting" => Accounting,
"adv_animal" => AdvAnimal,
"adv_geo" => AdvGeo,
"adv_history" => AdvHistory,
"adv_maritime" => AdvMaritime,
"adv_western" => AdvWestern,
"adventure" => Adventure,
"antique" => Antique,
"antique_ant" => AntiqueAnt,
"antique_east" => AntiqueEast,
"antique_european" => AntiqueEuropean,
"antique_myths" => AntiqueMyths,
"antique_russian" => AntiqueRussian,
"aphorism_quote" => AphorismQuote,
"architecture_book" => ArchitectureBook,
"auto_regulations" => AutoRegulations,
"banking" => Banking,
"beginning_authors" => BeginningAuthors,
"child_adv" => ChildAdv,
"child_det" => ChildDet,
"child_education" => ChildEducation,
"child_prose" => ChildProse,
"child_sf" => ChildSf,
"child_tale" => ChildTale,
"child_verse" => ChildVerse,
"children" => Children,
"cinema_theatre" => CinemaTheatre,
"city_fantasy" => CityFantasy,
"comp_db" => CompDb,
"comp_hard" => CompHard,
"comp_osnet" => CompOsnet,
"comp_programming" => CompProgramming,
"comp_soft" => CompSoft,
"comp_www" => CompWww,
"computers" => Computers,
"design" => Design,
"det_action" => DetAction,
"det_classic" => DetClassic,
"det_crime" => DetCrime,
"det_espionage" => DetEspionage,
"det_hard" => DetHard,
"det_history" => DetHistory,
"det_irony" => DetIrony,
"det_police" => DetPolice,
"det_political" => DetPolitical,
"detective" => Detective,
"dragon_fantasy" => DragonFantasy,
"dramaturgy" => Dramaturgy,
"economics" => Economics,
"essays" => Essays,
"fantasy_fight" => FantasyFight,
"foreign_action" => ForeignAction,
"foreign_adventure" => ForeignAdventure,
"foreign_antique" => ForeignAntique,
"foreign_business" => ForeignBusiness,
"foreign_children" => ForeignChildren,
"foreign_comp" => ForeignComp,
"foreign_contemporary" => ForeignContemporary,
"foreign_contemporary_lit" => ForeignContemporaryLit,
"foreign_desc" => ForeignDesc,
"foreign_detective" => ForeignDetective,
"foreign_dramaturgy" => ForeignDramaturgy,
"foreign_edu" => ForeignEdu,
"foreign_fantasy" => ForeignFantasy,
"foreign_home" => ForeignHome,
"foreign_humor" => ForeignHumor,
"foreign_language" => ForeignLanguage,
"foreign_love" => ForeignLove,
"foreign_novel" => ForeignNovel,
"foreign_other" => ForeignOther,
"foreign_poetry" => ForeignPoetry,
"foreign_prose" => ForeignProse,
"foreign_psychology" => ForeignPsychology,
"foreign_publicism" => ForeignPublicism,
"foreign_religion" => ForeignReligion,
"foreign_sf" => ForeignSf,
"geo_guides" => GeoGuides,
"geography_book" => GeographyBook,
"global_economy" => GlobalEconomy,
"historical_fantasy" => HistoricalFantasy,
"home" => Home,
"home_cooking" => HomeCooking,
"home_crafts" => HomeCrafts,
"home_diy" => HomeDiy,
"home_entertain" => HomeEntertain,
"home_garden" => HomeGarden,
"home_health" => HomeHealth,
"home_pets" => HomePets,
"home_sex" => HomeSex,
"home_sport" => HomeSport,
"humor" => Humor,
"humor_anecdote" => HumorAnecdote,
"humor_fantasy" => HumorFantasy,
"humor_prose" => HumorProse,
"humor_verse" => HumorVerse,
"industries" => Industries,
"job_hunting" => JobHunting,
"literature_18" => Literature18,
"literature_19" => Literature19,
"literature_20" => Literature20,
"love_contemporary" => LoveContemporary,
"love_detective" => LoveDetective,
"love_erotica" => LoveErotica,
"love_fantasy" => LoveFantasy,
"love_history" => LoveHistory,
"love_sf" => LoveSf,
"love_short" => LoveShort,
"magician_book" => MagicianBook,
"management" => Management,
"marketing" => Marketing,
"military_special" => MilitarySpecial,
"music_dancing" => MusicDancing,
"narrative" => Narrative,
"newspapers" => Newspapers,
"nonf_biography" => NonfBiography,
"nonf_criticism" => NonfCriticism,
"nonf_publicism" => NonfPublicism,
"nonfiction" => Nonfiction,
"org_behavior" => OrgBehavior,
"paper_work" => PaperWork,
"pedagogy_book" => PedagogyBook,
"periodic" => Periodic,
"personal_finance" => PersonalFinance,
"poetry" => Poetry,
"popadanec" => Popadanec,
"popular_business" => PopularBusiness,
"prose_classic" => ProseClassic,
"prose_counter" => ProseCounter,
"prose_history" => ProseHistory,
"prose_military" => ProseMilitary,
"prose_rus_classic" => ProseRusClassic,
"prose_su_classics" => ProseSuClassics,
"psy_alassic" => PsyAlassic,
"psy_childs" => PsyChilds,
"psy_generic" => PsyGeneric,
"psy_personal" => PsyPersonal,
"psy_sex_and_family" => PsySexAndFamily,
"psy_social" => PsySocial,
"psy_theraphy" => PsyTheraphy,
"real_estate" => RealEstate,
"ref_dict" => RefDict,
"ref_encyc" => RefEncyc,
"ref_guide" => RefGuide,
"ref_ref" => RefRef,
"reference" => Reference,
"religion" => Religion,
"religion_esoterics" => ReligionEsoterics,
"religion_rel" => ReligionRel,
"religion_self" => ReligionSelf,
"russian_contemporary" => RussianContemporary,
"russian_fantasy" => RussianFantasy,
"sci_biology" => SciBiology,
"sci_chem" => SciChem,
"sci_culture" => SciCulture,
"sci_history" => SciHistory,
"sci_juris" => SciJuris,
"sci_linguistic" => SciLinguistic,
"sci_math" => SciMath,
"sci_medicine" => SciMedicine,
"sci_philosophy" => SciPhilosophy,
"sci_phys" => SciPhys,
"sci_politics" => SciPolitics,
"sci_religion" => SciReligion,
"sci_tech" => SciTech,
"science" => Science,
"sf" => Sf,
"sf_action" => SfAction,
"sf_cyberpunk" => SfCyberpunk,
"sf_detective" => SfDetective,
"sf_fantasy" => SfFantasy,
"sf_heroic" => SfHeroic,
"sf_history" => SfHistory,
"sf_horror" => SfHorror,
"sf_humor" => SfHumor,
"sf_social" => SfSocial,
"sf_space" => SfSpace,
"short_story" => ShortStory,
"sketch" => Sketch,
"small_business" => SmallBusiness,
"sociology_book" => SociologyBook,
"stock" => Stock,
"thriller" => Thriller,
"upbringing_book" => UpbringingBook,
"vampire_book" => VampireBook,
"visual_arts" => VisualArts,
"unrecognised" => Unrecognised,
_ => return None,
})
}
}