#constructor #configurable #derive #macro #new #foo-bar #comments

macro fancy_constructor

Derive a highly configurable constructor for your struct

7 stable releases

1.2.2 Oct 28, 2023
1.1.1 Oct 22, 2023
1.1.0 Sep 28, 2023
1.0.1 Sep 26, 2023
1.0.0 Sep 18, 2023

#2143 in Development tools

Download history 1139/week @ 2024-01-03 669/week @ 2024-01-10 1466/week @ 2024-01-17 1241/week @ 2024-01-24 1289/week @ 2024-01-31 1431/week @ 2024-02-07 1222/week @ 2024-02-14 1174/week @ 2024-02-21 1442/week @ 2024-02-28 1950/week @ 2024-03-06 2036/week @ 2024-03-13 2115/week @ 2024-03-20 2186/week @ 2024-03-27 1986/week @ 2024-04-03 2045/week @ 2024-04-10 1620/week @ 2024-04-17

8,147 downloads per month
Used in 15 crates (via indexed_db_futures)

Apache-2.0

25KB
417 lines

Derive a highly configurable constructor for your struct

MASTER CI status crates.io badge docs.rs badge dependencies badge Coverage Status

Examples

Basic
use fancy_constructor::new;
#[derive(new, PartialEq, Eq, Debug)]
struct MyStruct {
  foo: String,
  bar: u8,
}

let a = MyStruct::new("#[derive(new)]".into(), 55);
let b = MyStruct { foo: "#[derive(new)]".into(), bar: 55 };
assert_eq!(a, b);

Outputs:

impl MyStruct {
  pub fn new(foo: String, bar: u8) -> Self {
    Self { foo, bar }
  }
}
Options showcase
#[derive(new, PartialEq, Eq, Debug)]
#[new(vis(pub(crate)), name(construct), comment("Foo"), bounds(T: Clone))]
struct MyStruct<T> {
  #[new(into)]
  a: T,

  #[new(val("Bar".into()))]
  b: String,

  #[new(clone)]
  c: Arc<Whatever>,

  #[new(default)]
  d: Vec<u8>,
}

let we = Arc::new(Whatever::default());
let a = MyStruct::<String>::construct("A", &we);
let b = MyStruct {a: "A".into(), b: "Bar".into(), c: we, d: vec![]};
assert_eq!(a, b);

Outputs:

impl<T> MyStruct<T> {
  /// Foo
  pub(crate) fn construct(a: impl Into<T>, c: &Arc<Whatever>) -> Self where T: Clone {
    Self {
      a: a.into(),
      b: "Bar".into(),
      c: c.clone(),
      d: Default::default(),
    }
  }
}
Private const fn
#[derive(new, PartialEq, Eq, Debug)]
#[new(const_fn, vis())]
struct Foo(u8);

const FOO: Foo = Foo::new(128);
assert_eq!(FOO, Foo(128));

Outputs:

impl Foo {
  const fn new(f1: u8) -> Self {
    Self(f1)
  }
}
Computed values
#[derive(new)]
struct Foo {
  is_bar: bool,
  #[new(val(if is_bar { 100 } else { 5 }))]
  barness_level: u8,
}

assert_eq!(Foo::new(true).barness_level, 100);
assert_eq!(Foo::new(false).barness_level, 5);
Custom constructor args
#[derive(new)]
#[new(args(input_string: &str))]
struct Foo {
  #[new(val(input_string.to_lowercase()))]
  pub lowercase: String,

  #[new(val(input_string.to_uppercase()))]
  pub uppercase: String,
}

let foo = Foo::new("Foo");
assert_eq!(foo.lowercase.as_str(), "foo");
assert_eq!(foo.uppercase.as_str(), "FOO");
Enums
#[derive(new, Eq, PartialEq, Debug)]
enum MyEnum {
  #[new]
  Foo { #[new(into)] bar: u8 },
  Qux,
}

assert_eq!(MyEnum::new(5), MyEnum::Foo { bar: 5 });

Outputs:

impl MyEnum {
  pub fn new(bar: Into<u8>) -> Self {
    Self::Foo { bar: bar.into() }
  }
}
Invalid inputs
#[derive(fancy_constructor::new)]
enum Foo {
  Bar, // no variants marked with `#[new]`
}
#[derive(fancy_constructor::new)]
enum Foo {
  #[new] Bar, // multiple variants marked with `#[new]`
  #[new] Qux,
}
#[derive(fancy_constructor::new)]
union Foo { // Unions not supported
  bar: u8,
  qux: u8,
}

Dependencies

~0.4–0.8MB
~20K SLoC