From dab791779febc9d78c050e3f35b3be372592c2ee Mon Sep 17 00:00:00 2001 From: Serhii Potapov Date: Sat, 1 Jun 2024 00:28:41 +0200 Subject: [PATCH] Add an example with a newtype with generics --- CHANGELOG.md | 5 ++ Cargo.lock | 7 +++ Cargo.toml | 2 +- examples/any_generics/Cargo.toml | 9 +++ examples/any_generics/src/main.rs | 30 +++++++++ test_suite/tests/any.rs | 101 ++++++++++++++++++++++++++++++ 6 files changed, 153 insertions(+), 1 deletion(-) create mode 100644 examples/any_generics/Cargo.toml create mode 100644 examples/any_generics/src/main.rs diff --git a/CHANGELOG.md b/CHANGELOG.md index 19146e3..fa67e29 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,8 @@ +### v0.x.x - 2024-xx-xx + +* Support newtypes with generics + + ### v0.4.2 - 2024-04-07 * Support `no_std` ( the dependency needs to be declared as `nutype = { default-features = false }` ) diff --git a/Cargo.lock b/Cargo.lock index 5dfd04c..bd7e639 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -20,6 +20,13 @@ dependencies = [ "nutype", ] +[[package]] +name = "any_generics" +version = "0.1.0" +dependencies = [ + "nutype", +] + [[package]] name = "arbitrary" version = "1.3.2" diff --git a/Cargo.toml b/Cargo.toml index 11ea57d..8a3b4bc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,5 +19,5 @@ members = [ "examples/serde_complex", "examples/string_bounded_len", "examples/string_regex_email", - "examples/string_arbitrary", + "examples/string_arbitrary", "examples/any_generics", ] diff --git a/examples/any_generics/Cargo.toml b/examples/any_generics/Cargo.toml new file mode 100644 index 0000000..10a487c --- /dev/null +++ b/examples/any_generics/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "any_generics" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +nutype = { path = "../../nutype" } diff --git a/examples/any_generics/src/main.rs b/examples/any_generics/src/main.rs new file mode 100644 index 0000000..a73e816 --- /dev/null +++ b/examples/any_generics/src/main.rs @@ -0,0 +1,30 @@ +use nutype::nutype; +use std::borrow::Cow; + +#[nutype( + validate(predicate = |vec| !vec.is_empty()), + derive(Debug), +)] +struct NotEmpty(Vec); + +#[nutype( + derive(Debug), + validate(predicate = |s| s.len() > 3), +)] +struct Clarabelle<'b>(Cow<'b, str>); + +fn main() { + { + let v = NotEmpty::new(vec![1, 2, 3]).unwrap(); + assert_eq!(v.into_inner(), vec![1, 2, 3]); + } + { + let err = NotEmpty::::new(vec![]).unwrap_err(); + assert_eq!(err, NotEmptyError::PredicateViolated); + } + + { + let c1 = Clarabelle::new(Cow::Borrowed("Muu")).unwrap(); + assert_eq!(c1.into_inner(), Cow::Borrowed("Muu")); + } +} diff --git a/test_suite/tests/any.rs b/test_suite/tests/any.rs index c588ed9..38909d5 100644 --- a/test_suite/tests/any.rs +++ b/test_suite/tests/any.rs @@ -382,3 +382,104 @@ mod new_unchecked { assert_eq!(line_point.into_inner(), Point::new(3, 4)); } } + +#[cfg(test)] +mod with_generics { + use super::*; + + #[test] + fn test_generic_with_validate() { + #[nutype( + validate(predicate = |v| !v.is_empty()), + derive(Debug) + )] + struct NonEmptyVec(Vec); + + { + let vec = NonEmptyVec::new(vec![1, 2, 3]).unwrap(); + assert_eq!(vec.into_inner(), vec![1, 2, 3]); + } + + { + let vec = NonEmptyVec::new(vec![5]).unwrap(); + assert_eq!(vec.into_inner(), vec![5]); + } + + { + let vec: Vec = vec![]; + let err = NonEmptyVec::new(vec).unwrap_err(); + assert_eq!(err, NonEmptyVecError::PredicateViolated); + } + } + + #[test] + fn test_generic_with_sanitize() { + #[nutype( + sanitize(with = |mut v| { v.truncate(2); v }), + derive(Debug) + )] + struct UpToTwo(Vec); + + { + let vec = UpToTwo::new(vec![1, 2, 3]); + assert_eq!(vec.into_inner(), vec![1, 2]); + } + + { + let vec = UpToTwo::new(vec![5]); + assert_eq!(vec.into_inner(), vec![5]); + } + } + + #[test] + fn test_generic_with_sanitize_and_validate() { + #[nutype( + sanitize(with = |mut v| { v.truncate(2); v }), + validate(predicate = |v| !v.is_empty()), + derive(Debug) + )] + struct OneOrTwo(Vec); + + { + let vec = OneOrTwo::new(vec![1, 2, 3]).unwrap(); + assert_eq!(vec.into_inner(), vec![1, 2]); + } + + { + let vec = OneOrTwo::new(vec![5]).unwrap(); + assert_eq!(vec.into_inner(), vec![5]); + } + + { + let vec: Vec = vec![]; + let err = OneOrTwo::new(vec).unwrap_err(); + assert_eq!(err, OneOrTwoError::PredicateViolated); + } + } + + // TODO + // #[test] + // fn test_generic_with_boundaries_and_sanitize() { + // #[nutype( + // sanitize(with = |v| { v.sort(); v }), + // derive(Debug) + // )] + // struct SortedVec(Vec); + + // { + // let vec = NonEmptyVec::new(vec![1, 2, 3]).unwrap(); + // assert_eq!(vec.into_inner(), vec![1, 2, 3]); + // } + + // { + // let vec = NonEmptyVec::new(vec![5]).unwrap(); + // assert_eq!(vec.into_inner(), vec![5]); + // } + + // { + // let vec: Vec = vec![]; + // let err = NonEmptyVec::new(vec).unwrap_err(); + // assert_eq!(err, NonEmptyVecError::PredicateViolated); + // } + // } +}