mos_bib/record.rs
1//! The parsed bibliography data model: [`Bibliography`], [`BibEntry`], and
2//! the document-body [`Citation`] reference.
3
4use std::collections::BTreeMap;
5use std::ops::Range;
6
7/// A parsed bibliography: every [`BibEntry`] keyed by its citation key.
8///
9/// Entries live in a [`BTreeMap`], so iterating them yields a deterministic,
10/// sorted-by-citation-key order that is easy to assert on in tests. Build
11/// one from BibTeX source with [`parse_bibtex`](crate::parse_bibtex). On a
12/// duplicate citation key the last entry in source order wins.
13///
14/// # Examples
15///
16/// ```
17/// use mos_bib::Bibliography;
18///
19/// let empty = Bibliography::default();
20/// assert!(empty.entries.is_empty());
21/// ```
22#[derive(Clone, Debug, Default, PartialEq, Eq)]
23pub struct Bibliography {
24 /// Parsed entries keyed by citation key, in sorted key order.
25 pub entries: BTreeMap<String, BibEntry>,
26}
27
28/// A single parsed BibTeX entry: one `@type{...}` record.
29///
30/// The entry type and field names are normalized to lowercase, because
31/// BibTeX treats them case-insensitively; the citation [`key`](Self::key) is
32/// preserved verbatim, because keys *are* case-sensitive. Fields live in a
33/// [`BTreeMap`], so [`fields`](Self::fields) iterates in sorted, stable
34/// order. Values are stored as raw text exactly as written between the
35/// delimiters; no `TeX` decoding or name parsing.
36///
37/// # Examples
38///
39/// ```
40/// use mos_bib::parse_bibtex;
41///
42/// # fn main() -> Result<(), mos_bib::BibParseError> {
43/// let bib = parse_bibtex("@article{knuth1984, title = {Literate Programming}}")?;
44/// let entry = &bib.entries["knuth1984"];
45/// assert_eq!(entry.entry_type, "article");
46/// assert_eq!(entry.key, "knuth1984");
47/// assert_eq!(entry.fields["title"], "Literate Programming");
48/// # Ok(())
49/// # }
50/// ```
51#[derive(Clone, Debug, PartialEq, Eq)]
52pub struct BibEntry {
53 /// The entry type without the leading `@`, lowercased (e.g. `article`).
54 pub entry_type: String,
55 /// The citation key, preserved verbatim (e.g. `knuth1984`).
56 pub key: String,
57 /// Byte range of [`key`](Self::key) inside the parsed BibTeX source.
58 pub key_span: Range<usize>,
59 /// Field name (lowercased) to raw value text, in sorted name order.
60 pub fields: BTreeMap<String, String>,
61}
62
63/// A citation reference within the document body: a single key that
64/// resolves into a [`Bibliography`] entry at render time.
65///
66/// # Examples
67///
68/// ```
69/// use mos_bib::Citation;
70///
71/// let citation = Citation {
72/// key: "knuth1984".to_owned(),
73/// };
74///
75/// assert_eq!(citation.key, "knuth1984");
76/// ```
77#[derive(Clone, Debug)]
78pub struct Citation {
79 pub key: String,
80}