Skip to main content

scones/
lib.rs

1//! Scones is a library for generating constructors and builders without the verbosity it usually
2//! requires. See the documentation for `#[make_constructor]` to see how to use this system. The
3//! syntax and usage of `#[make_builder]` is similar to `#[make_constructor]` apart from a few
4//! minor differences. A short example of how this crate works is as follows:
5//!
6//! ```
7//! use scones::make_constructor;
8//!
9//! #[make_constructor]
10//! #[make_constructor(pub inverse)]
11//! #[make_constructor(pub identity)]
12//! struct MyData {
13//!     #[value(1 for identity)]
14//!     val1: i32,
15//!     #[value(-val1 for inverse)]
16//!     #[value(1 for identity)]
17//!     val2: i32,
18//!     #[value(true)]
19//!     always_true: bool
20//! }
21//!
22//! let instance = MyData::new(10, 23);
23//! let inverse = MyData::inverse(5);
24//! let identity = MyData::identity();
25//! ```
26//! 
27//! Documented examples can be found at [https://docs.rs/scones_examples](https://docs.rs/scones_examples)
28
29use std::marker::PhantomData;
30
31/// Proc macro to generate builders for structs.
32///
33/// It is recommended to read the documentation of `#[make_constructor]` before reading this.
34///
35/// # Basic Usage
36/// The simplest way to use this macro is without any additional arguments:
37/// ```
38/// use scones::make_builder;
39///
40/// #[make_builder]
41/// struct MyStruct {
42///     int: i32,
43///     string: String,
44/// }
45///
46/// let instance = MyStructBuilder::new()
47///     .int(10)
48///     .string("Hello World".to_owned())
49///     .build();
50/// ```
51///
52/// # Syntax
53/// The full syntax of this macro is as follows:
54/// ```
55/// # /* This little bit of trickery makes this not be tested without telling doc readers.
56/// #[make_builder(visibility name params return_type)]
57/// # */
58/// ```
59/// Each of these elements are optional but must always be present in the order listed above. If an
60/// element is omitted, a default value is used instead. Invoking the macro without any of the
61/// arguments listed above is equivalent to:
62/// ```
63/// # /* This little bit of trickery makes this not be tested without telling doc readers.
64/// #[make_builder(pub <StructName>Builder(..) -> Self)]
65/// # */
66/// ```
67/// To make the visibility of the generated builder blank, provide a name but no visibility, like
68/// so:
69/// ```
70/// # /* This little bit of trickery makes this not be tested without telling doc readers.
71/// #[make_builder(PrivateBuilder)]
72/// # */
73/// ```
74///
75/// ### Params
76/// This argument can be used to provide additional parameters or make parameters optional.
77/// It is a comma-seperated list of parameters enclosed in parenthesis. To add an extra parameter
78/// (I.E. one which does not correspond to a field in your struct), use Rust's regular function
79/// parameter syntax:
80/// ```
81/// # /* This little bit of trickery makes this not be tested without telling doc readers.
82/// #[make_builder((custom_param: i32))]
83/// # */
84/// ```
85/// By default, this parameter will be required, meaning code that uses your builder will not
86/// compile if it does not set a value for `custom_param`. If you want to make it optional, make
87/// the type `Option<_>`. Note that the the macro is expecting the literal text `Option`, you
88/// cannot use a type alias.
89/// ```
90/// # /* This little bit of trickery makes this not be tested without telling doc readers.
91/// #[make_builder((optional: Option<i32>))]
92/// # */
93/// ```
94/// Override fields can be specified with the following syntax, more on what this means later:
95/// ```
96/// # /* This little bit of trickery makes this not be tested without telling doc readers.
97/// #[make_builder((field_name?))]
98/// # */
99/// ```
100///
101/// ### Return Type
102/// The return type can either be `-> Self` or `-> Result<Self, [any type]>`. Note that the macro
103/// is expecting the literal text `Self` and/or `Result`, it is not capable of recognizing type
104/// aliases like `std::fmt::Result`. Here is an example of how to make a builder that can return
105/// an error:
106/// ```
107/// # /* This little bit of trickery makes this not be tested without telling doc readers.
108/// #[make_builder(-> Result<Self, FileError>)]
109/// # */
110/// ```
111///
112/// # Value Attributes
113/// You can use the `#[value()]` attribute to add custom code for initializing a field:
114/// ```
115/// use scones::make_builder;
116///
117/// #[make_builder]
118/// struct MyStruct {
119///     #[value(123)]
120///     data: i32
121/// }
122///
123/// // We no longer need to specify a value for `data`.
124/// let instance = MyStructBuilder::new().build();
125/// ```
126/// You can place any expression inside the parenthesis. Keep in mind that fields are initialized in
127/// the order you declare them, so take care not to use parameters after they are moved:
128/// ```compile_fail
129/// use scones::make_builder;
130///
131/// #[make_builder]
132/// struct MyStruct {
133///     field_0: String,
134///     #[value(field_0.clone())]
135///     field_1: String,
136/// }
137/// ```
138/// You can make a value attribute only apply to a certain builder by appending
139/// `for BuilderName` to the end. You can do this multiple times for a single field of your
140/// struct. If you have a value attribute without a `for` clause and multiple value attributes with
141/// `for` clauses on the same field, the one without the clause will be used as a default for
142/// whenever there is not a specific value attribute for a particular builder:
143/// ```
144/// use scones::make_builder;
145///
146/// #[make_builder(DefaultBuilder)]
147/// #[make_builder(SpecificBuilder)]
148/// struct MyStruct {
149///     #[value(0)]
150///     #[value(31415 for SpecificBuilder)]
151///     data: i32,
152/// }
153///
154/// let data_is_zero = DefaultBuilder::new().build();
155/// let data_is_31415 = SpecificBuilder::new().build();
156/// ```
157/// When a field has a value attribute, the macro will not automatically add it to the parameters
158/// for the builder. If you still want it to be a parameter despite this, you can explicitly add
159/// it back to the parameter list of the builder:
160/// ```
161/// use scones::make_builder;
162///
163/// #[make_builder((data))]
164/// struct MyStruct {
165///     #[value(data + 2)]
166///     data: i32
167/// }
168///
169/// let data_is_10 = MyStructBuilder::new().data(8).build();
170/// ```
171///
172/// # Required, Optional, and Override parameters
173/// By default, all parameters for a builder are required. This means that the following code will
174/// not compile:
175/// ```compile_fail
176/// use scones::make_builder;
177///
178/// #[make_builder]
179/// struct MyStruct {
180///     data: i32
181/// }
182///
183/// // Ok
184/// let instance = MyStructBuilder::new().data(0).build();
185/// // Compile error! ("build() does not exist on type MyStructBuilder<Missing>")
186/// let instance = MyStructBuilder::new().build();
187/// ```
188/// As mentioned before, you can add a parameter and explicitly give it an `Option<>` datatype
189/// to make it optional, in which case it does not matter whether or not you specify its value
190/// when using the builder, your code will still compile. One common use of this is to have a
191/// default value for a particular field, but allow a user to change it. The long way to do that
192/// would be as follows:
193/// ```
194/// use scones::make_builder;
195///
196/// #[make_builder((data: Option<i32>))]
197/// struct MyStruct {
198///     #[value(data.unwrap_or(100))]
199///     data: i32
200/// }
201/// ```
202/// However, the case shown above is a fairly common and straightforward pattern, so the following
203/// shortcut was created which produces identical results:
204/// ```
205/// use scones::make_builder;
206///
207/// #[make_builder((data?))]
208/// struct MyStruct {
209///     #[value(100)]
210///     data: i32
211/// }
212/// ```
213/// The usage of `data?` is called an "override" because it is not required, but when it is
214/// provided, it will *override* the default value of `data`.
215///
216/// # Templates and Tuple Structs
217/// All the above semantics work with templated structs:
218/// ```
219/// use scones::make_builder;
220///
221/// #[make_builder]
222/// // This also works with `where T: ToString`.
223/// struct MyStruct<T: ToString> {
224///     #[value(data.to_string())]
225///     text: String,
226///     data: T,
227/// };
228///
229/// let instance = MyStructBuilder::new().data(123).build();
230/// ```
231/// All the above semantics are supported with tuple structs as well, the only difference being that
232/// fields are given the names `field_0`, `field_1`, etc.
233/// ```
234/// use scones::make_builder;
235///
236/// #[make_builder]
237/// struct MyTuple(
238///     i32,
239///     #[value(field_0)] i32,
240/// );
241///
242/// let instance = MyTupleBuilder::new().field_0(123).build();
243/// ```
244pub use scones_macros::make_builder;
245
246pub use scones_macros::generate_items__;
247/// Proc macro to generate constructors for structs.
248///
249/// # Basic Usage
250/// The simplest way to use this macro is without any additional arguments:
251/// ```
252/// use scones::make_constructor;
253///
254/// #[make_constructor]
255/// struct MyStruct {
256///     int: i32,
257///     string: String,
258/// }
259///
260/// // The macro generates:
261/// // impl MyStruct {
262/// //     pub fn new(int: i32, string: String) -> Self {
263/// //         Self {
264/// //             int,
265/// //             string,
266/// //         }
267/// //     }
268/// // }
269/// ```
270///
271/// # Syntax
272/// The full syntax of this macro is as follows:
273/// ```
274/// # /* This little bit of trickery makes this not be tested without telling doc readers.
275/// #[make_constructor(visibility name params return_type)]
276/// # */
277/// ```
278/// Each of these elements are optional but must always be present in the order listed above. If an
279/// element is omitted, a default value is used instead. Invoking the macro without any of the
280/// arguments listed above is equivalent to:
281/// ```
282/// # /* This little bit of trickery makes this not be tested without telling doc readers.
283/// #[make_constructor(pub new(..) -> Self)]
284/// # */
285/// ```
286/// To make the visibility of the generated function blank, provide a name but no visibility, like
287/// so:
288/// ```
289/// # /* This little bit of trickery makes this not be tested without telling doc readers.
290/// #[make_constructor(private_new)]
291/// # */
292/// ```
293///
294/// ### Params
295/// This argument can be used to rearrange the order of generated parameters or provide additional
296/// parameters. It is a comma-seperated list of parameters enclosed in parenthesis. To specify the
297/// location of a parameter for a particular field, use the name of that field:
298/// ```
299/// # /* This little bit of trickery makes this not be tested without telling doc readers.
300/// #[make_constructor((second_field, first_field))]
301/// # */
302/// ```
303/// To add an extra parameter (I.E. one which does not correspond to a field in your struct), use
304/// Rust's regular function parameter syntax:
305/// ```
306/// # /* This little bit of trickery makes this not be tested without telling doc readers.
307/// #[make_constructor((field, custom_param: i32))]
308/// # */
309/// ```
310/// You can also use ellipses to specify where any other required parameters should be inserted.
311/// If the macro detects that you have not explicitly given a position for a required parameter,
312/// it will insert them wherever you place the ellipses:
313/// ```
314/// # /* This little bit of trickery makes this not be tested without telling doc readers.
315/// // Generates `pub fn new(field_a, field_b, custom_param) -> Self`.
316/// #[make_constructor((.., custom_param: i32))]
317/// # */
318/// ```
319///
320/// ### Return Type
321/// The return type can either be `-> Self` or `-> Result<Self, [any type]>`. Note that the macro
322/// is expecting the literal text `Self` and/or `Result`, it is not capable of recognizing type
323/// aliases like `std::fmt::Result`. Here is an example of how to make a constructor that can return
324/// an error:
325/// ```
326/// # /* This little bit of trickery makes this not be tested without telling doc readers.
327/// #[make_constructor(-> Result<Self, FileError>)]
328/// # */
329/// ```
330///
331/// # Value Attributes
332/// You can use the `#[value()]` attribute to add custom code for initializing a field:
333/// ```
334/// use scones::make_constructor;
335///
336/// #[make_constructor]
337/// struct MyStruct {
338///     #[value(123)]
339///     data: i32
340/// }
341///
342/// // The macro generates:
343/// // impl MyStruct {
344/// //     fn new() -> Self {
345/// //         Self {
346/// //             data: 123,
347/// //         }
348/// //     }
349/// // }
350/// ```
351/// You can place any expression inside the parenthesis. Keep in mind that fields are initialized in
352/// the order you declare them, so take care not to use parameters after they are moved:
353/// ```compile_fail
354/// use scones::make_constructor;
355///
356/// #[make_constructor]
357/// struct MyStruct {
358///     field_0: String,
359///     #[value(field_0.clone())]
360///     field_1: String,
361/// }
362///
363/// // The macro generates:
364/// impl MyStruct {
365///     pub fn new(field_0: String) -> Self {
366///         Self {
367///             field_0: field_0,
368///             field_1: field_0.clone()
369///         }
370///     }
371/// }
372/// ```
373/// You can make a value attribute only apply to a certain constructor by appending
374/// `for constructor_name` to the end. You can do this multiple times for a single field of your
375/// struct. If you have a value attribute without a `for` clause and multiple value attributes with
376/// `for` clauses on the same field, the one without the clause will be used as a default for
377/// whenever there is not a specific value attribute for a particular constructor:
378/// ```
379/// use scones::make_constructor;
380///
381/// #[make_constructor(default)]
382/// #[make_constructor(specific)]
383/// struct MyStruct {
384///     #[value(0)]
385///     #[value(31415 for specific)]
386///     data: i32,
387/// }
388///
389/// // The macro generates:
390/// // impl MyStruct {
391/// //     pub fn default() -> Self {
392/// //         Self { data: 0 }
393/// //     }
394/// //     pub fn specific() -> Self {
395/// //         Self { data: 31415 }
396/// //     }
397/// // }
398/// ```
399/// When a field has a value attribute, the macro will not automatically add it to the parameters
400/// for the constructor. If you still want it to be a parameter despite this, you can explicitly add
401/// it back to the parameter list of the constructor:
402/// ```
403/// use scones::make_constructor;
404///
405/// #[make_constructor((data))]
406/// struct MyStruct {
407///     #[value(data + 2)]
408///     data: i32
409/// }
410///
411/// // The macro generates:
412/// // impl MyStruct {
413/// //     pub fn new(data: i32) -> Self {
414/// //         Self { data: data + 2 }
415/// //     }
416/// // }
417/// ```
418///
419/// # Templates and Tuple Structs
420/// All the above semantics work with templated structs:
421/// ```
422/// use scones::make_constructor;
423///
424/// #[make_constructor]
425/// // This also works with `where T: ToString`.
426/// struct MyStruct<T: ToString> {
427///     #[value(data.to_string())]
428///     text: String,
429///     data: T,
430/// };
431///
432/// // The macro generates:
433/// // impl<T: ToString> MyTuple<T> {
434/// //     pub fn new(data: T) -> Self {
435/// //         Self {
436/// //             text: data.to_string(),
437/// //             data: data,
438/// //         }
439/// //     }
440/// // }
441/// ```
442/// All the above semantics are supported with tuple structs as well, the only difference being that
443/// fields are given the names `field_0`, `field_1`, etc.
444/// ```
445/// use scones::make_constructor;
446///
447/// #[make_constructor]
448/// struct MyTuple(
449///     i32,
450///     #[value(field_0)] i32,
451/// );
452///
453/// // The macro generates:
454/// // impl MyTuple {
455/// //     pub fn new(field_0: i32) -> Self {
456/// //         Self(field_0, field_0)
457/// //     }
458/// // }
459/// ```
460pub use scones_macros::make_constructor;
461
462/// Indicates that a particular required value has been provided in a builder.
463pub struct Present;
464/// Indicates that a particular required value has not been provided yet in a builder.
465pub struct Missing;
466#[doc(hidden)]
467/// Used to implement builders.
468pub struct BuilderFieldContainer<FieldType, IsPresent> {
469    data: Option<FieldType>,
470    marker_: PhantomData<IsPresent>,
471}
472
473impl<FieldType, IsPresent> BuilderFieldContainer<FieldType, IsPresent> {
474    pub fn set(self, value: FieldType) -> BuilderFieldContainer<FieldType, Present> {
475        BuilderFieldContainer {
476            data: Some(value),
477            marker_: PhantomData,
478        }
479    }
480}
481
482impl<FieldType> BuilderFieldContainer<FieldType, Missing> {
483    pub fn missing() -> Self {
484        Self {
485            data: None,
486            marker_: PhantomData,
487        }
488    }
489}
490
491impl<FieldType> BuilderFieldContainer<FieldType, Present> {
492    pub fn present(value: FieldType) -> Self {
493        Self {
494            data: Some(value),
495            marker_: PhantomData,
496        }
497    }
498
499    pub fn into_value(self) -> FieldType {
500        // The only way for IsPresent to be Present is if the user called set() in the past.
501        self.data.unwrap()
502    }
503}