diff --git a/README.md b/README.md index 027f44c..332207c 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,7 @@ Nutype is a proc macro that allows adding extra constraints like _sanitization_ * [Quick start](#quick-start) -* [Inner types](#inner-types) ([String](#string) | [Integer](#integer) | [Float](#float) | [Other](#other-inner-types)) +* [Inner types](#inner-types) ([String](#string) | [Integer](#integer) | [Float](#float) | [Other](#other-inner-types-and-generics)) * [Custom](#custom-sanitizers) ([sanitizers](#custom-sanitizers) | [validators](#custom-validators)) * [Recipes](#recipes) * [Breaking constraints with new_unchecked](#breaking-constraints-with-new_unchecked) @@ -212,55 +212,42 @@ This can be done applying by `finite` validation. For example: struct Size(f64); ``` -## Other inner types +## Other inner types and generics For any other type it is possible to define custom sanitizers with `with` and custom validations with `predicate`: -```rs +```rust use nutype::nutype; #[nutype( - derive(Debug, PartialEq, Deref, AsRef), + derive(Debug, PartialEq, AsRef, Deref), sanitize(with = |mut guests| { guests.sort(); guests }), validate(predicate = |guests| !guests.is_empty() ), )] pub struct GuestList(Vec); +``` -// Empty list is not allowed -assert_eq!( - GuestList::try_new(vec![]), - Err(GuestListError::PredicateViolated) -); +It's also possible to use generics: -// Create the list of our guests -let guest_list = GuestList::try_new(vec![ - "Seneca".to_string(), - "Marcus Aurelius".to_string(), - "Socrates".to_string(), - "Epictetus".to_string(), -]).unwrap(); +```rust +#[nutype( + sanitize(with = |mut v| { v.sort(); v }), + validate(predicate = |vec| !vec.is_empty()), + derive(Debug, PartialEq, AsRef, Deref), +)] +struct SortedNotEmptyVec(Vec); -// The list is sorted (thanks to sanitize) -assert_eq!( - guest_list.as_ref(), - &[ - "Epictetus".to_string(), - "Marcus Aurelius".to_string(), - "Seneca".to_string(), - "Socrates".to_string(), - ] -); +let wise_friends = SortedNotEmptyVec::try_new(vec!["Seneca", "Zeno", "Plato"]).unwrap(); +assert_eq!(wise_friends.as_ref(), &["Plato", "Seneca", "Zeno"]); +assert_eq!(wise_friends.len(), 3); -// Since GuestList derives Deref, we can use methods from `Vec` -// due to deref coercion (if it's a good idea or not, it's left up to you to decide!). -assert_eq!(guest_list.len(), 4); +let numbers = SortedNotEmptyVec::try_new(vec![4, 2, 7, 1]).unwrap(); +assert_eq!(numbers.as_ref(), &[1, 2, 4, 7]); +assert_eq!(numbers.len(), 4); +``` -for guest in guest_list.iter() { - println!("{guest}"); -} -``` ## Custom sanitizers diff --git a/dummy/src/main.rs b/dummy/src/main.rs index 912d9cc..0a5a231 100644 --- a/dummy/src/main.rs +++ b/dummy/src/main.rs @@ -14,14 +14,11 @@ fn main() { Err(SortedNotEmptyVecError::PredicateViolated) ); - let wise_friends = - SortedNotEmptyVec::try_new(vec!["Seneca", "Zeno", "Socrates", "Epictetus", "Plato"]) - .unwrap(); + let wise_friends = SortedNotEmptyVec::try_new(vec!["Seneca", "Zeno", "Plato"]).unwrap(); + assert_eq!(wise_friends.as_ref(), &["Plato", "Seneca", "Zeno"]); + assert_eq!(wise_friends.len(), 3); - assert_eq!( - wise_friends.as_ref(), - &["Epictetus", "Plato", "Seneca", "Socrates", "Zeno"] - ); - - assert_eq!(wise_friends.len(), 5); + let numbers = SortedNotEmptyVec::try_new(vec![4, 2, 7, 1]).unwrap(); + assert_eq!(numbers.as_ref(), &[1, 2, 4, 7]); + assert_eq!(numbers.len(), 4); } diff --git a/nutype/src/lib.rs b/nutype/src/lib.rs index 6876791..37ad674 100644 --- a/nutype/src/lib.rs +++ b/nutype/src/lib.rs @@ -243,7 +243,7 @@ //! struct Size(f64); //! ``` //! -//! ## Other inner types +//! ## Other inner types and generics //! //! For any other type it is possible to define custom sanitizers with `with` and custom //! validations with `predicate`: @@ -252,45 +252,33 @@ //! use nutype::nutype; //! //! #[nutype( -//! derive(Debug, PartialEq, Deref, AsRef), +//! derive(Debug, PartialEq, AsRef, Deref), //! sanitize(with = |mut guests| { guests.sort(); guests }), //! validate(predicate = |guests| !guests.is_empty() ), //! )] //! pub struct GuestList(Vec); //! -//! // Empty list is not allowed -//! assert_eq!( -//! GuestList::try_new(vec![]), -//! Err(GuestListError::PredicateViolated) -//! ); +//! ``` //! -//! // Create the list of our guests -//! let guest_list = GuestList::try_new(vec![ -//! "Seneca".to_string(), -//! "Marcus Aurelius".to_string(), -//! "Socrates".to_string(), -//! "Epictetus".to_string(), -//! ]).unwrap(); +//! It's also possible to use generics: //! -//! // The list is sorted (thanks to sanitize) -//! assert_eq!( -//! guest_list.as_ref(), -//! &[ -//! "Epictetus".to_string(), -//! "Marcus Aurelius".to_string(), -//! "Seneca".to_string(), -//! "Socrates".to_string(), -//! ] -//! ); +//! ``` +//! use nutype::nutype; //! -//! // Since GuestList derives Deref, we can use methods from `Vec` -//! // due to deref coercion (if it's a good idea or not, it's left up to you to decide!). -//! assert_eq!(guest_list.len(), 4); +//! #[nutype( +//! sanitize(with = |mut v| { v.sort(); v }), +//! validate(predicate = |vec| !vec.is_empty()), +//! derive(Debug, PartialEq, AsRef, Deref), +//! )] +//! struct SortedNotEmptyVec(Vec); //! -//! for guest in guest_list.iter() { -//! println!("{guest}"); -//! } +//! let wise_friends = SortedNotEmptyVec::try_new(vec!["Seneca", "Zeno", "Plato"]).unwrap(); +//! assert_eq!(wise_friends.as_ref(), &["Plato", "Seneca", "Zeno"]); +//! assert_eq!(wise_friends.len(), 3); //! +//! let numbers = SortedNotEmptyVec::try_new(vec![4, 2, 7, 1]).unwrap(); +//! assert_eq!(numbers.as_ref(), &[1, 2, 4, 7]); +//! assert_eq!(numbers.len(), 4); //! ``` //! //! ## Custom sanitizers