#preprocessor #validation #process #test #api

macro preprocess-macro

Preprocesses a struct with built-in preprocessors

16 unstable releases (3 breaking)

0.5.7 Aug 2, 2024
0.5.6 Jun 22, 2024
0.5.2 May 20, 2024
0.4.1 Apr 22, 2024
0.2.1 Jul 19, 2023

#1887 in Procedural macros


Used in preprocess

MIT license

44KB
1.5K SLoC

Preprocess

A crate to help you preprocess your structs and enums. Can be used to validate data, or to transform it.

There are two kinds of preprocessors:

  • Validators: They check if the given field is valid and don't modify the value. For example: a validator could check if a string is a valid email address.
  • Preprocessors: These allow you to modify the value (and possibly type) of a field. For example: a preprocessor could trim a string, or convert it to uppercase.

Example usage

use preprocess::prelude::*;

#[preprocess::sync]
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct UserSignUpRequest {
    // First trims the email, then converts it to lowercase, then validates it as an email address.
    #[preprocess(trim, lowercase, email)]
    pub email: String,
    // First trims the password, then checks if it's at least 8 characters long.
    #[preprocess(trim, length(min = 8))]
    pub password: String,
}

let processed_value = raw_value.preprocess()?;

Inheriting derive attributes

Since the crate uses an attribute macro, it must always be the first attribute on the struct or enum. A new struct / enum will be generated with the name {original_name}Processed. The derive macro will inherit all the derive attributes from the original struct / enum. For example:

use preprocess::prelude::*;

#[preprocess::sync]
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct UserSignUpRequest {
    #[preprocess(trim, lowercase, email)]
    #[serde(default)]
    pub email: String,
    #[serde(alias = "pass")]
    #[preprocess(trim, length(min = 8))]
    pub password: String,
}

The above code will generate:

#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct UserSignUpRequestProcessed {
    #[serde(default)]
    pub email: String,
    #[serde(alias = "pass")]
    pub password: String,
}

This way, any custom derive attributes you use (like Serde) will be inherited by the generated struct / enum. This also ensures that you can preprocess your struct / enum and send the preprocessed version to the client, without having to write any extra code.

More details about the crate can be found in the documentation.

MSRV

There is no MSRV as such, and to be honest, I don't see the point of an MSRV, with how easy rust is to upgrade. I just use the latest version of rust on my machine. That being said, I don't think I've used any new rust features. So it should work on older versions of rust as well. Please open an issue if you're facing any, well, issues.

Inspiration

This crate is largely inspired by the validator crate. A huge thanks to Keats for creating it.

License

This project is licensed under the MIT license.

Dependencies

~2.4–4MB
~71K SLoC