1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209
//! Generates builder methods of every field of a struct. It is meant to be used on structs that
//! implement `Default`. There is no separate builder struct generated and no need to call a
//! `build()` method at the end or `.unwrap()`.
//!
//! This crate is used by the crate `leptos-use` for the option structs that
//! can be passed to the various functions.
//!
//! ## Installation
//!
//! In your project folder run
//!
//! ```sh
//! cargo add default-struct-builder
//! ```
//!
//! ## Usage
//!
//! It is very easy to use:
//!
//! ```
//! use default_struct_builder::DefaultBuilder;
//!
//! #[derive(DefaultBuilder, Default)]
//! pub struct SomeOptions {
//! throttle: f64,
//!
//! #[builder(into)]
//! offset: Option<f64>,
//!
//! #[builder(skip)]
//! not_included: u32,
//! }
//! ```
//!
//! you can then use the struct like this:
//!
//! ```
//! # use default_struct_builder::DefaultBuilder;
//! #
//! # #[derive(DefaultBuilder, Default)]
//! # pub struct SomeOptions {
//! # throttle: f64,
//! #
//! # #[builder(into)]
//! # offset: Option<f64>,
//! #
//! # #[builder(skip)]
//! # not_included: u32,
//! # }
//! #
//! # fn main() {
//! let options = SomeOptions::default().offset(4.0);
//!
//! assert_eq!(options.offset, Some(4.0));
//! assert_eq!(options.throttle, 0.0);
//! assert_eq!(options.not_included, 0);
//! # }
//! ```
//!
//! ### Generics
//!
//! The macro is ready to be used on generic structs.
//!
//! ```
//! use default_struct_builder::DefaultBuilder;
//!
//! #[derive(DefaultBuilder, Default)]
//! pub struct SomeOptions<T>
//! where
//! T: Default,
//! {
//! some_field: T,
//! }
//! ```
//!
//! ### Doc comments
//!
//! All doc comments on fields are directly passed on to their generated setter methods.
//!
//! ## How it works
//!
//! The derive macro generates the following code:
//!
//! ```
//! # #[derive(Default)]
//! # pub struct SomeOptions {
//! # throttle: f64,
//! # offset: Option<f64>,
//! # not_included: u32,
//! # }
//! #
//! impl SomeOptions {
//! // setter methods are given that consume `self` and return a new `Self` with the field value changed
//! pub fn throttle(self, value: f64) -> Self {
//! Self {
//! throttle: value,
//! ..self
//! }
//! }
//!
//! // because `into` was specified this method is generic and calls `.into()` when setting the value
//! pub fn offset<T>(self, value: T) -> Self
//! where
//! T: Into<Option<f64>>,
//! {
//! Self {
//! offset: value.into(),
//! ..self
//! }
//! }
//!
//! // no method for field `not_included` because `skip` was specified
//! }
//! ```
//!
//! ### Generics
//!
//! In the case of a generic field the generated method is a bit more complex because by calling
//! the method the type of the type parameter can be different than before.
//!
//! Let's look at the following example.
//!
//! ```
//! use default_struct_builder::DefaultBuilder;
//!
//! #[derive(DefaultBuilder, Default)]
//! pub struct SomeOptions<T>
//! where
//! T: Default,
//! {
//! some_field: T,
//! other_field: i16,
//! }
//!
//! impl SomeOptions<f32> {
//! pub fn new() -> Self {
//! Self {
//! some_field: 42.0,
//! other_field: 0,
//! }
//! }
//! }
//! #
//! # fn main() {
//! # let options = SomeOptions::new().some_field("string");
//! # }
//! ```
//!
//! This generates the setter method below.
//!
//! ```
//! # pub struct SomeOptions<T>
//! # where
//! # T: Default,
//! # {
//! # some_field: T,
//! # other_field: i16,
//! # }
//! #
//! # impl SomeOptions<f32> {
//! # pub fn new() -> Self {
//! # Self {
//! # some_field: 42.0,
//! # other_field: 0,
//! # }
//! # }
//! # }
//! #
//! impl<T> SomeOptions<T>
//! where
//! T: Default,
//! {
//! pub fn some_field<NewT>(self, value: NewT) -> SomeOptions<NewT>
//! where
//! NewT: Default,
//! {
//! SomeOptions::<NewT> {
//! some_field: value,
//! other_field: self.other_field,
//! }
//! }
//! }
//!
//! fn main() {
//! let options = SomeOptions::new() // at first SomeOptions<f32>
//! .some_field("string"); // changed to SomeOptions<&str>
//! }
//! ```
//!
//! ## Related Work
//!
//! For more general purposes please check out the much more powerful
//! [`derive_builder` crate](https://github.com/colin-kiegel/rust-derive-builder).
mod builder;
use builder::DefaultBuilderDeriveInput;
use darling::FromDeriveInput;
use proc_macro::TokenStream;
use quote::quote;
use syn::parse_macro_input;
#[proc_macro_derive(DefaultBuilder, attributes(builder))]
pub fn derive_builder(input: TokenStream) -> TokenStream {
let input = parse_macro_input!(input as syn::DeriveInput);
let data = DefaultBuilderDeriveInput::from_derive_input(&input).expect("Wrong options");
let stream = quote!(#data);
stream.into()
}