Skip to content

Commit

Permalink
Merge pull request #81 from greyblake/string-char-len
Browse files Browse the repository at this point in the history
Rename max_len -> char_len_max; min_len -> char_len_min
  • Loading branch information
greyblake committed Aug 12, 2023
2 parents 6400885 + 375fc12 commit 2573a81
Show file tree
Hide file tree
Showing 16 changed files with 59 additions and 58 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
* [BREAKING] Use commas to separate high level attributes
* [BREAKING] Traits are derived with `#[nutype(derive(Debug))]`. The regular `#[derive(Debug)]` syntax is not supported anymore.
* [BREAKING] Validator `with` has been renamed to `predicate` to reflect the boolean nature of its range
* [BREAKING] String validator `min_len` has been renamed to `char_len_min` to reflect that is based on UTF8 chars.
* [BREAKING] String validator `max_len` has been renamed to `char_len_max` to reflect that is based on UTF8 chars.
* Better error messages: in case of unknown attribute, validator or sanitizer the possible values are listed.

### v0.3.1 - 2023-06-30
Expand Down
18 changes: 9 additions & 9 deletions nutype/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
//!
//! #[nutype(
//! sanitize(trim, lowercase),
//! validate(not_empty, max_len = 20),
//! validate(not_empty, char_len_max = 20),
//! derive(Debug, PartialEq),
//! )]
//! pub struct Username(String);
Expand Down Expand Up @@ -104,13 +104,13 @@
//!
//! ### String validators
//!
//! | Validator | Description | Error variant | Example |
//! |-------------|---------------------------------------------------------------------------------|-----------------|----------------------------------------------|
//! | `max_len` | Max length of the string (in chars, not bytes) | `TooLong` | `max_len = 255` |
//! | `min_len` | Min length of the string (in chars, not bytes) | `TooShort` | `min_len = 5` |
//! | `not_empty` | Rejects an empty string | `Empty` | `not_empty` |
//! | `regex` | Validates format with a regex. Requires `regex` feature. | `RegexMismatch` | `regex = "^[0-9]{7}$"` or `regex = ID_REGEX` |
//! | `with` | Custom validator. A function or closure that receives `&str` and returns `bool` | `Invalid` | `with = \|s: &str\| s.contains('@')` |
//! | Validator | Description | Error variant | Example |
//! |----------------|---------------------------------------------------------------------------------|-----------------|----------------------------------------------|
//! | `char_len_min` | Min length of the string (in chars, not bytes) | `TooShort` | `char_len_min = 5` |
//! | `char_len_max` | Max length of the string (in chars, not bytes) | `TooLong` | `char_len_max = 255` |
//! | `not_empty` | Rejects an empty string | `Empty` | `not_empty` |
//! | `regex` | Validates format with a regex. Requires `regex` feature. | `RegexMismatch` | `regex = "^[0-9]{7}$"` or `regex = ID_REGEX` |
//! | `with` | Custom validator. A function or closure that receives `&str` and returns `bool` | `Invalid` | `with = \|s: &str\| s.contains('@')` |
//!
//! #### Regex validation
//!
Expand Down Expand Up @@ -320,7 +320,7 @@
//! #[nutype(
//! new_unchecked
//! sanitize(trim)
//! validate(min_len = 8)
//! validate(char_len_min = 8)
//! )]
//! pub struct Name(String);
//!
Expand Down
8 changes: 4 additions & 4 deletions nutype_macros/src/string/gen/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,10 @@ fn gen_definition(error_type_name: &ErrorTypeName, validators: &[StringValidator
let error_variants: TokenStream = validators
.iter()
.map(|validator| match validator {
StringValidator::MaxLen(_len) => {
StringValidator::CharLenMax(_len) => {
quote!(TooLong,)
}
StringValidator::MinLen(_len) => {
StringValidator::CharLenMin(_len) => {
quote!(TooShort,)
}
StringValidator::NotEmpty => {
Expand All @@ -61,10 +61,10 @@ fn gen_impl_display_trait(
validators: &[StringValidator],
) -> TokenStream {
let match_arms = validators.iter().map(|validator| match validator {
StringValidator::MaxLen(_len) => quote! {
StringValidator::CharLenMax(_len) => quote! {
#error_type_name::TooLong => write!(f, "too long")
},
StringValidator::MinLen(_len) => quote! {
StringValidator::CharLenMin(_len) => quote! {
#error_type_name::TooShort => write!(f, "too short")
},
StringValidator::NotEmpty => quote! {
Expand Down
4 changes: 2 additions & 2 deletions nutype_macros/src/string/gen/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,15 +85,15 @@ impl GenerateNewtype for StringNewtype {
let validations: TokenStream = validators
.iter()
.map(|validator| match validator {
StringValidator::MaxLen(max_len) => {
StringValidator::CharLenMax(max_len) => {
requires_chars_count = true;
quote!(
if chars_count > #max_len {
return Err(#error_name::TooLong);
}
)
}
StringValidator::MinLen(min_len) => {
StringValidator::CharLenMin(min_len) => {
requires_chars_count = true;
quote!(
if chars_count < #min_len {
Expand Down
4 changes: 2 additions & 2 deletions nutype_macros/src/string/models.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ pub type SpannedStringValidator = SpannedItem<StringValidator>;
#[derive(Debug, Kinded)]
#[kinded(display = "snake_case")]
pub enum StringValidator {
MinLen(usize),
MaxLen(usize),
CharLenMin(usize),
CharLenMax(usize),
NotEmpty,
Predicate(TypedCustomFunction),
#[cfg_attr(not(feature = "regex"), allow(dead_code))]
Expand Down
8 changes: 4 additions & 4 deletions nutype_macros/src/string/parse.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,19 +85,19 @@ impl Parse for SpannedStringValidator {
let (kind, ident) = parse_validator_kind(input)?;

match kind {
StringValidatorKind::MinLen => {
StringValidatorKind::CharLenMin => {
let _: Token![=] = input.parse()?;
let (min_len, span) = parse_number::<usize>(input)?;
Ok(SpannedStringValidator {
item: StringValidator::MinLen(min_len),
item: StringValidator::CharLenMin(min_len),
span,
})
}
StringValidatorKind::MaxLen => {
StringValidatorKind::CharLenMax => {
let _: Token![=] = input.parse()?;
let (max_len, span) = parse_number::<usize>(input)?;
Ok(SpannedStringValidator {
item: StringValidator::MaxLen(max_len),
item: StringValidator::CharLenMax(max_len),
span,
})
}
Expand Down
21 changes: 10 additions & 11 deletions nutype_macros/src/string/validate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,29 +43,28 @@ fn validate_validators(
format!("Duplicated validators `{kind}`.\nDon't worry, you still remain ingenious!")
})?;

// max_len VS min_len
// char_len_max VS char_len_min
//
let maybe_min_len = validators
let maybe_char_len_min = validators
.iter()
.flat_map(|v| match v.item {
StringValidator::MinLen(len) => Some((v.span, len)),
StringValidator::CharLenMin(len) => Some((v.span, len)),
_ => None,
})
.next();
let maybe_max_len = validators
let maybe_char_len_max = validators
.iter()
.flat_map(|v| match v.item {
StringValidator::MaxLen(len) => Some((v.span, len)),
StringValidator::CharLenMax(len) => Some((v.span, len)),
_ => None,
})
.next();
if let (Some((_min_len_span, min_len)), Some((max_len_span, max_len))) =
(maybe_min_len, maybe_max_len)
if let (Some((_, char_len_min)), Some((char_len_max_span, char_len_max))) =
(maybe_char_len_min, maybe_char_len_max)
{
if min_len > max_len {
let msg = "min_len cannot be greater than max_len.\nDon't you find this obvious?";
let span = max_len_span;
let err = syn::Error::new(span, msg);
if char_len_min > char_len_max {
let msg = "`char_len_min` cannot be greater than `char_len_max`.\nDon't you find this obvious?";
let err = syn::Error::new(char_len_max_span, msg);
return Err(err);
}
}
Expand Down
18 changes: 9 additions & 9 deletions test_suite/tests/string.rs
Original file line number Diff line number Diff line change
Expand Up @@ -91,9 +91,9 @@ mod validators {
use super::*;

#[test]
fn test_max_len() {
fn test_char_len_max() {
#[nutype(
validate(max_len = 5),
validate(char_len_max = 5),
derive(TryFrom, Debug, Clone, PartialEq, PartialOrd, FromStr, AsRef)
)]
pub struct Name(String);
Expand All @@ -106,8 +106,8 @@ mod validators {
}

#[test]
fn test_min_len() {
#[nutype(validate(min_len = 6), derive(Debug, PartialEq))]
fn test_char_len_min() {
#[nutype(validate(char_len_min = 6), derive(Debug, PartialEq))]
pub struct Name(String);

assert_eq!(Name::new("Anton"), Err(NameError::TooShort));
Expand All @@ -129,7 +129,7 @@ mod validators {

#[test]
fn test_many_validators() {
#[nutype(validate(min_len = 3, max_len = 6), derive(Debug, PartialEq))]
#[nutype(validate(char_len_min = 3, char_len_max = 6), derive(Debug, PartialEq))]
pub struct Name(String);

assert_eq!(Name::new("Jo"), Err(NameError::TooShort));
Expand Down Expand Up @@ -228,7 +228,7 @@ mod complex {
/// goes here.
#[nutype(
sanitize(trim, with = |s| s.to_uppercase()),
validate(not_empty, max_len = 6),
validate(not_empty, char_len_max = 6),
derive(Debug, PartialEq)
)]
pub struct Name(String);
Expand Down Expand Up @@ -414,7 +414,7 @@ mod derives {

#[test]
fn test_default_with_validation_when_valid() {
#[nutype(validate(min_len = 5), default = "Anonymous", derive(Default))]
#[nutype(validate(char_len_min = 5), default = "Anonymous", derive(Default))]

Check warning on line 417 in test_suite/tests/string.rs

View workflow job for this annotation

GitHub Actions / Unit Tests

cannot test inner items

Check warning on line 417 in test_suite/tests/string.rs

View workflow job for this annotation

GitHub Actions / Unit Tests

cannot test inner items

Check warning on line 417 in test_suite/tests/string.rs

View workflow job for this annotation

GitHub Actions / Unit Tests

cannot test inner items

Check warning on line 417 in test_suite/tests/string.rs

View workflow job for this annotation

GitHub Actions / Unit Tests

cannot test inner items

Check warning on line 417 in test_suite/tests/string.rs

View workflow job for this annotation

GitHub Actions / Unit Tests

cannot test inner items
pub struct Name(String);

assert_eq!(Name::default().into_inner(), "Anonymous");
Expand All @@ -423,7 +423,7 @@ mod derives {
#[test]
#[should_panic(expected = "Default value for type Name is invalid")]
fn test_default_with_validation_when_invalid() {
#[nutype(validate(min_len = 5), default = "Nope", derive(Default))]
#[nutype(validate(char_len_min = 5), default = "Nope", derive(Default))]

Check warning on line 426 in test_suite/tests/string.rs

View workflow job for this annotation

GitHub Actions / Unit Tests

cannot test inner items

Check warning on line 426 in test_suite/tests/string.rs

View workflow job for this annotation

GitHub Actions / Unit Tests

cannot test inner items

Check warning on line 426 in test_suite/tests/string.rs

View workflow job for this annotation

GitHub Actions / Unit Tests

cannot test inner items

Check warning on line 426 in test_suite/tests/string.rs

View workflow job for this annotation

GitHub Actions / Unit Tests

cannot test inner items

Check warning on line 426 in test_suite/tests/string.rs

View workflow job for this annotation

GitHub Actions / Unit Tests

cannot test inner items
pub struct Name(String);

Name::default();
Expand Down Expand Up @@ -481,7 +481,7 @@ mod new_unchecked {

#[test]
fn test_new_unchecked() {
#[nutype(new_unchecked, sanitize(trim), validate(min_len = 8))]
#[nutype(new_unchecked, sanitize(trim), validate(char_len_min = 8))]
pub struct Name(String);

let name = unsafe { Name::new_unchecked(" boo ".to_string()) };
Expand Down
2 changes: 1 addition & 1 deletion test_suite/tests/ui/common/attribute_with_wrong_case.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use nutype::nutype;

#[nutype(validate(maxLen = 255))]
#[nutype(validate(charLenMax = 255))]
pub struct Name(String);

fn main () {}
6 changes: 3 additions & 3 deletions test_suite/tests/ui/common/attribute_with_wrong_case.stderr
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
error: Unknown validator `maxLen`. Did you mean `max_len`?
error: Unknown validator `charLenMax`. Did you mean `char_len_max`?
--> tests/ui/common/attribute_with_wrong_case.rs:3:19
|
3 | #[nutype(validate(maxLen = 255))]
| ^^^^^^
3 | #[nutype(validate(charLenMax = 255))]
| ^^^^^^^^^^
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use nutype::nutype;

#[nutype(validate(min_len = 127, max_len = 63))]
#[nutype(validate(char_len_min = 127, char_len_max = 63))]
pub struct Email(String);

fn main () {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
error: `char_len_min` cannot be greater than `char_len_max`.
Don't you find this obvious?
--> tests/ui/string/validate/char_len_min_vs_char_len_max.rs:3:54
|
3 | #[nutype(validate(char_len_min = 127, char_len_max = 63))]
| ^^
2 changes: 1 addition & 1 deletion test_suite/tests/ui/string/validate/duplicated.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use nutype::nutype;

#[nutype(validate(min_len = 5, max_len = 255, min_len = 6))]
#[nutype(validate(char_len_min = 5, char_len_max = 255, char_len_min = 6))]
pub struct Email(String);

fn main () {}
8 changes: 4 additions & 4 deletions test_suite/tests/ui/string/validate/duplicated.stderr
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
error: Duplicated validators `min_len`.
error: Duplicated validators `char_len_min`.
Don't worry, you still remain ingenious!
--> tests/ui/string/validate/duplicated.rs:3:57
--> tests/ui/string/validate/duplicated.rs:3:72
|
3 | #[nutype(validate(min_len = 5, max_len = 255, min_len = 6))]
| ^
3 | #[nutype(validate(char_len_min = 5, char_len_max = 255, char_len_min = 6))]
| ^
6 changes: 0 additions & 6 deletions test_suite/tests/ui/string/validate/min_len_vs_max_len.stderr

This file was deleted.

2 changes: 1 addition & 1 deletion test_suite/tests/ui/string/validate/unknown.stderr
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
error: Unknown validator `unique`.
Possible values are `min_len`, `max_len`, `not_empty`, `predicate`, `regex`.
Possible values are `char_len_min`, `char_len_max`, `not_empty`, `predicate`, `regex`.
--> tests/ui/string/validate/unknown.rs:3:19
|
3 | #[nutype(validate(unique))]
Expand Down

0 comments on commit 2573a81

Please sign in to comment.