Skip to main content

ValidatorId

Struct ValidatorId 

Source
pub struct ValidatorId(/* private fields */);
Expand description

A validated, process-independent validator identifier.

The value is non-empty and consists of one or more dot-separated segments. Each segment starts with an ASCII letter and continues with ASCII letters, digits, or underscores. Empty segments, whitespace, non-ASCII letters, and hyphens are rejected. No trimming or case normalization is performed.

§Examples

use qubit_validator::ValidatorId;
use qubit_validator::ValidatorIdError;

let id = ValidatorId::try_new("qubit.text.non_empty")?;
assert_eq!(id.as_str(), "qubit.text.non_empty");
let error = ValidatorId::try_new("qubit..non_empty").unwrap_err();
assert_eq!(error, ValidatorIdError::EmptySegment);
assert_eq!(
    ValidatorId::try_new("_custom.invalid"),
    Err(ValidatorIdError::InvalidSegment),
);

Implementations§

Source§

impl ValidatorId

Source

pub const fn new(value: &'static str) -> Self

Creates a stable ID from a static string.

§Parameters
  • value: A static string containing the complete protocol value.
§Returns

The validated identifier.

§Panics

Panics when value violates the syntax documented on ValidatorId.

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}
138
139fn assert_parameters_are_consumed_once() -> Result<(), BindError> {
140    let args = [NamedValidationArgument::new("limit", ValidationArgument::Unsigned(10))];
141    let mut reader = ArgumentReader::new(&args)?;
142    assert_eq!(reader.required_u32("limit")?, 10);
143    let error = reader
144        .required_u32("limit")
145        .expect_err("a parameter cannot be read twice");
146    assert_eq!(error.kind(), BindErrorKind::ParameterAlreadyConsumed);
147    Ok(())
148}
149
150fn main() -> Result<(), Box<dyn Error>> {
151    let registration = ValidatorRegistration::new(
152        ValidatorId::new("text.non_blank"),
153        &DESCRIPTOR,
154        RegistrationSource::new(env!("CARGO_PKG_NAME"), module_path!(), file!(), line!()),
155    );
156    let registry = ValidatorRegistry::from_registrations([registration])?;
157
158    assert!(registry.get("text.non_blank").is_some());
159    let validator = registry.bind("text.non_blank", InputType::Text, &[])?;
160    let context = BoundValidationContext::new(&[]);
161
162    let valid = validator.validate(ValidationValue::Text("Ada"), &context)?;
163    assert_eq!(valid, ValidationOutcome::Valid);
164
165    let invalid = validator.validate(ValidationValue::Text("   "), &context)?;
166    let ValidationOutcome::Invalid(violations) = invalid else {
167        panic!("blank text must be invalid");
168    };
169    assert_eq!(violations.len(), 1);
170    assert_eq!(violations[0].code(), ViolationCode::new("text.blank"));
171
172    assert_dependency_specs_come_from_signature()?;
173    assert_parameters_are_consumed_once()?;
174
175    #[cfg(feature = "inventory")]
176    {
177        let global = ValidatorRegistry::try_global()?;
178        assert!(global.get("text.non_blank.global").is_some());
179    }
180
181    Ok(())
182}
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 const fn try_new(value: &'static str) -> Result<Self, ValidatorIdError>

Validates and creates a stable ID.

§Parameters
  • value: A static string containing the complete protocol value.
§Returns

The validated identifier when value follows the protocol.

§Errors

Returns ValidatorIdError::Empty for an empty string, ValidatorIdError::EmptySegment for an empty dot-separated segment, or ValidatorIdError::InvalidSegment for a segment with invalid characters or an invalid first character.

Source

pub const fn as_str(self) -> &'static str

Returns the complete stable ID.

Trait Implementations§

Source§

impl Borrow<str> for ValidatorId

Source§

fn borrow(&self) -> &str

Borrows the complete validated identifier as text.

§Returns

The identifier text, borrowed from this value.

Source§

impl Clone for ValidatorId

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 ValidatorId

Source§

impl Debug for ValidatorId

Source§

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

Formats the value using the given formatter. Read more
Source§

impl Eq for ValidatorId

Source§

impl Hash for ValidatorId

Source§

fn hash<__H: Hasher>(&self, state: &mut __H)

Feeds this value into the given Hasher. Read more
1.3.0 · Source§

fn hash_slice<H>(data: &[Self], state: &mut H)
where H: Hasher, Self: Sized,

Feeds a slice of this type into the given Hasher. Read more
Source§

impl Ord for ValidatorId

Source§

fn cmp(&self, other: &Self) -> Ordering

This method returns an Ordering between self and other. Read more
1.21.0 (const: unstable) · Source§

fn max(self, other: Self) -> Self
where Self: Sized,

Compares and returns the maximum of two values. Read more
1.21.0 (const: unstable) · Source§

fn min(self, other: Self) -> Self
where Self: Sized,

Compares and returns the minimum of two values. Read more
1.50.0 (const: unstable) · Source§

fn clamp(self, min: Self, max: Self) -> Self
where Self: Sized,

Restrict a value to a certain interval. Read more
Source§

fn clamp_to<R>(self, range: R) -> Self
where Self: Sized, R: ClampBounds<Self>,

🔬This is a nightly-only experimental API. (clamp_to)
Restrict a value to a certain range. Read more
Source§

impl PartialEq for ValidatorId

Source§

fn eq(&self, other: &Self) -> bool

Equality operator ==. Read more
1.0.0 (const: unstable) · Source§

fn ne(&self, other: &Rhs) -> bool

Inequality operator !=. Read more
Source§

impl PartialOrd for ValidatorId

Source§

fn partial_cmp(&self, other: &Self) -> Option<Ordering>

This method returns an ordering between self and other values if one exists. Read more
1.0.0 (const: unstable) · Source§

fn lt(&self, other: &Rhs) -> bool

Tests less than (for self and other) and is used by the < operator. Read more
1.0.0 (const: unstable) · Source§

fn le(&self, other: &Rhs) -> bool

Tests less than or equal to (for self and other) and is used by the <= operator. Read more
1.0.0 (const: unstable) · Source§

fn gt(&self, other: &Rhs) -> bool

Tests greater than (for self and other) and is used by the > operator. Read more
1.0.0 (const: unstable) · Source§

fn ge(&self, other: &Rhs) -> bool

Tests greater than or equal to (for self and other) and is used by the >= operator. Read more
Source§

impl StructuralPartialEq for ValidatorId

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.