substrate_data/schema/reader/
reader.rs1use super::Found;
4use super::keys::is_metadata_key;
5use super::suggest::{closest, found_text};
6use crate::Diagnostic;
7use crate::diagnostic::Problem;
8use crate::model::borrowed::{MapRef, ValueRef};
9use crate::model::value::{Path, Ref, RefKey, Seg};
10use crate::schema::{Expected, Resolve, Schema};
11
12#[derive(Default)]
15pub struct Reader<'r> {
16 pub(crate) path: Vec<Step>,
19 pub(crate) value_only: bool,
21 pub(crate) resolver: Option<&'r mut dyn Resolve>,
23 pub problems: Vec<Diagnostic>,
25 pub refs: Vec<Found<Ref>>,
27 pub(crate) allowed: Vec<&'static str>,
29}
30
31impl std::fmt::Debug for Reader<'_> {
32 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
33 f.debug_struct("Reader")
34 .field("path", &self.path())
35 .field("value_only", &self.value_only)
36 .field("resolves", &self.resolver.is_some())
37 .field("problems", &self.problems)
38 .field("refs", &self.refs)
39 .finish_non_exhaustive()
40 }
41}
42
43pub(crate) enum Step {
45 Seg(Seg),
46 Field(&'static str),
47}
48
49impl<'r> Reader<'r> {
50 #[must_use]
52 pub fn new() -> Self {
53 Self::default()
54 }
55
56 pub fn with_resolver(resolver: &'r mut dyn Resolve) -> Self {
58 Self {
59 resolver: Some(resolver),
60 ..Self::default()
61 }
62 }
63
64 pub fn resolve_ref(&mut self, r: &Ref) -> Option<RefKey> {
66 let result = match &mut self.resolver {
67 Some(res) => res.reference(r, &Self::built(&self.path)),
68 None => Ok(r.id.clone()),
69 };
70 result
71 .map_err(|e| self.problem_of(Problem::Unresolved, e.to_string()))
72 .ok()
73 }
74
75 pub fn take_ref(&mut self, r: Ref) -> Option<RefKey> {
77 if self.resolver.is_none() {
78 return Some(r.id);
79 }
80 self.resolve_ref(&r)
81 }
82
83 #[must_use]
85 pub fn keeps_found(&self) -> bool {
86 !self.value_only
87 }
88
89 #[must_use]
91 pub fn resolves(&self) -> bool {
92 self.resolver.is_some()
93 }
94
95 #[must_use]
97 pub fn path(&self) -> Path {
98 Self::built(&self.path)
99 }
100
101 fn built(steps: &[Step]) -> Path {
102 let mut p = Path::root();
103 for s in steps {
104 p.push(match s {
105 Step::Seg(s) => s.clone(),
106 Step::Field(k) => Seg::Key((*k).to_string()),
107 });
108 }
109 p
110 }
111
112 pub fn problem(&mut self, message: impl Into<String>) {
114 self.problem_of(Problem::Invalid, message);
115 }
116
117 pub fn problem_of(&mut self, problem: Problem, message: impl Into<String>) {
119 let found = Diagnostic::error(problem, message.into()).at_path(self.path());
120 self.problems.push(found);
121 }
122
123 pub fn expected(&mut self, what: Expected, found: &ValueRef<'_>) {
125 self.problem_of(
126 Problem::Expected,
127 format!("expected {what}, found {}", found_text(found)),
128 );
129 }
130
131 pub fn at<T>(&mut self, seg: Seg, f: impl FnOnce(&mut Self) -> T) -> T {
133 self.path.push(Step::Seg(seg));
134 let r = f(self);
135 self.path.pop();
136 r
137 }
138
139 fn in_field<T>(&mut self, key: &'static str, f: impl FnOnce(&mut Self) -> T) -> T {
141 self.path.push(Step::Field(key));
142 let r = f(self);
143 self.path.pop();
144 r
145 }
146
147 pub fn note_ref(&mut self, r: Ref) {
149 if self.value_only {
150 return;
151 }
152 let path = self.path();
153 self.refs.push(Found { value: r, path });
154 }
155
156 pub fn map<'v>(&mut self, v: &ValueRef<'v>) -> Option<MapRef<'v>> {
158 match v {
159 ValueRef::Map(m) => Some(*m),
160 other => {
161 self.expected(Expected::Object, other);
162 None
163 }
164 }
165 }
166
167 pub fn unknown_keys(&mut self, map: MapRef<'_>, known: &[&str]) {
169 for key in map.keys() {
170 if known.contains(&key) || is_metadata_key(key) || self.allowed.contains(&key) {
171 continue;
172 }
173 let hint = closest(key, known).map_or_else(
174 || {
175 if known.is_empty() {
176 String::new()
177 } else {
178 format!(
179 " (expected {})",
180 known
181 .iter()
182 .map(|k| format!("`{k}`"))
183 .collect::<Vec<_>>()
184 .join(", ")
185 )
186 }
187 },
188 |k| format!(" — did you mean `{k}`?"),
189 );
190 let mut found = Diagnostic::error(
191 Problem::UnknownField,
192 format!("unknown field `{key}`{hint}"),
193 )
194 .at_path(self.path().key(key));
195 found.on_key = true;
196 self.problems.push(found);
197 }
198 }
199
200 pub fn unknown_name(&mut self, name: &str, known: &[&str]) {
202 let hint = match closest(name, known) {
203 Some(k) => format!(" — did you mean `{k}`?"),
204 None => format!(
205 " (expected {})",
206 known
207 .iter()
208 .map(|k| format!("`{k}`"))
209 .collect::<Vec<_>>()
210 .join(", ")
211 ),
212 };
213 self.problem(format!("unknown `{name}`{hint}"));
214 }
215
216 pub fn field<T: Schema>(&mut self, map: MapRef<'_>, key: &'static str) -> Option<T> {
218 match map.get(key) {
219 Some(v) => self.at(Seg::Key(key.to_string()), |cx| T::read(v, cx)),
220 None => T::absent().or_else(|| {
221 self.problem_of(Problem::MissingField, format!("missing `{key}`"));
222 None
223 }),
224 }
225 }
226
227 pub fn field_or<T: Schema>(
229 &mut self,
230 map: MapRef<'_>,
231 key: &'static str,
232 default: impl FnOnce() -> T,
233 ) -> Option<T> {
234 match map.get(key) {
235 Some(v) => self.at(Seg::Key(key.to_string()), |cx| T::read(v, cx)),
236 None => Some(default()),
237 }
238 }
239
240 pub fn field_with<W: crate::with::With<F>, F>(
242 &mut self,
243 map: MapRef<'_>,
244 key: &'static str,
245 ) -> Option<F> {
246 match map.get(key) {
247 Some(v) => self.in_field(key, |cx| W::read(v, cx)),
248 None => W::absent().or_else(|| {
249 self.problem_of(Problem::MissingField, format!("missing `{key}`"));
250 None
251 }),
252 }
253 }
254
255 pub fn field_or_with<W: crate::with::With<F>, F>(
257 &mut self,
258 map: MapRef<'_>,
259 key: &'static str,
260 default: impl FnOnce() -> F,
261 ) -> Option<F> {
262 match map.get(key) {
263 Some(v) => self.in_field(key, |cx| W::read(v, cx)),
264 None => Some(default()),
265 }
266 }
267
268 pub fn with_allowed<T>(&mut self, key: &'static str, f: impl FnOnce(&mut Self) -> T) -> T {
270 self.allowed.push(key);
271 let r = f(self);
272 self.allowed.pop();
273 r
274 }
275
276 pub fn with_allowed_all<T>(
279 &mut self,
280 keys: &[&'static str],
281 f: impl FnOnce(&mut Self) -> T,
282 ) -> T {
283 let before = self.allowed.len();
284 self.allowed.extend_from_slice(keys);
285 let r = f(self);
286 self.allowed.truncate(before);
287 r
288 }
289
290 pub fn own_keys<T>(&mut self, f: impl FnOnce(&mut Self) -> T) -> T {
292 let saved = std::mem::take(&mut self.allowed);
293 let r = f(self);
294 self.allowed = saved;
295 r
296 }
297}