substrate_data/schema/reader/resolve.rs
1//! [`Resolve`]: what a tool makes of the references it reads, and
2//! [`Unresolved`], why one is wrong.
3
4use std::fmt;
5
6use crate::model::value::{Path, Ref, RefKey, Value};
7
8/// What a tool makes of the references it reads: a build checks each one
9/// against what there is (and may rewrite its id), an editor shows them.
10pub trait Resolve {
11 /// A reference at `path`: the id to keep, or why it's wrong.
12 ///
13 /// # Errors
14 ///
15 /// [`Unresolved`] when the reference names nothing there is, or names
16 /// it in a way the tool refuses.
17 fn reference(&mut self, r: &Ref, path: &Path) -> Result<RefKey, Unresolved>;
18
19 /// A reference at `path` the tool replaces by a value — a word of a
20 /// dictionary, a localized text: `Some(value)` is read in its place,
21 /// `None` keeps it a reference. Asked only where a field says it takes
22 /// a value or a reference ([`with::Expand`](crate::with::Expand)); a
23 /// reference met anywhere else goes through [`Resolve::reference`].
24 ///
25 /// # Errors
26 ///
27 /// [`Unresolved`] when the reference names nothing there is, or names
28 /// it in a way the tool refuses.
29 fn expand(&mut self, _r: &Ref, _path: &Path) -> Result<Option<Value>, Unresolved> {
30 Ok(None)
31 }
32}
33
34/// Why a reference doesn't resolve.
35#[derive(Debug, Clone, PartialEq, Eq)]
36pub enum Unresolved {
37 /// There is nothing it names.
38 Missing(Ref),
39 /// It names something, but not in a way this tool takes (a reason for a person).
40 Refused {
41 /// The reference.
42 reference: Ref,
43 /// Why, for a person.
44 reason: String,
45 },
46}
47
48impl fmt::Display for Unresolved {
49 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
50 match self {
51 Unresolved::Missing(r) => write!(f, "`{r}`: there is no such {}", r.kind),
52 Unresolved::Refused { reference, reason } => write!(f, "`{reference}`: {reason}"),
53 }
54 }
55}
56
57impl std::error::Error for Unresolved {}