Struct Validated

Source
pub struct Validated<C, T>(/* private fields */);
Expand description

A wrapper type to express that the value of type T has been validated by the constraint C.

The idea is that an instance of Validated<C, T> can only be obtained by validating a value of type T using the constraint C. There is no way to construct an instance of Validated directly.1

It follows the new type pattern and can be de-referenced to a immutable reference to its inner value or unwrapped to get the owned inner value.

In an application we can make use of the type system to assure that only valid values of some type can be input to some function performing some domain related things.

For example, lets assume we have a function that expects a valid email address as input. We could write the function like:

fn send_email(to: String, message: String) {
    unimplemented!()
}

The problem with this approach is, that we can never be sure that the string input for the to argument is a valid email address.

Lets rewrite the same function using Validated<Email, String>.

use valid::Validated;

fn send_email(to: Validated<Email, String>, message: String) {
    unimplemented!()
}

Due to we can not instantiate Validated directly using some constructor function like Validated(email) or Validated::new(email) we need to use a validation function like:

# fn send_email(to: Validated<Email, String>, message: String) {
#     unimplemented!()
# }
use valid::{Validated, Validate};

let to_addr = "jane.doe@email.net".to_string().validate("email", Email).result()
        .expect("valid email address");

send_email(to_addr, "some message".into());

Now we can be sure that the variable to_addr contains a valid email address.

To further make use of meaningful new types we might define a custom new type for email addresses, that can only be constructed from a validated value like so:

# fn send_email(to: EmailAddress, message: String) {
#     unimplemented!()
# }
use valid::{Validate, Validated};

mod domain_model {
    use valid::Validated;
    pub struct EmailAddress(String);

    impl From<Validated<Email, String>> for EmailAddress {
        fn from(value: Validated<String>) -> Self {
            EmailAddress(value.unwrap())
        }
    }
}

let validated = "jane.doe@email.net".to_string().validate("email", Email).result(None)
        .expect("valid email address");

let to_addr = EmailAddress::from(validated);

send_email(to_addr, "some message".into());

Due to the type EmailAddress is defined in another module it can only be constructed from a Validated<Email, String>.


  1. Actually there is a way to construct an instance of Validated without actually doing any validation: we can use the Validation::success method (see unit tests on how it can be done) We need this method for custom implementations of the Validate trait. Unfortunately I have no idea how to prevent this. Fortunately such code can be found by (automated) code review. 

Implementations§

Source§

impl<C, T> Validated<C, T>

Source

pub fn unwrap(self) -> T

Unwraps the original value that has been validated

Trait Implementations§

Source§

impl<C, T> Clone for Validated<C, T>
where T: Clone,

Source§

fn clone(&self) -> Self

Returns a duplicate of the value. Read more
1.0.0 · Source§

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

Performs copy-assignment from source. Read more
Source§

impl<C, T> Debug for Validated<C, T>
where T: Debug,

Source§

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

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

impl<C, T> Deref for Validated<C, T>

Source§

type Target = T

The resulting type after dereferencing.
Source§

fn deref(&self) -> &Self::Target

Dereferences the value.
Source§

impl<C, T> PartialEq for Validated<C, T>
where T: PartialEq,

Source§

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

Tests for self and other values to be equal, and is used by ==.
1.0.0 · Source§

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

Tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
Source§

impl<C, T> Copy for Validated<C, T>
where T: Copy,

Source§

impl<C, T> Eq for Validated<C, T>
where T: Eq,

Auto Trait Implementations§

§

impl<C, T> Freeze for Validated<C, T>
where T: Freeze,

§

impl<C, T> RefUnwindSafe for Validated<C, T>

§

impl<C, T> Send for Validated<C, T>
where T: Send, C: Send,

§

impl<C, T> Sync for Validated<C, T>
where T: Sync, C: Sync,

§

impl<C, T> Unpin for Validated<C, T>
where T: Unpin, C: Unpin,

§

impl<C, T> UnwindSafe for Validated<C, T>
where T: UnwindSafe, C: UnwindSafe,

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<P, T> Receiver for P
where P: Deref<Target = T> + ?Sized, T: ?Sized,

Source§

type Target = T

🔬This is a nightly-only experimental API. (arbitrary_self_types)
The target type on which the method may be called.
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 = Infallible

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

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

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.