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
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
/*
SPDX-License-Identifier: MIT OR Apache-2.0
SPDX-FileCopyrightText: © 2023-2026 Bruce D'Arcus and Citum contributors
*/
//! Per-render-run mutable state for [`Processor`](super::Processor).
//!
//! See `docs/specs/EXPLICIT_RENDER_RUN_STATE.md` for the full design.
//!
//! `RunState` owns the citation-order-dependent state that used to live as
//! `RefCell` fields directly on `Processor`: citation numbers, the cited-ID
//! set, dynamic (cite-time) compound-group membership, and first-note
//! tracking. It is created fresh via [`Processor::begin_run`](super::Processor::begin_run),
//! populated in citation-processing order by registration methods that take
//! `&mut RunState`, and then finalized into a [`FinalizedRun`] so that
//! bibliography rendering — which takes `&FinalizedRun` — cannot be called
//! before registration is complete. That ordering contract is enforced by
//! the type system: there is no way to construct a `FinalizedRun` other than
//! through [`RunState::finalize`]. Citation rendering itself stays
//! `&mut RunState`-threaded rather than moving to `&FinalizedRun`:
//! registration and rendering are interleaved per citation (see
//! `citation.rs`'s module docs), so a citation can only be rendered as part
//! of the same in-progress run that is registering it.
//!
//! Two fields, `citation_numbers` and `first_note_by_id`, stay behind a
//! `RwLock` even inside `RunState`/`FinalizedRun`: the render layer
//! (`Renderer::get_or_assign_citation_number`) lazily assigns a citation
//! number the first time a reference is rendered, which is a monotonic,
//! assign-once operation, not a read. This does not weaken the ordering
//! contract this type adds — it only means "render before registration is
//! complete" is a compile error, not that rendering can never touch interior
//! state. `RwLock` (rather than `RefCell`) is required so that `FinalizedRun`
//! is `Sync` and bibliography entries can render across threads (see
//! `docs/specs/PARALLEL_BIBLIOGRAPHY_RENDERING.md`); lock poisoning is
//! recovered from rather than propagated, since a panicking reader/writer
//! does not invalidate the numbering data already in the map.
use IndexMap;
use ;
use RwLock;
/// Mutable per-render-run state: citation numbering, cite-order tracking,
/// and dynamic (cite-time) compound-group membership.
///
/// Create with [`Processor::begin_run`](super::Processor::begin_run);
/// populate via registration methods (`&self, &mut RunState`); consume via
/// [`finalize`](RunState::finalize) before rendering.
///
/// `Clone` is provided for long-lived callers (e.g. the FFI session handle)
/// that need to render a bibliography from a snapshot of the current state
/// without pausing ongoing citation registration on the original `RunState`.
/// Implemented by hand (rather than derived) because `RwLock<T>` is not
/// `Clone` even when `T` is; the impl below clones the locked contents into
/// fresh locks instead.
/// A [`RunState`] that has completed the registration phase.
///
/// Rendering methods that depend on cite order or citation numbers (e.g.
/// bibliography rendering, citation-collapse across a document) take
/// `&FinalizedRun` rather than `&RunState`, so calling them before
/// registration is complete is a compile error.
RunState);