kaj / ructe

Rust Compiled Templates with static-file handling
https://crates.io/crates/ructe
453 stars 33 forks source link

match enum struct variant defect? #103

Open LittleEntity opened 3 years ago

LittleEntity commented 3 years ago

I try to match the following enum with internal struct variants

pub enum ValidationError {
    LengthOutOfBounds {
        min: usize,
        max: usize,
    },
    InvalidName {
        invalid_chars: Vec<char>,
    },
    UniqueConstraintViolation,
}

with

@use crate::ValidationError::{self, *};

@(error: &ValidationError)

@match error {
    UniqueConstraintViolation => {
        This name is taken.
    }
    LengthOutOfBounds { min, max } => {
        This field must contain at min @min and at max @max characters.
    }
    InvalidName { invalid_chars } => {
        @format!("The name must not contain any of the following characters: {:?}", invalid_chars)
    }
}

The error message is:

warning: Template parse error in "template_src/validation_error_display_part.rs.html":
warning:    5:@match error {
warning:      ^ Error in expression starting here:
warning:    5:@match error {
warning:             ^ Error in match expression:
warning:    8:    }
warning:           ^ Error in match arm starting here:

this works:

@use crate::ValidationError::{self, *};

@(error: &ValidationError)

@match error {
    UniqueConstraintViolation(value) => {
        This name is taken.
    }
    _ => {
        other error
    }
}

In rust this works:

impl<'s> std::fmt::Display for ValidationError<'s> {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
        use ValidationError::*;
        match self {
            LengthOutOfBounds { min, max } => {
                write!(
                    f,
                    "This field must contain at min {} and at max {} characters.",
                    min, max
                )
            }
            InvalidName {
                invalid_chars,
            } => {
                write!(
                    f,
                    "The name must not contain any of the following characters: {:?}",
                    invalid_chars
                )
            }
            UniqueConstraintViolation => {
                write!(f, "This name is taken.")
            }
        }
    }
}

Am I doing something wrong? Is this a defect of the library?

I enjoy using ructe 🦀 thankyou for sharing 🙏

kaj commented 3 years ago

Yes, this seems like a defect in ructe. I'll try to fix it.

LittleEntity commented 3 years ago

I guess it can be fixed here: https://github.com/kaj/ructe/blob/75b2e7da686abdd22bd2488e63f1528e3e16d313/src/templateexpression.rs#L210-L244

Unfortunatly I only have some experience with https://pest.rs/ . Nom seems to be a fine parsing library too. Maybe I will find some spare time this weekend to look into https://lib.rs/crates/nom. Maybe I can contribute in the future ^^.

Please take note there is more to the match syntax to explore: https://doc.rust-lang.org/book/ch18-03-pattern-syntax.html

There are many cases I didn't know of before. For example the @ binding. It seems to be a huge task to parse every possible match syntax pattern correctly. I personally use this pattern as well:

enum Variation {
    Structure {
        id: usize,
        name: String,
        not_used: i32,
    },
    SimpleVariant,
}

fn main() {
    let variation = Variation::Structure {
        id: 42,
        name: "an example for the great ructe lib 🦀".into(),
        not_used: -123,
    };

    match variation {
        Variation::Structure {
            id,
            name: the_name, 
            ..
        } => {
            println!(r#"Object with ID {} has the name "{}""#, id, the_name);
        }
        Variation::SimpleVariant => {
            println!("This is just a simple variant match");
        }
    }
}

Please consider documenting which patterns are explicitly implemented and tested. If the mentioned enum/struct patterns work, that would be great. If you cannot fix it, because of lack of time or whatever reason, I will try to make a good work around =) thankyou 🙏

Are you looking for help with this library of yours? If so I will check if I can take off some spare time to contribute to this lib.