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
use std::str;
use nom::IError;
use error::ParsingError;
use parser;
#[cfg(features="nightly")]
use std::convert::TryFrom;
#[derive(Debug, PartialEq, Eq)]
pub struct Bibtex<'a> {
entries: Vec<Entry<'a>>,
}
impl<'a> Bibtex<'a> {
pub fn new(entries: Vec<Entry<'a>>) -> Self {
Self { entries }
}
pub fn parse(bibtex: &'a str) -> Result<Self, ParsingError> {
match parser::bibtex(bibtex.as_bytes()).to_full_result() {
Ok(v) => Ok(v),
Err(e) => Err(convert_nom_ierror(e)),
}
}
pub fn entries(&self) -> &Vec<Entry> {
&self.entries
}
}
#[cfg(features="nightly")]
impl<'a> TryFrom<&'a str> for Bibtex {
type Error = ParsingError;
fn try_from(value: &str) -> Result<Self, Self::Error> {
Bibtex::parse(value)
}
}
#[derive(Debug, PartialEq, Eq)]
pub enum Entry<'a> {
Preamble(&'a str),
Comment(&'a str),
Variable(&'a str, &'a str),
Bibliography(BibliographyEntry<'a>),
}
#[derive(Debug, PartialEq, Eq)]
pub struct BibliographyEntry<'a> {
pub entry_type: &'a str,
pub citation_key: &'a str,
tags: Vec<(&'a str, &'a str)>,
}
impl<'a> BibliographyEntry<'a> {
pub fn new(entry_type: &'a str, citation_key: &'a str, tags: Vec<(&'a str, &'a str)>) -> Self {
BibliographyEntry {
entry_type,
citation_key,
tags,
}
}
pub fn tags(&self) -> &Vec<(&str, &str)> {
&self.tags
}
}
#[cfg(features="nightly")]
impl<'a> TryFrom<&'a str> for BibliographyEntry {
type Error = ParsingError;
fn try_from(value: &str) -> Result<Self, Self::Error> {
match parser::bibliography_entry(value.as_bytes()).to_full_result() {
Ok(v) => {
if let Entry::Bibliography(entry) = v {
Ok(entry)
}
unreachable!();
}
Err(e) => Err(handle_nom_ierror),
}
}
}
fn convert_nom_ierror(err: IError) -> ParsingError {
match err {
IError::Incomplete(e) => {
let msg = format!("Incomplete: {:?}", e);
ParsingError::new(&msg)
}
IError::Error(e) => ParsingError::new(e.description()),
}
}