pub struct ValidationPath { /* private fields */ }Expand description
A structured path to a value being validated.
Debug and Display do not reveal field labels. Call Self::render
explicitly only in a trusted presentation layer; even rendered map entries
contain opaque positions rather than raw map keys.
Field labels are static program declarations. Runtime map keys must be represented by opaque map-entry segments.
§Examples
use qubit_validator::ValidationPath;
let path = ValidationPath::root().with_field("profile").with_index(2);
assert_eq!(path.render(), "profile[2]");
assert_eq!(path.as_segments().len(), 2);Runtime field names cannot be retained in a path. Represent dynamic map
entries with Self::with_map_entry instead.
use qubit_validator::ValidationPath;
let runtime_name = String::from("user supplied key");
let _ = ValidationPath::root().with_field(&runtime_name);Implementations§
Source§impl ValidationPath
impl ValidationPath
Sourcepub const fn root() -> Self
pub const fn root() -> Self
Creates an empty root path.
§Returns
A path with no segments. Rendering this path produces an empty string.
Examples found in repository?
168fn main() {
169 let b0 = V0.bind(ValidatorId::new("bench.zero"), 0, &[]).unwrap();
170 let b1 = V1.bind(ValidatorId::new("bench.one"), 0, &[]).unwrap();
171 let b4 = V4.bind(ValidatorId::new("bench.four"), 0, &[]).unwrap();
172 let b8 = V8.bind(ValidatorId::new("bench.eight"), 0, &[]).unwrap();
173 let b9 = V9.bind(ValidatorId::new("bench.nine"), 0, &[]).unwrap();
174 let number = 7_u64;
175 let value = ValidationValue::Typed(&number);
176 let path = ValidationPath::root().with_field("sample");
177 let tail_path = ValidationPath::root().with_field("tail");
178
179 let empty_named: [NamedValidationDependency<'_>; 0] = [];
180 let empty_values: [ValidationValue<'_>; 0] = [];
181 run_case("zero", &b0, &empty_named, &BoundValidationContext::new(&empty_values));
182
183 let one_named = [NamedValidationDependency::new("a", value)];
184 let one_values = [value];
185 run_case("one_plain", &b1, &one_named, &BoundValidationContext::new(&one_values));
186 let one_named_path = [NamedValidationDependency::new("a", value).with_path(&path)];
187 let one_paths = [path.clone()];
188 let one_context = BoundValidationContext::new_with_paths(&one_values, &one_paths).unwrap();
189 run_case("one_path", &b1, &one_named_path, &one_context);
190
191 let four_named = [
192 NamedValidationDependency::new("a", value),
193 NamedValidationDependency::new("b", value),
194 NamedValidationDependency::new("c", value),
195 NamedValidationDependency::new("d", value),
196 ];
197 let four_values = [value; 4];
198 run_case(
199 "four_plain",
200 &b4,
201 &four_named,
202 &BoundValidationContext::new(&four_values),
203 );
204 let four_named_path = [
205 NamedValidationDependency::new("a", value).with_path(&path),
206 NamedValidationDependency::new("b", value).with_path(&path),
207 NamedValidationDependency::new("c", value).with_path(&path),
208 NamedValidationDependency::new("d", value).with_path(&path),
209 ];
210 let four_paths = [path.clone(), path.clone(), path.clone(), path.clone()];
211 let four_context = BoundValidationContext::new_with_paths(&four_values, &four_paths).unwrap();
212 run_case("four_path", &b4, &four_named_path, &four_context);
213
214 let eight_named = [
215 NamedValidationDependency::new("h", value),
216 NamedValidationDependency::new("g", value),
217 NamedValidationDependency::new("f", value),
218 NamedValidationDependency::new("e", value),
219 NamedValidationDependency::new("d", value),
220 NamedValidationDependency::new("c", value),
221 NamedValidationDependency::new("b", value),
222 NamedValidationDependency::new("a", value),
223 ];
224 let eight_values = [value; 8];
225 let eight_context = BoundValidationContext::new(&eight_values);
226 run_case("eight_plain", &b8, &eight_named, &eight_context);
227 let eight_named_mixed = [
228 NamedValidationDependency::new("h", value).with_path(&path),
229 NamedValidationDependency::new("g", value),
230 NamedValidationDependency::new("f", value),
231 NamedValidationDependency::new("e", value),
232 NamedValidationDependency::new("d", value),
233 NamedValidationDependency::new("c", value),
234 NamedValidationDependency::new("b", value),
235 NamedValidationDependency::new("a", value).with_path(&tail_path),
236 ];
237 let eight_paths = [
238 tail_path.clone(),
239 ValidationPath::root(),
240 ValidationPath::root(),
241 ValidationPath::root(),
242 ValidationPath::root(),
243 ValidationPath::root(),
244 ValidationPath::root(),
245 path.clone(),
246 ];
247 let eight_context = BoundValidationContext::new_with_paths(&eight_values, &eight_paths).unwrap();
248 run_case("eight_mixed_path", &b8, &eight_named_mixed, &eight_context);
249
250 let nine_named = [
251 NamedValidationDependency::new("i", value),
252 NamedValidationDependency::new("h", value),
253 NamedValidationDependency::new("g", value),
254 NamedValidationDependency::new("f", value),
255 NamedValidationDependency::new("e", value),
256 NamedValidationDependency::new("d", value),
257 NamedValidationDependency::new("c", value),
258 NamedValidationDependency::new("b", value),
259 NamedValidationDependency::new("a", value),
260 ];
261 let nine_values = [value; 9];
262 let nine_context = BoundValidationContext::new(&nine_values);
263 run_case("nine_plain", &b9, &nine_named, &nine_context);
264 let nine_named_mixed = [
265 NamedValidationDependency::new("i", value).with_path(&path),
266 NamedValidationDependency::new("h", value),
267 NamedValidationDependency::new("g", value),
268 NamedValidationDependency::new("f", value),
269 NamedValidationDependency::new("e", value),
270 NamedValidationDependency::new("d", value),
271 NamedValidationDependency::new("c", value),
272 NamedValidationDependency::new("b", value),
273 NamedValidationDependency::new("a", value).with_path(&tail_path),
274 ];
275 let nine_paths = [
276 tail_path.clone(),
277 ValidationPath::root(),
278 ValidationPath::root(),
279 ValidationPath::root(),
280 ValidationPath::root(),
281 ValidationPath::root(),
282 ValidationPath::root(),
283 ValidationPath::root(),
284 path.clone(),
285 ];
286 let nine_context = BoundValidationContext::new_with_paths(&nine_values, &nine_paths).unwrap();
287 run_case("nine_mixed_path", &b9, &nine_named_mixed, &nine_context);
288}Sourcepub fn as_segments(&self) -> &[PathSegment]
pub fn as_segments(&self) -> &[PathSegment]
Returns the path segments in order.
§Returns
A borrowed slice ordered from the root toward the target.
Sourcepub fn with_field(self, field: &'static str) -> Self
pub fn with_field(self, field: &'static str) -> Self
Appends a statically declared field segment.
Use only program-declared field labels. Runtime map keys belong in an opaque map-entry segment so their text is not retained.
§Parameters
field: Static label of the declared field.
§Returns
The path with field appended after its existing segments.
Examples found in repository?
168fn main() {
169 let b0 = V0.bind(ValidatorId::new("bench.zero"), 0, &[]).unwrap();
170 let b1 = V1.bind(ValidatorId::new("bench.one"), 0, &[]).unwrap();
171 let b4 = V4.bind(ValidatorId::new("bench.four"), 0, &[]).unwrap();
172 let b8 = V8.bind(ValidatorId::new("bench.eight"), 0, &[]).unwrap();
173 let b9 = V9.bind(ValidatorId::new("bench.nine"), 0, &[]).unwrap();
174 let number = 7_u64;
175 let value = ValidationValue::Typed(&number);
176 let path = ValidationPath::root().with_field("sample");
177 let tail_path = ValidationPath::root().with_field("tail");
178
179 let empty_named: [NamedValidationDependency<'_>; 0] = [];
180 let empty_values: [ValidationValue<'_>; 0] = [];
181 run_case("zero", &b0, &empty_named, &BoundValidationContext::new(&empty_values));
182
183 let one_named = [NamedValidationDependency::new("a", value)];
184 let one_values = [value];
185 run_case("one_plain", &b1, &one_named, &BoundValidationContext::new(&one_values));
186 let one_named_path = [NamedValidationDependency::new("a", value).with_path(&path)];
187 let one_paths = [path.clone()];
188 let one_context = BoundValidationContext::new_with_paths(&one_values, &one_paths).unwrap();
189 run_case("one_path", &b1, &one_named_path, &one_context);
190
191 let four_named = [
192 NamedValidationDependency::new("a", value),
193 NamedValidationDependency::new("b", value),
194 NamedValidationDependency::new("c", value),
195 NamedValidationDependency::new("d", value),
196 ];
197 let four_values = [value; 4];
198 run_case(
199 "four_plain",
200 &b4,
201 &four_named,
202 &BoundValidationContext::new(&four_values),
203 );
204 let four_named_path = [
205 NamedValidationDependency::new("a", value).with_path(&path),
206 NamedValidationDependency::new("b", value).with_path(&path),
207 NamedValidationDependency::new("c", value).with_path(&path),
208 NamedValidationDependency::new("d", value).with_path(&path),
209 ];
210 let four_paths = [path.clone(), path.clone(), path.clone(), path.clone()];
211 let four_context = BoundValidationContext::new_with_paths(&four_values, &four_paths).unwrap();
212 run_case("four_path", &b4, &four_named_path, &four_context);
213
214 let eight_named = [
215 NamedValidationDependency::new("h", value),
216 NamedValidationDependency::new("g", value),
217 NamedValidationDependency::new("f", value),
218 NamedValidationDependency::new("e", value),
219 NamedValidationDependency::new("d", value),
220 NamedValidationDependency::new("c", value),
221 NamedValidationDependency::new("b", value),
222 NamedValidationDependency::new("a", value),
223 ];
224 let eight_values = [value; 8];
225 let eight_context = BoundValidationContext::new(&eight_values);
226 run_case("eight_plain", &b8, &eight_named, &eight_context);
227 let eight_named_mixed = [
228 NamedValidationDependency::new("h", value).with_path(&path),
229 NamedValidationDependency::new("g", value),
230 NamedValidationDependency::new("f", value),
231 NamedValidationDependency::new("e", value),
232 NamedValidationDependency::new("d", value),
233 NamedValidationDependency::new("c", value),
234 NamedValidationDependency::new("b", value),
235 NamedValidationDependency::new("a", value).with_path(&tail_path),
236 ];
237 let eight_paths = [
238 tail_path.clone(),
239 ValidationPath::root(),
240 ValidationPath::root(),
241 ValidationPath::root(),
242 ValidationPath::root(),
243 ValidationPath::root(),
244 ValidationPath::root(),
245 path.clone(),
246 ];
247 let eight_context = BoundValidationContext::new_with_paths(&eight_values, &eight_paths).unwrap();
248 run_case("eight_mixed_path", &b8, &eight_named_mixed, &eight_context);
249
250 let nine_named = [
251 NamedValidationDependency::new("i", value),
252 NamedValidationDependency::new("h", value),
253 NamedValidationDependency::new("g", value),
254 NamedValidationDependency::new("f", value),
255 NamedValidationDependency::new("e", value),
256 NamedValidationDependency::new("d", value),
257 NamedValidationDependency::new("c", value),
258 NamedValidationDependency::new("b", value),
259 NamedValidationDependency::new("a", value),
260 ];
261 let nine_values = [value; 9];
262 let nine_context = BoundValidationContext::new(&nine_values);
263 run_case("nine_plain", &b9, &nine_named, &nine_context);
264 let nine_named_mixed = [
265 NamedValidationDependency::new("i", value).with_path(&path),
266 NamedValidationDependency::new("h", value),
267 NamedValidationDependency::new("g", value),
268 NamedValidationDependency::new("f", value),
269 NamedValidationDependency::new("e", value),
270 NamedValidationDependency::new("d", value),
271 NamedValidationDependency::new("c", value),
272 NamedValidationDependency::new("b", value),
273 NamedValidationDependency::new("a", value).with_path(&tail_path),
274 ];
275 let nine_paths = [
276 tail_path.clone(),
277 ValidationPath::root(),
278 ValidationPath::root(),
279 ValidationPath::root(),
280 ValidationPath::root(),
281 ValidationPath::root(),
282 ValidationPath::root(),
283 ValidationPath::root(),
284 path.clone(),
285 ];
286 let nine_context = BoundValidationContext::new_with_paths(&nine_values, &nine_paths).unwrap();
287 run_case("nine_mixed_path", &b9, &nine_named_mixed, &nine_context);
288}Sourcepub fn with_index(self, index: usize) -> Self
pub fn with_index(self, index: usize) -> Self
Sourcepub fn with_map_entry(self, index: usize) -> Self
pub fn with_map_entry(self, index: usize) -> Self
Sourcepub fn with_map_key(self) -> Self
pub fn with_map_key(self) -> Self
Appends the key side of a map entry without storing the key itself.
§Returns
The path with a map-key marker appended.
Sourcepub fn with_map_value(self) -> Self
pub fn with_map_value(self) -> Self
Sourcepub fn concat(&self, relative: &Self) -> Self
pub fn concat(&self, relative: &Self) -> Self
Appends a relative path to this path without rendering either one.
Returns a new path and leaves both inputs unchanged. Segments from
relative follow this path’s segments in their original order.
§Parameters
relative: Relative suffix to append to this path.
§Returns
A newly allocated path containing both segment sequences.
Sourcepub fn render(&self) -> String
pub fn render(&self) -> String
Explicitly renders this path for a trusted presentation layer.
The result can contain program-supplied field labels but never contains
a raw validation value or map key. Simple ASCII identifiers use dotted
notation; other field labels use JSON-escaped [...] notation. This
changes the rendered format for special field labels.
§Returns
A newly allocated string containing the rendered field and positional segments, or an empty string for the root path.