pub struct ValidatorDescriptor { /* private fields */ }Expand description
A definition containing one or more input/dependency signatures.
§Examples
use std::convert::Infallible;
use std::sync::Arc;
use qubit_validator::prepare_text_validator;
use qubit_validator::ArgumentReader;
use qubit_validator::BindError;
use qubit_validator::InputType;
use qubit_validator::PreparedValidator;
use qubit_validator::Validator;
use qubit_validator::ValidatorDescriptor;
use qubit_validator::ValidatorSignature;
struct AcceptAll;
impl Validator<str> for AcceptAll {
type Error = Infallible;
fn validate(&self, _: &str, _: &()) -> Result<(), Self::Error> {
Ok(())
}
}
fn prepare(
_reader: &mut ArgumentReader<'_>,
) -> Result<Arc<dyn PreparedValidator>, BindError> {
Ok(prepare_text_validator(AcceptAll, |never| match never {}))
}
static SIGNATURES: &[ValidatorSignature] = &[
ValidatorSignature::new(InputType::Text, &[], prepare),
];
let descriptor = ValidatorDescriptor::try_new(SIGNATURES)?;
assert_eq!(descriptor.signatures().len(), 1);Implementations§
Source§impl ValidatorDescriptor
impl ValidatorDescriptor
Sourcepub const fn new(signatures: &'static [ValidatorSignature]) -> Self
pub const fn new(signatures: &'static [ValidatorSignature]) -> Self
Creates a descriptor from static signatures.
Duplicate signature shapes are rejected when binding. Use
Self::try_new when construction-time validation is desired.
§Parameters
signatures: Static signature declarations in their selection order.
§Returns
A descriptor referring to the supplied declarations.
Examples found in repository?
More examples
76static DESCRIPTOR: ValidatorDescriptor = ValidatorDescriptor::new(SIGNATURES);
77
78#[cfg(feature = "inventory")]
79register_validator!(id = "text.non_blank.global", descriptor = &DESCRIPTOR);
80
81static DEPENDENCIES: &[DependencySpec] = &[
82 DependencySpec::new("minimum", InputType::Text, false),
83 DependencySpec::new("maximum", InputType::Text, false),
84];
85
86struct CheckDependencySlots;
87
88impl PreparedValidator for CheckDependencySlots {
89 fn input_type(&self) -> InputType {
90 InputType::Text
91 }
92 fn dependency_specs(&self) -> &'static [DependencySpec] {
93 DEPENDENCIES
94 }
95
96 fn validate(
97 &self,
98 _: ValidationValue<'_>,
99 context: &BoundValidationContext<'_>,
100 ) -> Result<PreparedOutcome, ExecutionError> {
101 let valid = context.value(0)?.as_text() == Some("minimum") && context.value(1)?.as_text() == Some("maximum");
102 Ok(if valid {
103 PreparedOutcome::Valid
104 } else {
105 PreparedOutcome::Invalid(vec![ViolationDraft::new(ViolationCode::new(
106 "text.dependencies_mismatch",
107 ))])
108 })
109 }
110}
111
112fn prepare_dependency_slots(_reader: &mut ArgumentReader<'_>) -> Result<Arc<dyn PreparedValidator>, BindError> {
113 Ok(Arc::new(CheckDependencySlots))
114}
115
116static DEPENDENCY_SIGNATURES: &[ValidatorSignature] = &[ValidatorSignature::new(
117 InputType::Text,
118 DEPENDENCIES,
119 prepare_dependency_slots,
120)];
121static DEPENDENCY_DESCRIPTOR: ValidatorDescriptor = ValidatorDescriptor::new(DEPENDENCY_SIGNATURES);Sourcepub fn try_new(
signatures: &'static [ValidatorSignature],
) -> Result<Self, BindError>
pub fn try_new( signatures: &'static [ValidatorSignature], ) -> Result<Self, BindError>
Creates a descriptor and checks for duplicate signature shapes.
§Parameters
signatures: Static signature declarations in their selection order.
§Returns
A descriptor containing the declarations when they are non-empty and unambiguous.
§Errors
Returns InvalidDeclaration when there are no signatures or a
dependency name is empty or repeated. Returns AmbiguousSignature when
two signatures accept the same input shape.
Sourcepub const fn signatures(&self) -> &'static [ValidatorSignature]
pub const fn signatures(&self) -> &'static [ValidatorSignature]
Returns every supported signature in declaration order.
§Returns
The static signature slice used by this descriptor.
Sourcepub fn bind<'a>(
&self,
rule_id: ValidatorId,
signature_index: usize,
params: &'a [NamedValidationArgument<'a>],
) -> Result<BoundValidator, BindError>
pub fn bind<'a>( &self, rule_id: ValidatorId, signature_index: usize, params: &'a [NamedValidationArgument<'a>], ) -> Result<BoundValidator, BindError>
Binds one explicitly selected signature and owns its prepared instance.
§Parameters
rule_id: Stable rule identifier attached to the binding, its violations, and binding errors.signature_index: Zero-based index intoSelf::signaturesin declaration order. Reordering signatures changes this selection.params: Named configuration arguments borrowed during preparation. The factory must own any configuration it retains for execution.
§Returns
A reusable binding owning a shared prepared validator instance. The
returned binding does not borrow params.
§Errors
Returns InvalidDeclaration or AmbiguousSignature when the
descriptor is malformed, and InvalidSelection when
signature_index is out of range. Parameter binding errors identify
duplicate or unconsumed arguments; factory errors and prepared-shape
mismatches are also returned with rule_id attached.
Examples found in repository?
123fn assert_dependency_specs_come_from_signature() -> Result<(), ExecutionError> {
124 let bound = DEPENDENCY_DESCRIPTOR
125 .bind(ValidatorId::new("text.dependent"), 0, &[])
126 .expect("signature binds");
127 assert_eq!(bound.dependency_specs(), DEPENDENCIES);
128 let dependencies = [
129 NamedValidationDependency::new("maximum", ValidationValue::Text("maximum")),
130 NamedValidationDependency::new("minimum", ValidationValue::Text("minimum")),
131 ];
132 assert_eq!(
133 bound.validate_named(ValidationValue::Text("target"), &dependencies)?,
134 ValidationOutcome::Valid,
135 );
136 Ok(())
137}More examples
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 bind_for<'a>(
&self,
rule_id: ValidatorId,
input: InputType,
params: &'a [NamedValidationArgument<'a>],
) -> Result<BoundValidator, BindError>
pub fn bind_for<'a>( &self, rule_id: ValidatorId, input: InputType, params: &'a [NamedValidationArgument<'a>], ) -> Result<BoundValidator, BindError>
Selects and binds the unique signature matching an input shape.
§Parameters
rule_id: Stable rule identifier attached to the binding, its violations, and binding errors.input: Input shape used to select the matching signature; binding does not convert values between input shapes.params: Named configuration arguments borrowed during preparation. The factory must own any configuration it retains for execution.
§Returns
A reusable binding owning a shared prepared validator instance for
input. The returned binding does not borrow params.
§Errors
Returns InvalidDeclaration or AmbiguousSignature when the
descriptor is malformed, and UnsupportedInput when no signature
accepts input. Parameter binding errors, factory errors, and prepared
shape mismatches are returned with rule_id attached.
Trait Implementations§
Source§impl Clone for ValidatorDescriptor
impl Clone for ValidatorDescriptor
impl Copy for ValidatorDescriptor
Source§impl Debug for ValidatorDescriptor
impl Debug for ValidatorDescriptor
Source§fn fmt(&self, formatter: &mut Formatter<'_>) -> Result
fn fmt(&self, formatter: &mut Formatter<'_>) -> Result
Formats the number of signatures without exposing preparation details.
§Parameters
self: Descriptor whose signature count is written to the formatter.formatter: Destination formatter that receives the debug representation.
§Returns
Ok(()) when formatting succeeds.
§Errors
Returns the formatter’s error if writing the representation fails.