use std::str::FromStr;
use strum::{Display, EnumString};
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Eq, PartialEq, Display, EnumString)]
#[allow(missing_docs)]
#[strum(serialize_all = "lowercase")]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub enum EntryType {
Article,
Book,
Booklet,
InBook,
InCollection,
InProceedings,
Manual,
MastersThesis,
PhdThesis,
Misc,
Proceedings,
TechReport,
Unpublished,
MvBook,
BookInBook,
SuppBook,
Periodical,
SuppPeriodical,
Collection,
MvCollection,
SuppCollection,
Reference,
MvReference,
InReference,
MvProceedings,
Report,
Patent,
Thesis,
Online,
Software,
Dataset,
Set,
XData,
Unknown(String),
}
#[derive(Clone, Debug)]
pub enum AuthorMode {
NoneRequired,
OneRequired,
BothRequired,
AuthorRequired,
AuthorRequiredEditorOptional,
EditorRequiredAuthorForbidden,
}
impl Default for AuthorMode {
fn default() -> Self {
Self::AuthorRequired
}
}
impl AuthorMode {
pub(crate) fn possible(&self) -> &'static [&'static str] {
match self {
Self::OneRequired
| Self::BothRequired
| Self::AuthorRequiredEditorOptional => &["author", "editor"],
Self::AuthorRequired => &["author"],
Self::EditorRequiredAuthorForbidden => &["editor"],
_ => &[],
}
}
}
#[derive(Clone, Debug)]
pub enum PagesChapterMode {
None,
OneRequired,
BothOptional,
BothForbidden,
PagesOptional,
#[allow(dead_code)]
PagesRequired,
}
impl Default for PagesChapterMode {
fn default() -> Self {
Self::None
}
}
impl PagesChapterMode {
pub(crate) fn possible(&self) -> &'static [&'static str] {
match self {
Self::OneRequired | Self::BothOptional => &["pages", "chapter"],
Self::PagesOptional | Self::PagesRequired => &["pages"],
_ => &[],
}
}
}
#[derive(Debug, Default, Clone)]
pub struct Requirements {
pub required: Vec<&'static str>,
pub optional: Vec<&'static str>,
pub forbidden: Vec<&'static str>,
pub author_eds_field: AuthorMode,
pub page_chapter_field: PagesChapterMode,
pub needs_date: bool,
}
impl EntryType {
pub fn new(name: &str) -> Self {
let name = name.to_lowercase();
if let Ok(ty) = EntryType::from_str(&name) {
return ty;
}
match name.as_str() {
"conference" => EntryType::InProceedings,
"electronic" => EntryType::Online,
"www" => EntryType::Online,
_ => EntryType::Unknown(name),
}
}
pub fn is_multi_volume(&self) -> bool {
matches!(
self,
Self::MvBook | Self::MvCollection | Self::MvReference | Self::MvProceedings
)
}
pub fn is_collection(&self) -> bool {
matches!(
self,
Self::Book
| Self::Collection
| Self::Periodical
| Self::Reference
| Self::Proceedings
)
}
pub fn to_biblatex(&self) -> Self {
match self {
Self::MastersThesis => Self::Thesis,
Self::PhdThesis => Self::Thesis,
Self::TechReport => Self::Report,
Self::Unknown(_) => Self::Misc,
_ => self.clone(),
}
}
pub fn to_bibtex(&self) -> Self {
match self {
Self::MvBook => Self::Book,
Self::BookInBook => Self::InBook,
Self::SuppBook => Self::InBook,
Self::Periodical => Self::Misc,
Self::SuppPeriodical => Self::Article,
Self::Collection => Self::Proceedings,
Self::MvCollection => Self::Proceedings,
Self::SuppCollection => Self::InCollection,
Self::Reference => Self::Misc,
Self::MvReference => Self::Misc,
Self::InReference => Self::InCollection,
Self::MvProceedings => Self::Proceedings,
Self::Report => Self::TechReport,
Self::Patent => Self::Misc,
Self::Thesis => Self::PhdThesis,
Self::Online => Self::Misc,
Self::Software => Self::Misc,
Self::Dataset => Self::Misc,
Self::Set => Self::Misc,
Self::XData => Self::Misc,
Self::Unknown(_) => Self::Misc,
_ => self.clone(),
}
}
pub(crate) fn requirements(&self) -> Requirements {
let mut reqs = Requirements { needs_date: true, ..Default::default() };
reqs.required.push("title");
reqs.optional.push("note");
reqs.optional.push("location");
reqs.optional.push("titleadddon");
reqs.optional.push("subtitle");
reqs.optional.push("url");
reqs.optional.push("urldate");
reqs.optional.push("doi");
reqs.optional.push("eprint");
reqs.optional.push("eprintclass");
reqs.optional.push("eprinttype");
reqs.optional.push("pubstate");
reqs.optional.push("language");
reqs.optional.push("addendum");
if self.is_multi_volume() {
reqs.forbidden.push("maintitle");
reqs.forbidden.push("mainsubtitle");
reqs.forbidden.push("maintitleaddon");
reqs.forbidden.push("part");
reqs.forbidden.push("volume");
}
match self {
Self::Article => {
reqs.required.push("journaltitle");
reqs.optional.remove(1);
reqs.optional.push("number");
reqs.optional.push("series");
reqs.optional.push("version");
reqs.optional.push("volume");
reqs.optional.push("annotator");
reqs.optional.push("commentator");
reqs.optional.push("translator");
reqs.optional.push("origlanguage");
reqs.optional.push("journalsubtitle");
reqs.optional.push("issue");
reqs.optional.push("issuetitle");
reqs.optional.push("issuesubtitle");
reqs.optional.push("eid");
reqs.optional.push("issn");
reqs.page_chapter_field = PagesChapterMode::PagesOptional;
reqs.author_eds_field = AuthorMode::AuthorRequiredEditorOptional;
}
Self::Book => {
reqs.required.push("publisher");
reqs.optional.push("edition");
reqs.optional.push("number");
reqs.optional.push("series");
reqs.optional.push("part");
reqs.optional.push("volume");
reqs.optional.push("volumes");
reqs.optional.push("annotator");
reqs.optional.push("commentator");
reqs.optional.push("translator");
reqs.optional.push("origlanguage");
reqs.optional.push("afterword");
reqs.optional.push("foreword");
reqs.optional.push("introduction");
reqs.optional.push("maintitle");
reqs.optional.push("mainsubtitle");
reqs.optional.push("maintitleaddon");
reqs.optional.push("isbn");
reqs.optional.push("pagetotal");
reqs.author_eds_field = AuthorMode::OneRequired;
reqs.page_chapter_field = PagesChapterMode::BothOptional;
}
Self::Booklet => {
reqs.optional.push("howpublished");
reqs.optional.push("type");
reqs.optional.push("pagetotal");
reqs.author_eds_field = AuthorMode::OneRequired;
reqs.page_chapter_field = PagesChapterMode::BothOptional;
reqs.needs_date = false;
}
Self::InBook => {
reqs.required.push("publisher");
reqs.required.push("booktitle");
reqs.optional.push("bookauthor");
reqs.optional.push("volume");
reqs.optional.push("volumes");
reqs.optional.push("part");
reqs.optional.push("type");
reqs.optional.push("series");
reqs.optional.push("number");
reqs.optional.push("edition");
reqs.optional.push("annotator");
reqs.optional.push("commentator");
reqs.optional.push("translator");
reqs.optional.push("origlanguage");
reqs.optional.push("afterword");
reqs.optional.push("foreword");
reqs.optional.push("introduction");
reqs.optional.push("maintitle");
reqs.optional.push("mainsubtitle");
reqs.optional.push("maintitleaddon");
reqs.optional.push("booksubtitle");
reqs.optional.push("booktitleaddon");
reqs.optional.push("isbn");
reqs.forbidden.push("pagetotal");
reqs.author_eds_field = AuthorMode::OneRequired;
reqs.page_chapter_field = PagesChapterMode::OneRequired;
}
Self::InCollection => {
reqs.required.push("publisher");
reqs.required.push("booktitle");
reqs.optional.push("volume");
reqs.optional.push("type");
reqs.optional.push("series");
reqs.optional.push("number");
reqs.optional.push("edition");
reqs.optional.push("annotator");
reqs.optional.push("commentator");
reqs.optional.push("translator");
reqs.optional.push("origlanguage");
reqs.optional.push("afterword");
reqs.optional.push("foreword");
reqs.optional.push("introduction");
reqs.optional.push("maintitle");
reqs.optional.push("mainsubtitle");
reqs.optional.push("maintitleaddon");
reqs.optional.push("booksubtitle");
reqs.optional.push("booktitleaddon");
reqs.optional.push("part");
reqs.optional.push("volumes");
reqs.optional.push("isbn");
reqs.forbidden.push("pagetotal");
reqs.author_eds_field = AuthorMode::BothRequired;
reqs.page_chapter_field = PagesChapterMode::BothOptional;
}
Self::InProceedings => {
reqs.required.push("booktitle");
reqs.optional.push("number");
reqs.optional.push("organization");
reqs.optional.push("series");
reqs.optional.push("volume");
reqs.optional.push("volumes");
reqs.optional.push("part");
reqs.optional.push("publisher");
reqs.optional.push("maintitle");
reqs.optional.push("mainsubtitle");
reqs.optional.push("maintitleaddon");
reqs.optional.push("booksubtitle");
reqs.optional.push("booktitleaddon");
reqs.optional.push("eventtitle");
reqs.optional.push("eventsubtitle");
reqs.optional.push("eventtitleaddon");
reqs.optional.push("venue");
reqs.optional.push("isbn");
reqs.optional.push("publisher");
reqs.forbidden.push("pagetotal");
reqs.page_chapter_field = PagesChapterMode::BothOptional;
reqs.author_eds_field = AuthorMode::AuthorRequiredEditorOptional;
}
Self::Manual => {
reqs.optional.push("edition");
reqs.optional.push("organization");
reqs.optional.push("series");
reqs.optional.push("version");
reqs.optional.push("isbn");
reqs.optional.push("publisher");
reqs.optional.push("type");
reqs.optional.push("pagetotal");
reqs.author_eds_field = AuthorMode::OneRequired;
reqs.page_chapter_field = PagesChapterMode::BothOptional;
reqs.needs_date = false;
}
Self::MastersThesis => {
reqs.required.push("school");
reqs.optional.push("type");
reqs.author_eds_field = AuthorMode::AuthorRequired;
}
Self::Misc => {
reqs.optional.remove(1);
reqs.optional.push("howpublished");
reqs.optional.push("organization");
reqs.optional.push("type");
reqs.author_eds_field = AuthorMode::OneRequired;
reqs.needs_date = false;
}
Self::Proceedings => {
reqs.optional.push("number");
reqs.optional.push("organization");
reqs.optional.push("series");
reqs.optional.push("volume");
reqs.optional.push("volumes");
reqs.optional.push("part");
reqs.optional.push("publisher");
reqs.optional.push("maintitle");
reqs.optional.push("mainsubtitle");
reqs.optional.push("maintitleaddon");
reqs.optional.push("isbn");
reqs.optional.push("publisher");
reqs.optional.push("pagetotal");
reqs.author_eds_field = AuthorMode::EditorRequiredAuthorForbidden;
reqs.page_chapter_field = PagesChapterMode::BothOptional;
}
Self::TechReport => {
reqs.required.push("institution");
reqs.optional.push("number");
reqs.optional.push("type");
}
Self::Unpublished => {
reqs.required.push("note");
reqs.optional.remove(1);
reqs.optional.remove(0);
reqs.optional.push("isbn");
reqs.optional.push("howpublished");
reqs.needs_date = false;
}
Self::MvBook => {
reqs.optional.push("annotator");
reqs.optional.push("commentator");
reqs.optional.push("translator");
reqs.optional.push("origlanguage");
reqs.optional.push("afterword");
reqs.optional.push("foreword");
reqs.optional.push("introduction");
reqs.optional.push("edition");
reqs.optional.push("number");
reqs.optional.push("series");
reqs.optional.push("volumes");
reqs.optional.push("isbn");
reqs.optional.push("publisher");
reqs.optional.push("pagetotal");
reqs.page_chapter_field = PagesChapterMode::BothOptional;
reqs.author_eds_field = AuthorMode::AuthorRequiredEditorOptional;
}
Self::Periodical => {
reqs.optional.push("issue");
reqs.optional.push("issuetitle");
reqs.optional.push("issuesubtitle");
reqs.optional.push("number");
reqs.optional.push("series");
reqs.optional.push("volume");
reqs.optional.push("issn");
reqs.author_eds_field = AuthorMode::EditorRequiredAuthorForbidden;
}
Self::Collection => {
reqs.optional.push("annotator");
reqs.optional.push("commentator");
reqs.optional.push("translator");
reqs.optional.push("origlanguage");
reqs.optional.push("afterword");
reqs.optional.push("foreword");
reqs.optional.push("introduction");
reqs.optional.push("maintitle");
reqs.optional.push("mainsubtitle");
reqs.optional.push("maintitleaddon");
reqs.optional.push("edition");
reqs.optional.push("number");
reqs.optional.push("series");
reqs.optional.push("part");
reqs.optional.push("volume");
reqs.optional.push("volumes");
reqs.optional.push("isbn");
reqs.optional.push("publisher");
reqs.optional.push("pagetotal");
reqs.author_eds_field = AuthorMode::EditorRequiredAuthorForbidden;
reqs.page_chapter_field = PagesChapterMode::BothOptional;
}
Self::MvCollection => {
reqs.optional.push("annotator");
reqs.optional.push("commentator");
reqs.optional.push("translator");
reqs.optional.push("origlanguage");
reqs.optional.push("afterword");
reqs.optional.push("foreword");
reqs.optional.push("introduction");
reqs.optional.push("edition");
reqs.optional.push("number");
reqs.optional.push("series");
reqs.optional.push("volumes");
reqs.optional.push("isbn");
reqs.optional.push("publisher");
reqs.optional.push("pagetotal");
reqs.author_eds_field = AuthorMode::EditorRequiredAuthorForbidden;
reqs.page_chapter_field = PagesChapterMode::BothForbidden;
}
Self::MvProceedings => {
reqs.optional.push("number");
reqs.optional.push("series");
reqs.optional.push("volumes");
reqs.optional.push("publisher");
reqs.optional.push("organization");
reqs.optional.push("pagetotal");
reqs.author_eds_field = AuthorMode::EditorRequiredAuthorForbidden;
reqs.page_chapter_field = PagesChapterMode::BothForbidden;
}
Self::Report => {
reqs.required.push("institution");
reqs.required.push("type");
reqs.optional.push("number");
reqs.optional.push("version");
reqs.optional.push("isrn");
reqs.optional.push("pagetotal");
reqs.page_chapter_field = PagesChapterMode::BothOptional;
}
Self::Patent => {
reqs.required.push("number");
reqs.optional.push("holder");
reqs.optional.push("type");
}
Self::Thesis => {
reqs.optional.push("isbn");
reqs.required.push("institution");
reqs.required.push("type");
reqs.optional.push("pagetotal");
reqs.page_chapter_field = PagesChapterMode::BothOptional;
}
Self::Online => {
reqs.required.push("url");
reqs.optional.remove(9);
reqs.optional.remove(8);
reqs.optional.remove(7);
reqs.optional.remove(6);
reqs.optional.remove(4);
reqs.optional.remove(1);
reqs.optional.push("organization");
reqs.author_eds_field = AuthorMode::OneRequired;
}
Self::Dataset => {
reqs.optional.push("edition");
reqs.optional.push("type");
reqs.optional.push("series");
reqs.optional.push("number");
reqs.optional.push("version");
reqs.optional.push("organization");
reqs.optional.push("publisher");
reqs.author_eds_field = AuthorMode::OneRequired;
}
Self::PhdThesis => {
reqs = Self::MastersThesis.requirements();
}
Self::SuppPeriodical => {
reqs = Self::Article.requirements();
}
Self::BookInBook => {
reqs = Self::InBook.requirements();
}
Self::SuppBook => {
reqs = Self::InBook.requirements();
}
Self::SuppCollection => {
reqs = Self::InCollection.requirements();
}
Self::Reference => {
reqs = Self::Collection.requirements();
}
Self::MvReference => {
reqs = Self::MvCollection.requirements();
}
Self::InReference => {
reqs = Self::InCollection.requirements();
}
Self::Software => {
reqs = Self::Misc.requirements();
}
Self::Set => {
reqs.optional.clear();
reqs.required = vec!["entryset"];
reqs.author_eds_field = AuthorMode::NoneRequired;
reqs.needs_date = false;
}
Self::XData => {
reqs.optional.clear();
reqs.required.clear();
reqs.author_eds_field = AuthorMode::NoneRequired;
reqs.needs_date = false;
}
Self::Unknown(_) => {
reqs = Self::MvCollection.requirements();
}
}
reqs
}
}
pub fn is_verbatim_field(key: &str) -> bool {
matches!(
key,
"file"
| "doi"
| "uri"
| "eprint"
| "verba"
| "verbb"
| "verbc"
| "pdf"
| "url"
| "urlraw"
)
}