TransformParser

Struct TransformParser 

Source
pub struct TransformParser<P, T, O> { /* private fields */ }
Expand description

Parser implementation that performs type conversion and validation after the parsing is complete

This parser delegates the parsing and completion to the underlying parser. If parsing is successfull, it calls the ParsableTransformation’s transform method which maps the parsed value onto another type.

§Examples

This parser can be used for type converstion (as it is done for T -> Box<T>) or for data validation.

For example, you can implement Parsable for a newtype that would use the inner data’s default parser implementation (without using derive macro):

use cmdparse::{Parsable, parse};
use cmdparse::error::ParseError;
use cmdparse::parsers::{TransformParser, ParsableTransformation};

#[derive(Debug, PartialEq, Eq)]
struct PostId(usize);

impl ParsableTransformation<PostId> for PostId {
    type Input = usize;

    fn transform(input: usize) -> Result<PostId, ParseError<'static>> {
        Ok(PostId(input))
    }
}

impl<Ctx> Parsable<Ctx> for PostId {
    type Parser = TransformParser<<usize as Parsable<Ctx>>::Parser, PostId, PostId>;
}

let value = parse::<_, PostId>("42", ())?;
assert_eq!(value, PostId(42));

Note that the example above can be greatly simplified by using a Parsable derive macro. Although the implementation details are going to be different, the following example is functionally equivalent to the one above:

#[derive(Debug, PartialEq, Eq, Parsable)]
struct PostId(usize);

let value = parse::<_, PostId>("42", ())?;
assert_eq!(value, PostId(42));

It is not important which trait implements ParsableTransformation. The trait is designed this way to circumvent the limitations of the Rust’s type system: foreign traits cannot be implemented for foreign types. Also, it allows the user to define multiple different transformations for the same type, which is useful for data validation:

use cmdparse::{Parsable, parse_parser};
use cmdparse::error::ParseError;
use cmdparse::parsers::{TransformParser, ParsableTransformation};

struct IsPowerOfTwo;

impl ParsableTransformation<u64> for IsPowerOfTwo {
    type Input = u64;

    fn transform(input: u64) -> Result<u64, ParseError<'static>> {
        if input.is_power_of_two() {
            Ok(input)
        } else {
            Err(ParseError::custom("not a power of two"))
        }
    }
}

type PowerOfTwoParser<Ctx> =
    TransformParser<<u64 as Parsable<Ctx>>::Parser, IsPowerOfTwo, u64>;

assert!(parse_parser::<_, PowerOfTwoParser<()>>("16", ()).is_ok());
assert!(parse_parser::<_, PowerOfTwoParser<()>>("14", ()).is_err());

Trait Implementations§

Source§

impl<P, T, O> Default for TransformParser<P, T, O>

Source§

fn default() -> Self

Returns the “default value” for a type. Read more
Source§

impl<Ctx, P, T, O> Parser<Ctx> for TransformParser<P, T, O>
where P: Parser<Ctx>, T: ParsableTransformation<O, Input = P::Value>,

Source§

type Value = O

The type that this parser will parse the input stream into.
Source§

fn parse<'a>( &self, input: TokenStream<'a>, ctx: Ctx, ) -> ParseResult<'a, Self::Value>

Parsers the beginning of the token stream into a Value. Read more
Source§

fn complete<'a>(&self, input: TokenStream<'a>, ctx: Ctx) -> CompletionResult<'a>

Constructs the completion suggestions for the last token of the input stream Read more

Auto Trait Implementations§

§

impl<P, T, O> Freeze for TransformParser<P, T, O>

§

impl<P, T, O> RefUnwindSafe for TransformParser<P, T, O>

§

impl<P, T, O> Send for TransformParser<P, T, O>
where P: Send, T: Send, O: Send,

§

impl<P, T, O> Sync for TransformParser<P, T, O>
where P: Sync, T: Sync, O: Sync,

§

impl<P, T, O> Unpin for TransformParser<P, T, O>
where P: Unpin, T: Unpin, O: Unpin,

§

impl<P, T, O> UnwindSafe for TransformParser<P, T, O>
where P: UnwindSafe, T: UnwindSafe, O: 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> 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> ParsableTransformation<Box<T>> for T

Source§

type Input = T

The type that will be transformed by the implementation if this trait (Self::Input -> O).
Source§

fn transform( input: <T as ParsableTransformation<Box<T>>>::Input, ) -> Result<Box<T>, ParseError<'static>>

Performs the transformation.
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.