1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
|
use std::str::FromStr;
use rustc_hash::FxHashMap;
use strum::EnumString;
use crate::syntax::bibtex::{Entry, Field, HasName, HasType, HasValue, Value};
use super::field::{
author::{AuthorField, AuthorFieldData},
date::{DateField, DateFieldData},
number::{NumberField, NumberFieldData},
text::{TextField, TextFieldData},
};
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Hash, EnumString)]
#[strum(ascii_case_insensitive)]
pub enum EntryKind {
Article,
Book,
MVBook,
InBook,
BookInBook,
SuppBook,
Booklet,
Collection,
MVCollection,
InCollection,
SuppCollection,
DataSet,
Manual,
Misc,
Online,
Electronic,
Www,
Patent,
Periodical,
SuppPeriodical,
Proceedings,
MVProceedings,
InProceedings,
Conference,
Reference,
MVReference,
InReference,
Report,
Set,
Software,
Thesis,
MasterThesis,
PhdThesis,
TechReport,
Unknown,
}
impl Default for EntryKind {
fn default() -> Self {
Self::Unknown
}
}
#[derive(Debug, Clone, Default)]
pub struct EntryData {
pub kind: EntryKind,
pub text: FxHashMap<TextField, TextFieldData>,
pub author: FxHashMap<AuthorField, AuthorFieldData>,
pub date: FxHashMap<DateField, DateFieldData>,
pub number: FxHashMap<NumberField, NumberFieldData>,
}
impl From<&Entry> for EntryData {
fn from(entry: &Entry) -> Self {
let mut data = EntryData {
kind: entry
.type_token()
.and_then(|token| EntryKind::from_str(&token.text()[1..]).ok())
.unwrap_or(EntryKind::Unknown),
..EntryData::default()
};
for field in entry.fields() {
let _ = data.parse_field(&field);
}
data
}
}
impl EntryData {
fn parse_field(&mut self, field: &Field) -> Option<()> {
let name = field.name_token()?;
let name = name.text();
let value = field.value()?;
self.parse_author_field(name, &value)
.or_else(|| self.parse_date_field(name, &value))
.or_else(|| self.parse_number_field(name, &value))
.or_else(|| self.parse_text_field(name, &value))
}
fn parse_author_field(&mut self, name: &str, value: &Value) -> Option<()> {
let name = AuthorField::parse(name)?;
let data = AuthorFieldData::parse(value)?;
self.author.insert(name, data);
Some(())
}
fn parse_date_field(&mut self, name: &str, value: &Value) -> Option<()> {
let name = DateField::parse(name)?;
let data = DateFieldData::parse(value)?;
self.date.insert(name, data);
Some(())
}
fn parse_number_field(&mut self, name: &str, value: &Value) -> Option<()> {
let name = NumberField::parse(name)?;
let data = NumberFieldData::parse(value)?;
self.number.insert(name, data);
Some(())
}
fn parse_text_field(&mut self, name: &str, value: &Value) -> Option<()> {
let name = TextField::parse(name).unwrap_or(TextField::Unknown);
let data = TextFieldData::parse(value)?;
self.text.insert(name, data);
Some(())
}
}
|