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>
impl<P, T, O> Default for TransformParser<P, T, O>
Source§impl<Ctx, P, T, O> Parser<Ctx> for TransformParser<P, T, O>
impl<Ctx, P, T, O> Parser<Ctx> for TransformParser<P, T, O>
Source§fn parse<'a>(
&self,
input: TokenStream<'a>,
ctx: Ctx,
) -> ParseResult<'a, Self::Value>
fn parse<'a>( &self, input: TokenStream<'a>, ctx: Ctx, ) -> ParseResult<'a, Self::Value>
Value. Read more