Skip to content

Commit

Permalink
Add support for multiple generic input types
Browse files Browse the repository at this point in the history
  • Loading branch information
marcdejonge committed Jan 6, 2025
1 parent 2728bda commit 20a87ca
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 5 deletions.
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[package]
name = "nom-parse-macros"
description = "Procedural macros for generating parser functions for the nom libary"
version = "0.1.0"
version = "0.1.1"
license = "MIT/Apache-2.0"
keywords = ["nom", "parser", "parsable"]
categories = ["parsing"]
Expand Down
29 changes: 25 additions & 4 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,12 +40,15 @@ fn generate_struct_parser(attrs: TokenStream, mut object: ItemStruct) -> TokenSt
let expression_names = fields.get_expression_names();
let derived_expressions = fields.get_derived_expressions();
let create_expr = fields.create_instance_expr(None);
let where_clause = generate_where_clause();

let tokens = quote! {
#object

impl nom_parse_trait::ParseFrom<&str> for #name {
fn parse(input: &str) -> nom::IResult<&str, Self> {
impl<I> nom_parse_trait::ParseFrom<I> for #name
#where_clause
{
fn parse(input: I) -> nom::IResult<I, Self> {
use nom::*;

let (input, (#(#expression_names),*)) = #expression.parse(input)?;
Expand Down Expand Up @@ -145,15 +148,18 @@ pub fn parse_match(attrs: TokenStream, object: TokenStream) -> TokenStream {
Err(e) => return e.to_compile_error().into(),
};
let name = object.ident.clone();
let where_clause = generate_where_clause();

match parse_string_match(&fields, literal) {
Ok(parts) => {
let names: Vec<_> = fields.fields.iter().map(|field| field.get_name()).collect();
let tokens = quote! {
#object

impl nom_parse_trait::ParseFrom<&str> for #name {
fn parse(input: &str) -> nom::IResult<&str, Self> {
impl<I> nom_parse_trait::ParseFrom<I> for #name
#where_clause
{
fn parse(input: I) -> nom::IResult<I, Self> {
use nom::*;

let mut input = input;
Expand All @@ -168,3 +174,18 @@ pub fn parse_match(attrs: TokenStream, object: TokenStream) -> TokenStream {
Err(e) => e.to_compile_error().into(),
}
}

fn generate_where_clause() -> proc_macro2::TokenStream {
quote! {
where
I: Clone,
I: nom::Slice<std::ops::RangeTo<usize>> + nom::Slice<std::ops::RangeFrom<usize>> + nom::Slice<std::ops::Range<usize>>,
I: nom::InputTake + nom::InputLength + nom::Offset + nom::AsBytes,
I: nom::InputIter,
<I as nom::InputIter>::Item: nom::AsChar + Copy,
<I as nom::InputIter>::IterElem: Clone,
I: nom::InputTakeAtPosition,
<I as nom::InputTakeAtPosition>::Item: nom::AsChar + Copy,
I: for<'a> nom::Compare<&'a [u8]>,
}
}
16 changes: 16 additions & 0 deletions tests/different_input_types.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
use nom_parse_macros::parse_from;
use nom_parse_trait::ParseFromExt;

#[parse_from(())]
#[derive(Debug, PartialEq)]
struct Test(i32);

#[test]
pub fn from_str() {
assert_eq!(Ok(Test(32)), Test::parse_complete("32"));
}

#[test]
pub fn from_bytes() {
assert_eq!(Ok(Test(32)), Test::parse_complete(b"32".as_ref()));
}

0 comments on commit 20a87ca

Please sign in to comment.