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