summaryrefslogtreecommitdiffstats
path: root/vendor/derive-new
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 12:02:58 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 12:02:58 +0000
commit698f8c2f01ea549d77d7dc3338a12e04c11057b9 (patch)
tree173a775858bd501c378080a10dca74132f05bc50 /vendor/derive-new
parentInitial commit. (diff)
downloadrustc-698f8c2f01ea549d77d7dc3338a12e04c11057b9.tar.xz
rustc-698f8c2f01ea549d77d7dc3338a12e04c11057b9.zip
Adding upstream version 1.64.0+dfsg1.upstream/1.64.0+dfsg1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'vendor/derive-new')
-rw-r--r--vendor/derive-new/.cargo-checksum.json1
-rw-r--r--vendor/derive-new/Cargo.toml34
-rw-r--r--vendor/derive-new/README.md92
-rw-r--r--vendor/derive-new/src/lib.rs453
-rw-r--r--vendor/derive-new/tests/test.rs361
5 files changed, 941 insertions, 0 deletions
diff --git a/vendor/derive-new/.cargo-checksum.json b/vendor/derive-new/.cargo-checksum.json
new file mode 100644
index 000000000..6cb4b7752
--- /dev/null
+++ b/vendor/derive-new/.cargo-checksum.json
@@ -0,0 +1 @@
+{"files":{"Cargo.toml":"3e95715ee0f542470854db178544d4910da0081ab5c5244d019a8c916bfa2067","README.md":"e3c5c183cca06c9c419eb69a42acb742d4e95b220eee3dd746b7329249f2c9b2","src/lib.rs":"0ab7b53e32c371c594b937b216035fd80334b7e20dd989ae124a65895fd6cef5","tests/test.rs":"99d471d22ebe68c55e052bf2f6236fbc966e9991d5738b85254cab9f2f5bd9f3"},"package":"71f31892cd5c62e414316f2963c5689242c43d8e7bbcaaeca97e5e28c95d91d9"} \ No newline at end of file
diff --git a/vendor/derive-new/Cargo.toml b/vendor/derive-new/Cargo.toml
new file mode 100644
index 000000000..1542b4234
--- /dev/null
+++ b/vendor/derive-new/Cargo.toml
@@ -0,0 +1,34 @@
+# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
+#
+# When uploading crates to the registry Cargo will automatically
+# "normalize" Cargo.toml files for maximal compatibility
+# with all versions of Cargo and also rewrite `path` dependencies
+# to registry (e.g., crates.io) dependencies
+#
+# If you believe there's an error in this file please file an
+# issue against the rust-lang/cargo repository. If you're
+# editing this file be aware that the upstream Cargo.toml
+# will likely look very different (and much more reasonable)
+
+[package]
+name = "derive-new"
+version = "0.5.8"
+authors = ["Nick Cameron <ncameron@mozilla.com>"]
+description = "`#[derive(new)]` implements simple constructor functions for structs and enums."
+license = "MIT"
+repository = "https://github.com/nrc/derive-new"
+
+[lib]
+proc-macro = true
+[dependencies.proc-macro2]
+version = "1"
+
+[dependencies.quote]
+version = "1"
+
+[dependencies.syn]
+version = "1"
+
+[features]
+default = ["std"]
+std = []
diff --git a/vendor/derive-new/README.md b/vendor/derive-new/README.md
new file mode 100644
index 000000000..3568343c7
--- /dev/null
+++ b/vendor/derive-new/README.md
@@ -0,0 +1,92 @@
+# A custom derive implementation for `#[derive(new)]`
+
+A `derive(new)` attribute creates a `new` constructor function for the annotated
+type. That function takes an argument for each field in the type giving a
+trivial constructor. This is useful since as your type evolves you can make the
+constructor non-trivial (and add or remove fields) without changing client code
+(i.e., without breaking backwards compatibility). It is also the most succinct
+way to initialise a struct or an enum.
+
+Implementation uses macros 1.1 custom derive (which works in stable Rust from
+1.15 onwards).
+
+`#[no_std]` is fully supported if you switch off the default feature `"std"`.
+
+## Examples
+
+Cargo.toml:
+
+```toml
+[dependencies]
+derive-new = "0.5"
+```
+
+Include the macro:
+
+```rust
+#[macro_use]
+extern crate derive_new;
+```
+
+Generating constructor for a simple struct:
+
+```rust
+#[derive(new)]
+struct Bar {
+ a: i32,
+ b: String,
+}
+
+let _ = Bar::new(42, "Hello".to_owned());
+```
+
+Default values can be specified either via `#[new(default)]` attribute which removes
+the argument from the constructor and populates the field with `Default::default()`,
+or via `#[new(value = "..")]` which initializes the field with a given expression:
+
+```rust
+#[derive(new)]
+struct Foo {
+ x: bool,
+ #[new(value = "42")]
+ y: i32,
+ #[new(default)]
+ z: Vec<String>,
+}
+
+let _ = Foo::new(true);
+```
+
+Generic types are supported; in particular, `PhantomData<T>` fields will be not
+included in the argument list and will be intialized automatically:
+
+```rust
+use std::marker::PhantomData;
+
+#[derive(new)]
+struct Generic<'a, T: Default, P> {
+ x: &'a str,
+ y: PhantomData<P>,
+ #[new(default)]
+ z: T,
+}
+
+let _ = Generic::<i32, u8>::new("Hello");
+```
+
+For enums, one constructor method is generated for each variant, with the type
+name being converted to snake case; otherwise, all features supported for
+structs work for enum variants as well:
+
+```rust
+#[derive(new)]
+struct Enum {
+ FirstVariant,
+ SecondVariant(bool, #[new(default)] u8),
+ ThirdVariant { x: i32, #[new(value = "vec![1]")] y: Vec<u8> }
+}
+
+let _ = Enum::new_first_variant();
+let _ = Enum::new_second_variant(true);
+let _ = Enum::new_third_variant(42);
+```
diff --git a/vendor/derive-new/src/lib.rs b/vendor/derive-new/src/lib.rs
new file mode 100644
index 000000000..9fb1fb0bf
--- /dev/null
+++ b/vendor/derive-new/src/lib.rs
@@ -0,0 +1,453 @@
+//!# A custom derive implementation for `#[derive(new)]`
+//!
+//!A `derive(new)` attribute creates a `new` constructor function for the annotated
+//!type. That function takes an argument for each field in the type giving a
+//!trivial constructor. This is useful since as your type evolves you can make the
+//!constructor non-trivial (and add or remove fields) without changing client code
+//!(i.e., without breaking backwards compatibility). It is also the most succinct
+//!way to initialise a struct or an enum.
+//!
+//!Implementation uses macros 1.1 custom derive (which works in stable Rust from
+//!1.15 onwards).
+//!
+//!## Examples
+//!
+//!Cargo.toml:
+//!
+//!```toml
+//![dependencies]
+//!derive-new = "0.5"
+//!```
+//!
+//!Include the macro:
+//!
+//!```rust
+//!#[macro_use]
+//!extern crate derive_new;
+//!fn main() {}
+//!```
+//!
+//!Generating constructor for a simple struct:
+//!
+//!```rust
+//!#[macro_use]
+//!extern crate derive_new;
+//!#[derive(new)]
+//!struct Bar {
+//! a: i32,
+//! b: String,
+//!}
+//!
+//!fn main() {
+//! let _ = Bar::new(42, "Hello".to_owned());
+//!}
+//!```
+//!
+//!Default values can be specified either via `#[new(default)]` attribute which removes
+//!the argument from the constructor and populates the field with `Default::default()`,
+//!or via `#[new(value = "..")]` which initializes the field with a given expression:
+//!
+//!```rust
+//!#[macro_use]
+//!extern crate derive_new;
+//!#[derive(new)]
+//!struct Foo {
+//! x: bool,
+//! #[new(value = "42")]
+//! y: i32,
+//! #[new(default)]
+//! z: Vec<String>,
+//!}
+//!
+//!fn main() {
+//! let _ = Foo::new(true);
+//!}
+//!```
+//!
+//!Generic types are supported; in particular, `PhantomData<T>` fields will be not
+//!included in the argument list and will be intialized automatically:
+//!
+//!```rust
+//!#[macro_use]
+//!extern crate derive_new;
+//!use std::marker::PhantomData;
+//!
+//!#[derive(new)]
+//!struct Generic<'a, T: Default, P> {
+//! x: &'a str,
+//! y: PhantomData<P>,
+//! #[new(default)]
+//! z: T,
+//!}
+//!
+//!fn main() {
+//! let _ = Generic::<i32, u8>::new("Hello");
+//!}
+//!```
+//!
+//!For enums, one constructor method is generated for each variant, with the type
+//!name being converted to snake case; otherwise, all features supported for
+//!structs work for enum variants as well:
+//!
+//!```rust
+//!#[macro_use]
+//!extern crate derive_new;
+//!#[derive(new)]
+//!enum Enum {
+//! FirstVariant,
+//! SecondVariant(bool, #[new(default)] u8),
+//! ThirdVariant { x: i32, #[new(value = "vec![1]")] y: Vec<u8> }
+//!}
+//!
+//!fn main() {
+//! let _ = Enum::new_first_variant();
+//! let _ = Enum::new_second_variant(true);
+//! let _ = Enum::new_third_variant(42);
+//!}
+//!```
+#![crate_type = "proc-macro"]
+#![recursion_limit = "192"]
+
+extern crate proc_macro;
+extern crate proc_macro2;
+#[macro_use]
+extern crate quote;
+extern crate syn;
+
+macro_rules! my_quote {
+ ($($t:tt)*) => (quote_spanned!(proc_macro2::Span::call_site() => $($t)*))
+}
+
+fn path_to_string(path: &syn::Path) -> String {
+ path.segments.iter().map(|s| s.ident.to_string()).collect::<Vec<String>>().join("::")
+}
+
+use proc_macro::TokenStream;
+use syn::Token;
+
+#[proc_macro_derive(new, attributes(new))]
+pub fn derive(input: TokenStream) -> TokenStream {
+ let ast: syn::DeriveInput = syn::parse(input).expect("Couldn't parse item");
+ let result = match ast.data {
+ syn::Data::Enum(ref e) => new_for_enum(&ast, e),
+ syn::Data::Struct(ref s) => new_for_struct(&ast, &s.fields, None),
+ syn::Data::Union(_) => panic!("doesn't work with unions yet"),
+ };
+ result.into()
+}
+
+fn new_for_struct(
+ ast: &syn::DeriveInput,
+ fields: &syn::Fields,
+ variant: Option<&syn::Ident>,
+) -> proc_macro2::TokenStream {
+ match *fields {
+ syn::Fields::Named(ref fields) => new_impl(&ast, Some(&fields.named), true, variant),
+ syn::Fields::Unit => new_impl(&ast, None, false, variant),
+ syn::Fields::Unnamed(ref fields) => new_impl(&ast, Some(&fields.unnamed), false, variant),
+ }
+}
+
+fn new_for_enum(ast: &syn::DeriveInput, data: &syn::DataEnum) -> proc_macro2::TokenStream {
+ if data.variants.is_empty() {
+ panic!("#[derive(new)] cannot be implemented for enums with zero variants");
+ }
+ let impls = data.variants.iter().map(|v| {
+ if v.discriminant.is_some() {
+ panic!("#[derive(new)] cannot be implemented for enums with discriminants");
+ }
+ new_for_struct(ast, &v.fields, Some(&v.ident))
+ });
+ my_quote!(#(#impls)*)
+}
+
+fn new_impl(
+ ast: &syn::DeriveInput,
+ fields: Option<&syn::punctuated::Punctuated<syn::Field, Token![,]>>,
+ named: bool,
+ variant: Option<&syn::Ident>,
+) -> proc_macro2::TokenStream {
+ let name = &ast.ident;
+ let unit = fields.is_none();
+ let empty = Default::default();
+ let fields: Vec<_> = fields
+ .unwrap_or(&empty)
+ .iter()
+ .enumerate()
+ .map(|(i, f)| FieldExt::new(f, i, named))
+ .collect();
+ let args = fields.iter().filter(|f| f.needs_arg()).map(|f| f.as_arg());
+ let inits = fields.iter().map(|f| f.as_init());
+ let inits = if unit {
+ my_quote!()
+ } else if named {
+ my_quote![{ #(#inits),* }]
+ } else {
+ my_quote![( #(#inits),* )]
+ };
+ let (impl_generics, ty_generics, where_clause) = ast.generics.split_for_impl();
+ let (mut new, qual, doc) = match variant {
+ None => (
+ syn::Ident::new("new", proc_macro2::Span::call_site()),
+ my_quote!(),
+ format!("Constructs a new `{}`.", name),
+ ),
+ Some(ref variant) => (
+ syn::Ident::new(
+ &format!("new_{}", to_snake_case(&variant.to_string())),
+ proc_macro2::Span::call_site(),
+ ),
+ my_quote!(::#variant),
+ format!("Constructs a new `{}::{}`.", name, variant),
+ ),
+ };
+ new.set_span(proc_macro2::Span::call_site());
+ let lint_attrs = collect_parent_lint_attrs(&ast.attrs);
+ let lint_attrs = my_quote![#(#lint_attrs),*];
+ my_quote! {
+ impl #impl_generics #name #ty_generics #where_clause {
+ #[doc = #doc]
+ #lint_attrs
+ pub fn #new(#(#args),*) -> Self {
+ #name #qual #inits
+ }
+ }
+ }
+}
+
+fn collect_parent_lint_attrs(attrs: &[syn::Attribute]) -> Vec<syn::Attribute> {
+ fn is_lint(item: &syn::Meta) -> bool {
+ if let syn::Meta::List(ref l) = *item {
+ let path = &l.path;
+ return path.is_ident("allow") || path.is_ident("deny") || path.is_ident("forbid") || path.is_ident("warn")
+ }
+ false
+ }
+
+ fn is_cfg_attr_lint(item: &syn::Meta) -> bool {
+ if let syn::Meta::List(ref l) = *item {
+ if l.path.is_ident("cfg_attr") && l.nested.len() == 2 {
+ if let syn::NestedMeta::Meta(ref item) = l.nested[1] {
+ return is_lint(item);
+ }
+ }
+ }
+ false
+ }
+
+ attrs
+ .iter()
+ .filter_map(|a| a.parse_meta().ok().map(|m| (m, a)))
+ .filter(|&(ref m, _)| is_lint(m) || is_cfg_attr_lint(m))
+ .map(|p| p.1)
+ .cloned()
+ .collect()
+}
+
+enum FieldAttr {
+ Default,
+ Value(proc_macro2::TokenStream),
+}
+
+impl FieldAttr {
+ pub fn as_tokens(&self) -> proc_macro2::TokenStream {
+ match *self {
+ FieldAttr::Default => {
+ if cfg!(feature = "std") {
+ my_quote!(::std::default::Default::default())
+ } else {
+ my_quote!(::core::default::Default::default())
+ }
+ }
+ FieldAttr::Value(ref s) => my_quote!(#s),
+ }
+ }
+
+ pub fn parse(attrs: &[syn::Attribute]) -> Option<FieldAttr> {
+ use syn::{AttrStyle, Meta, NestedMeta};
+
+ let mut result = None;
+ for attr in attrs.iter() {
+ match attr.style {
+ AttrStyle::Outer => {}
+ _ => continue,
+ }
+ let last_attr_path = attr
+ .path
+ .segments
+ .iter()
+ .last()
+ .expect("Expected at least one segment where #[segment[::segment*](..)]");
+ if (*last_attr_path).ident != "new" {
+ continue;
+ }
+ let meta = match attr.parse_meta() {
+ Ok(meta) => meta,
+ Err(_) => continue,
+ };
+ let list = match meta {
+ Meta::List(l) => l,
+ _ if meta.path().is_ident("new") => {
+ panic!("Invalid #[new] attribute, expected #[new(..)]")
+ }
+ _ => continue,
+ };
+ if result.is_some() {
+ panic!("Expected at most one #[new] attribute");
+ }
+ for item in list.nested.iter() {
+ match *item {
+ NestedMeta::Meta(Meta::Path(ref path)) => {
+ if path.is_ident("default") {
+ result = Some(FieldAttr::Default);
+ } else {
+ panic!("Invalid #[new] attribute: #[new({})]", path_to_string(&path));
+ }
+ }
+ NestedMeta::Meta(Meta::NameValue(ref kv)) => {
+ if let syn::Lit::Str(ref s) = kv.lit {
+ if kv.path.is_ident("value") {
+ let tokens = s.value().parse().ok().expect(&format!(
+ "Invalid expression in #[new]: `{}`",
+ s.value()
+ ));
+ result = Some(FieldAttr::Value(tokens));
+ } else {
+ panic!("Invalid #[new] attribute: #[new({} = ..)]", path_to_string(&kv.path));
+ }
+ } else {
+ panic!("Non-string literal value in #[new] attribute");
+ }
+ }
+ NestedMeta::Meta(Meta::List(ref l)) => {
+ panic!("Invalid #[new] attribute: #[new({}(..))]", path_to_string(&l.path));
+ }
+ NestedMeta::Lit(_) => {
+ panic!("Invalid #[new] attribute: literal value in #[new(..)]");
+ }
+ }
+ }
+ }
+ result
+ }
+}
+
+struct FieldExt<'a> {
+ ty: &'a syn::Type,
+ attr: Option<FieldAttr>,
+ ident: syn::Ident,
+ named: bool,
+}
+
+impl<'a> FieldExt<'a> {
+ pub fn new(field: &'a syn::Field, idx: usize, named: bool) -> FieldExt<'a> {
+ FieldExt {
+ ty: &field.ty,
+ attr: FieldAttr::parse(&field.attrs),
+ ident: if named {
+ field.ident.clone().unwrap()
+ } else {
+ syn::Ident::new(&format!("f{}", idx), proc_macro2::Span::call_site())
+ },
+ named: named,
+ }
+ }
+
+ pub fn has_attr(&self) -> bool {
+ self.attr.is_some()
+ }
+
+ pub fn is_phantom_data(&self) -> bool {
+ match *self.ty {
+ syn::Type::Path(syn::TypePath {
+ qself: None,
+ ref path,
+ }) => path
+ .segments
+ .last()
+ .map(|x| x.ident == "PhantomData")
+ .unwrap_or(false),
+ _ => false,
+ }
+ }
+
+ pub fn needs_arg(&self) -> bool {
+ !self.has_attr() && !self.is_phantom_data()
+ }
+
+ pub fn as_arg(&self) -> proc_macro2::TokenStream {
+ let f_name = &self.ident;
+ let ty = &self.ty;
+ my_quote!(#f_name: #ty)
+ }
+
+ pub fn as_init(&self) -> proc_macro2::TokenStream {
+ let f_name = &self.ident;
+ let init = if self.is_phantom_data() {
+ if cfg!(feature = "std") {
+ my_quote!(::std::marker::PhantomData)
+ } else {
+ my_quote!(::core::marker::PhantomData)
+ }
+ } else {
+ match self.attr {
+ None => my_quote!(#f_name),
+ Some(ref attr) => attr.as_tokens(),
+ }
+ };
+ if self.named {
+ my_quote!(#f_name: #init)
+ } else {
+ my_quote!(#init)
+ }
+ }
+}
+
+fn to_snake_case(s: &str) -> String {
+ let (ch, next, mut acc): (Option<char>, Option<char>, String) =
+ s.chars()
+ .fold((None, None, String::new()), |(prev, ch, mut acc), next| {
+ if let Some(ch) = ch {
+ if let Some(prev) = prev {
+ if ch.is_uppercase() {
+ if prev.is_lowercase()
+ || prev.is_numeric()
+ || (prev.is_uppercase() && next.is_lowercase())
+ {
+ acc.push('_');
+ }
+ }
+ }
+ acc.extend(ch.to_lowercase());
+ }
+ (ch, Some(next), acc)
+ });
+ if let Some(next) = next {
+ if let Some(ch) = ch {
+ if (ch.is_lowercase() || ch.is_numeric()) && next.is_uppercase() {
+ acc.push('_');
+ }
+ }
+ acc.extend(next.to_lowercase());
+ }
+ acc
+}
+
+#[test]
+fn test_to_snake_case() {
+ assert_eq!(to_snake_case(""), "");
+ assert_eq!(to_snake_case("a"), "a");
+ assert_eq!(to_snake_case("B"), "b");
+ assert_eq!(to_snake_case("BC"), "bc");
+ assert_eq!(to_snake_case("Bc"), "bc");
+ assert_eq!(to_snake_case("bC"), "b_c");
+ assert_eq!(to_snake_case("Fred"), "fred");
+ assert_eq!(to_snake_case("CARGO"), "cargo");
+ assert_eq!(to_snake_case("_Hello"), "_hello");
+ assert_eq!(to_snake_case("QuxBaz"), "qux_baz");
+ assert_eq!(to_snake_case("FreeBSD"), "free_bsd");
+ assert_eq!(to_snake_case("specialK"), "special_k");
+ assert_eq!(to_snake_case("hello1World"), "hello1_world");
+ assert_eq!(to_snake_case("Keep_underscore"), "keep_underscore");
+ assert_eq!(to_snake_case("ThisISNotADrill"), "this_is_not_a_drill");
+}
diff --git a/vendor/derive-new/tests/test.rs b/vendor/derive-new/tests/test.rs
new file mode 100644
index 000000000..36f06e6ff
--- /dev/null
+++ b/vendor/derive-new/tests/test.rs
@@ -0,0 +1,361 @@
+#![deny(non_snake_case)]
+
+#[macro_use]
+extern crate derive_new;
+
+use std::default::Default;
+use std::fmt::Debug;
+use std::marker::PhantomData;
+
+/// A struct with no fields.
+#[derive(new, PartialEq, Debug)]
+pub struct Foo {}
+
+#[test]
+fn test_empty_struct() {
+ let x = Foo::new();
+ assert_eq!(x, Foo {});
+}
+
+/// A unit struct.
+#[derive(new, PartialEq, Debug)]
+pub struct Baz;
+
+#[test]
+fn test_unit_struct() {
+ let x = Baz::new();
+ assert_eq!(x, Baz);
+}
+
+/// A struct with fields.
+#[derive(new, PartialEq, Debug)]
+pub struct Bar {
+ pub x: i32,
+ pub y: String,
+}
+
+#[test]
+fn test_simple_struct() {
+ let x = Bar::new(42, "Hello".to_owned());
+ assert_eq!(
+ x,
+ Bar {
+ x: 42,
+ y: "Hello".to_owned()
+ }
+ );
+}
+
+/// A struct with a lifetime parameter.
+#[derive(new, PartialEq, Debug)]
+pub struct Intersection<'scene> {
+ pub object: &'scene Bar,
+ pub normal: Foo,
+ pub point: Foo,
+ pub t: f64,
+}
+
+#[test]
+fn test_struct_with_lifetime() {
+ let b = Bar::new(42, "Hello".to_owned());
+ let x = Intersection::new(&b, Foo::new(), Foo::new(), 42.0);
+ assert_eq!(
+ x,
+ Intersection {
+ object: &b,
+ normal: Foo {},
+ point: Foo {},
+ t: 42.0
+ }
+ );
+}
+
+/// A struct with generics and bounds.
+#[derive(new, PartialEq, Debug)]
+pub struct Qux<T: Debug + PartialEq, U: Debug + PartialEq> {
+ pub f1: T,
+ pub f2: Vec<U>,
+ pub f3: i32,
+}
+
+#[test]
+fn test_struct_with_bounds() {
+ let x = Qux::new("Hello!", Vec::<String>::new(), 42);
+ assert_eq!(
+ x,
+ Qux {
+ f1: "Hello!",
+ f2: vec![],
+ f3: 42
+ }
+ );
+
+ let x: Qux<&'static str, String> = Qux::new("Hello!", Vec::<String>::new(), 42);
+ assert_eq!(
+ x,
+ Qux {
+ f1: "Hello!",
+ f2: vec![],
+ f3: 42
+ }
+ );
+
+ let x = Qux::<_, String>::new("Hello!", vec![], 42);
+ assert_eq!(
+ x,
+ Qux {
+ f1: "Hello!",
+ f2: vec![],
+ f3: 42
+ }
+ );
+}
+
+/// A struct with a lifetime parameter, generics and bounds.
+#[derive(new, PartialEq, Debug)]
+pub struct FooBar<'a, T, U>
+where
+ T: 'a + PartialEq + Debug,
+ U: Sized + Send + 'a + PartialEq + Debug,
+{
+ pub f1: Box<T>,
+ pub f2: Vec<&'a U>,
+ pub f3: i32,
+}
+
+#[test]
+fn test_struct_lifetime_bounds() {
+ let a = 42;
+ let x = FooBar::new(Box::new("Hello".to_owned()), vec![&a], 42);
+ assert_eq!(
+ x,
+ FooBar {
+ f1: Box::new("Hello".to_owned()),
+ f2: vec![&a],
+ f3: 42
+ }
+ );
+}
+
+/// A tuple struct.
+#[derive(new, PartialEq, Debug)]
+pub struct Tuple(pub i32, pub i32);
+
+#[test]
+fn test_simple_tuple_struct() {
+ let x = Tuple::new(5, 6);
+ assert_eq!(x, Tuple(5, 6));
+}
+
+/// A tuple struct with a lifetime parameter.
+#[derive(new, PartialEq, Debug)]
+pub struct TupleWithLifetime<'a>(pub &'a str);
+
+#[test]
+fn test_tuple_struct_lifetime() {
+ let x = TupleWithLifetime::new("Hello");
+ assert_eq!(x, TupleWithLifetime("Hello"));
+}
+
+/// A struct where fields have default values.
+#[derive(new, PartialEq, Debug)]
+pub struct Waldo<T: PartialEq + Debug + Default> {
+ #[new(default)]
+ pub x: i32,
+ pub y: u8,
+ #[new(default)]
+ pub z: T,
+}
+
+#[test]
+fn test_struct_with_defaults() {
+ let x = Waldo::<Vec<String>>::new(42);
+ assert_eq!(
+ x,
+ Waldo {
+ x: 0,
+ y: 42,
+ z: vec![]
+ }
+ );
+}
+
+/// A struct where fields have explicitly provided defaults.
+#[derive(new, PartialEq, Debug)]
+pub struct Fred {
+ #[new(value = "1 + 2")]
+ pub x: i32,
+ pub y: String,
+ #[new(value = "vec![-42, 42]")]
+ pub z: Vec<i8>,
+}
+
+#[test]
+fn test_struct_with_values() {
+ let x = Fred::new("Fred".to_owned());
+ assert_eq!(
+ x,
+ Fred {
+ x: 3,
+ y: "Fred".to_owned(),
+ z: vec![-42, 42]
+ }
+ );
+}
+
+/// A struct with defaults and specified values.
+#[derive(new, PartialEq, Debug)]
+pub struct Thud {
+ #[new(value = r#""Thud".to_owned()"#)]
+ pub x: String,
+ #[new(default)]
+ pub y: String,
+}
+
+#[test]
+fn test_struct_mixed_defaults() {
+ let x = Thud::new();
+ assert_eq!(
+ x,
+ Thud {
+ x: "Thud".to_owned(),
+ y: String::new()
+ }
+ );
+}
+
+/// A generic struct with PhantomData member.
+#[derive(new, PartialEq, Debug)]
+pub struct Bob<T: PartialEq + Debug> {
+ pub a: i32,
+ pub b: PhantomData<T>,
+}
+
+#[test]
+fn test_struct_phantom_data() {
+ let x = Bob::<i32>::new(42);
+ assert_eq!(
+ x,
+ Bob {
+ a: 42,
+ b: PhantomData
+ }
+ );
+}
+
+/// A tuple struct where fields have default values.
+#[derive(new, PartialEq, Debug)]
+pub struct Boom<T: PartialEq + Debug + Default>(
+ #[new(default)] pub i32,
+ pub u8,
+ #[new(default)] pub T,
+);
+
+#[test]
+fn test_tuple_with_defaults() {
+ let x = Boom::<Vec<String>>::new(42);
+ assert_eq!(x, Boom(0, 42, vec![]));
+}
+
+/// A tuple struct where fields have explicitly provided defaults.
+#[derive(new, PartialEq, Debug)]
+pub struct Moog(
+ #[new(value = "1 + 2")] pub i32,
+ pub String,
+ #[new(value = "vec![-42, 42]")] pub Vec<i8>,
+);
+
+#[test]
+fn test_tuple_with_values() {
+ let x = Moog::new("Fred".to_owned());
+ assert_eq!(x, Moog(3, "Fred".to_owned(), vec![-42, 42]));
+}
+
+/// A tuple struct with defaults and specified values.
+#[derive(new, PartialEq, Debug)]
+pub struct Crab(
+ #[new(value = r#""Thud".to_owned()"#)] pub String,
+ #[new(default)] pub String,
+);
+
+#[test]
+fn test_tuple_mixed_defaults() {
+ let x = Crab::new();
+ assert_eq!(x, Crab("Thud".to_owned(), String::new()));
+}
+
+/// A generic tuple struct with PhantomData member.
+#[derive(new, PartialEq, Debug)]
+pub struct Sponge<T: PartialEq + Debug>(pub i32, pub PhantomData<T>);
+
+#[test]
+fn test_tuple_phantom_data() {
+ let x = Sponge::<i32>::new(42);
+ assert_eq!(x, Sponge(42, PhantomData));
+}
+
+/// An enum with unit variants
+#[derive(new, PartialEq, Debug)]
+pub enum Fizz {
+ ThisISNotADrill,
+ BiteMe,
+}
+
+#[test]
+fn test_enum_unit_variants() {
+ let x = Fizz::new_this_is_not_a_drill();
+ assert_eq!(x, Fizz::ThisISNotADrill);
+
+ let x = Fizz::new_bite_me();
+ assert_eq!(x, Fizz::BiteMe);
+}
+
+/// A more involved enum
+#[derive(new, PartialEq, Debug)]
+pub enum Enterprise<T: PartialEq + Debug + Default> {
+ Picard,
+ Data(
+ #[new(value = "\"fascinating\".to_owned()")] String,
+ #[new(default)] T,
+ ),
+ Spock {
+ x: PhantomData<T>,
+ y: i32,
+ },
+}
+
+#[test]
+fn test_more_involved_enum() {
+ let x = Enterprise::<u8>::new_picard();
+ assert_eq!(x, Enterprise::Picard);
+
+ let x = Enterprise::<u8>::new_data();
+ assert_eq!(x, Enterprise::Data("fascinating".to_owned(), 0u8));
+
+ let x = Enterprise::<u8>::new_spock(42);
+ assert_eq!(
+ x,
+ Enterprise::Spock {
+ x: PhantomData,
+ y: 42
+ }
+ );
+}
+
+#[allow(non_snake_case)]
+#[derive(new, PartialEq, Debug)]
+pub struct Upside {
+ X: i32,
+}
+
+#[cfg_attr(test, allow(non_snake_case))]
+#[derive(new, PartialEq, Debug)]
+pub struct Down {
+ X: i32,
+}
+
+#[derive(new, PartialEq, Debug)]
+pub struct All {
+ #[allow(missing_docs)]
+ pub x: i32,
+}