Skip to main content

ValidatorDescriptor

Struct ValidatorDescriptor 

Source
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

Source

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?
examples/validate_named_bench.rs (line 107)
107static V0: ValidatorDescriptor = ValidatorDescriptor::new(S0);
108static V1: ValidatorDescriptor = ValidatorDescriptor::new(S1);
109static V4: ValidatorDescriptor = ValidatorDescriptor::new(S4);
110static V8: ValidatorDescriptor = ValidatorDescriptor::new(S8);
111static V9: ValidatorDescriptor = ValidatorDescriptor::new(S9);
More examples
Hide additional examples
examples/local_registry.rs (line 76)
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);
Source

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.

Source

pub const fn signatures(&self) -> &'static [ValidatorSignature]

Returns every supported signature in declaration order.

§Returns

The static signature slice used by this descriptor.

Source

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 into Self::signatures in 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?
examples/local_registry.rs (line 125)
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
Hide additional examples
examples/validate_named_bench.rs (line 169)
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}
Source

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

Source§

fn clone(&self) -> Self

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Copy for ValidatorDescriptor

Source§

impl Debug for ValidatorDescriptor

Source§

fn fmt(&self, formatter: &mut Formatter<'_>) -> Result

Formats the number of signatures without exposing preparation details.

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.