Skip to main content

pedant_types/resolution/
error.rs

1//! Every refusal the resolution report contract produces.
2//!
3//! One error type covers both writer boundaries — the builder and custom
4//! deserialization — because both reach the same validator, and a consumer
5//! comparing a builder refusal with a wire refusal should compare one value.
6
7use std::fmt;
8
9use thiserror::Error;
10
11use crate::Language;
12
13use super::ResolutionGap;
14
15/// Which report collection a structural rule names.
16#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
17pub enum ReportCollection {
18    /// The report's resolution units.
19    Units,
20    /// The report's symbol definitions.
21    Definitions,
22    /// The report's symbol references.
23    References,
24    /// The report's resolution records.
25    Resolutions,
26}
27
28impl fmt::Display for ReportCollection {
29    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
30        formatter.write_str(match self {
31            Self::Units => "units",
32            Self::Definitions => "definitions",
33            Self::References => "references",
34            Self::Resolutions => "resolutions",
35        })
36    }
37}
38
39/// A rejected resolution report, or a rejected write into one.
40#[derive(Clone, Debug, Error, PartialEq, Eq)]
41pub enum ResolutionReportError {
42    /// A unit handle another builder issued.
43    #[error("the unit handle belongs to another builder")]
44    ForeignUnitHandle,
45    /// A definition handle another builder issued.
46    #[error("the definition handle belongs to another builder")]
47    ForeignDefinitionHandle,
48    /// A reference handle another builder issued.
49    #[error("the reference handle belongs to another builder")]
50    ForeignReferenceHandle,
51    /// The configured or fixed-width unit capacity is reached.
52    #[error("the report already holds its limit of {limit} units")]
53    UnitCapacityExceeded {
54        /// The capacity that refused the insertion.
55        limit: u32,
56    },
57    /// The configured or fixed-width definition capacity is reached.
58    #[error("the report already holds its limit of {limit} definitions")]
59    DefinitionCapacityExceeded {
60        /// The capacity that refused the insertion.
61        limit: u32,
62    },
63    /// The configured or fixed-width reference capacity is reached.
64    #[error("the report already holds its limit of {limit} references")]
65    ReferenceCapacityExceeded {
66        /// The capacity that refused the insertion.
67        limit: u32,
68    },
69    /// The configured or fixed-width resolution-record capacity is reached.
70    ///
71    /// A document may state more records than it states references, so this
72    /// ceiling is reached by a decoded report rather than by a writer.
73    #[error("the report already holds its limit of {limit} resolution records")]
74    ResolutionCapacityExceeded {
75        /// The capacity that refused the record.
76        limit: u32,
77    },
78    /// More than one record names one reference.
79    #[error("reference {reference} already carries a resolution record")]
80    DuplicateResolution {
81        /// The reference named twice.
82        reference: u32,
83    },
84    /// A definition or reference names a unit the report does not contain.
85    #[error("unit {unit} is not in the report")]
86    UnknownUnit {
87        /// The absent unit identifier.
88        unit: u32,
89    },
90    /// A parent, enclosing definition, or candidate names an absent definition.
91    #[error("definition {definition} is not in the report")]
92    UnknownDefinition {
93        /// The absent definition identifier.
94        definition: u32,
95    },
96    /// A record names a reference the report does not contain.
97    #[error("reference {reference} is not in the report")]
98    UnknownReference {
99        /// The absent reference identifier.
100        reference: u32,
101    },
102    /// An identifier does not equal its own sorted slice position.
103    #[error("{collection} position {position} carries identifier {id}")]
104    NonDenseId {
105        /// The collection holding the entry.
106        collection: ReportCollection,
107        /// The entry's position in the collection.
108        position: u32,
109        /// The identifier the entry carried.
110        id: u32,
111    },
112    /// A collection is not in its stable structural order.
113    #[error("{collection} position {position} breaks the structural order")]
114    UnsortedEntries {
115        /// The collection holding the entry.
116        collection: ReportCollection,
117        /// The position that follows a greater predecessor.
118        position: u32,
119    },
120    /// Two units share one stable key.
121    #[error("two units share the key `{key}`")]
122    DuplicateUnitKey {
123        /// The repeated key.
124        key: Box<str>,
125    },
126    /// A definition or reference contradicts its unit's language.
127    ///
128    /// The offender is named by its own coordinates, so a bad definition and a
129    /// bad reference at two positions never produce one value.
130    #[error("{collection} position {position} claims {claimed:?} in {unit_language:?} unit {unit}")]
131    UnitLanguageMismatch {
132        /// The collection holding the offending record.
133        collection: ReportCollection,
134        /// The offender's position in that collection.
135        position: u32,
136        /// The unit whose language was contradicted.
137        unit: u32,
138        /// The language the record claimed.
139        claimed: Language,
140        /// The language the unit states.
141        unit_language: Language,
142    },
143    /// A parent definition belongs to another unit.
144    #[error("definition {definition} has parent {parent} from another unit")]
145    ForeignParentDefinition {
146        /// The child definition.
147        definition: u32,
148        /// The parent in the other unit.
149        parent: u32,
150    },
151    /// An enclosing definition belongs to another unit.
152    #[error("reference {reference} is enclosed by definition {enclosing} from another unit")]
153    ForeignEnclosingDefinition {
154        /// The reference.
155        reference: u32,
156        /// The enclosing definition in the other unit.
157        enclosing: u32,
158    },
159    /// The definition-parent relation contains a cycle.
160    #[error("definition {definition} is its own ancestor")]
161    DefinitionParentCycle {
162        /// A definition on the cycle.
163        definition: u32,
164    },
165    /// A reference carries no resolution record.
166    #[error("reference {reference} carries no resolution record")]
167    MissingResolution {
168        /// The unrecorded reference.
169        reference: u32,
170    },
171    /// One record names one definition twice.
172    #[error("reference {reference} names candidate definition {definition} twice")]
173    DuplicateCandidate {
174        /// The record's reference.
175        reference: u32,
176        /// The repeated candidate definition.
177        definition: u32,
178    },
179    /// A record's candidates are out of order.
180    #[error("reference {reference} carries candidates out of order at position {position}")]
181    UnsortedCandidates {
182        /// The record's reference.
183        reference: u32,
184        /// The position that follows a greater predecessor.
185        position: u32,
186    },
187    /// One record names one gap twice.
188    #[error("reference {reference} names the gap {gap:?} twice")]
189    DuplicateGap {
190        /// The record's reference.
191        reference: u32,
192        /// The repeated gap.
193        gap: ResolutionGap,
194    },
195    /// A record's gaps are out of order.
196    #[error("reference {reference} carries gaps out of order at position {position}")]
197    UnsortedGaps {
198        /// The record's reference.
199        reference: u32,
200        /// The position that follows a greater predecessor.
201        position: u32,
202    },
203    /// A record mixes resolved and possible candidates.
204    #[error("reference {reference} mixes resolved and possible candidates")]
205    MixedCandidateCertainty {
206        /// The record's reference.
207        reference: u32,
208    },
209    /// A resolved record does not name exactly one definition.
210    #[error("reference {reference} is resolved to {candidates} candidates")]
211    ResolvedCandidateCount {
212        /// The record's reference.
213        reference: u32,
214        /// How many candidates the record carried.
215        candidates: u32,
216    },
217    /// A resolved record carries a gap.
218    #[error("reference {reference} is resolved and still carries a gap")]
219    ResolvedWithGaps {
220        /// The record's reference.
221        reference: u32,
222    },
223    /// A candidate-free record carries no gap.
224    #[error("reference {reference} has neither a candidate nor a gap")]
225    EmptyResolution {
226        /// The record's reference.
227        reference: u32,
228    },
229    /// A span names a path that is not normalized repository-relative.
230    #[error("`{path}` is not a normalized repository-relative path")]
231    InvalidSourcePath {
232        /// The rejected path.
233        path: Box<str>,
234    },
235    /// A span ends before it starts.
236    #[error("a span in `{path}` ends before it starts")]
237    ReversedSiteSpan {
238        /// The span's path.
239        path: Box<str>,
240    },
241    /// A span covers no source.
242    #[error("a span in `{path}` is zero width")]
243    EmptySiteSpan {
244        /// The span's path.
245        path: Box<str>,
246    },
247}