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
//! [![crates.io](https://img.shields.io/crates/v/derive_constructors.svg)](https://crates.io/crates/derive_constructors)
//! [![GitHub Actions Workflow Status](https://img.shields.io/github/actions/workflow/status/JorgeRicoVivas/derive_constructors/rust.yml)](https://github.com/JorgeRicoVivas/derive_constructors/actions)
//! [![docs.rs](https://img.shields.io/docsrs/derive_constructors)](https://docs.rs/derive_constructors/latest/derive_constructors/)
//! [![GitHub License](https://img.shields.io/github/license/JorgeRicoVivas/derive_constructors)](https://github.com/JorgeRicoVivas/derive_constructors/blob/main/LICENSE)
//!
//! > *You are reading the documentation for derive_constructors version 1.0.0*
//!
//! Allows to derive multiple constructor functions and implement the [From] and [TryFrom] traits
//! for a struct by giving simple information such as their field's names.
//!
//! Also allows to derive [From] for enums.
//!
//! ## 1 The Derive macros for structs: From and TryFrom
//! > Ref: [derive_constructors_proc::From], [derive_constructors_proc::TryFrom]
//!
//! These allow you to Derive the [From] and [TryFrom] traits where a tuple of the fields are passed
//! to the [From::from] or [TryFrom::try_from] function, for example
//!
//! ``` rust
//! #[derive(derive_constructors::From, PartialEq, Debug)]
//! struct CharacterInfo{
//!     name: String,
//!     age: u8,
//!     #[no_from]
//!     times_appeared: u8,
//!     #[no_from(4)]
//!     years_studied: u8
//! }
//!
//! let character_using_from = CharacterInfo::from(("Jorge".to_string(), 23));
//! let expected_character = CharacterInfo { name: "Jorge".to_string(), age: 23, times_appeared: 0, years_studied: 4};
//! assert_eq!(character_using_from, expected_character);
//! ```
//! ## 2 The Attribute Macro for structs:
//! > Ref: [derive_constructors_proc::constructor]
//!
//! Allows you to define a constructor function, inside the proc attribute you can customize the
//! implementation by giving this information following attributes (Note every attribute is
//! optional):
//!
//! - named: Name of the function, constructor functions are usually named like
//! 'with_*name of the fields*', as calling them are quite readable, like
//! ```CharacterInfo::with_name_and_age("Jorge", 23)```. <br> Note: If this field isn't given,
//! instead of implementing a 'with_*' constructor function, it will implement the [From] or
//! [TryFrom] trait.
//!
//! - pattern (values: [From, TryFrom], default: From):
//!     - When using the From pattern, the function receives fields as parameters and returns this
//! struct with said values, this is what you'll be looking for most of the time.
//!     - When using the TryFrom pattern, the functions receives types that implement
//! Into<YourField1>, Into<YourField2>..., returning a [Ok] with your struct if every field could
//! successfully be turned to your field, in case not, it will return [Err] with an enum telling
//! which field couldn't get initialized and the Error why it didn't, see examples below for this.
//!
//! - fields (default: All fields not included in the '```defaults```' attribute): Name of the
//! fields you want to create your constructor for, for example: ```fields(age, name)``` could
//! result in a function like: ```fn new(age: u8, name: String) -> CharacterInfo```.
//!
//! - defaults: Tells how to initialize fields not covered in the ```fields``` attribute, for
//! example ```defaults(years_studied(4))```. <br>If a field isn't either on the ```fields``` or
//! ```defaults``` attributes, it would count as it was initialized through [Default::default], this
//! means, the ```times_appeared``` field that hasn't been covered will be init as 0 (since
//! u8::default() is 0).
//!
//! - error_enum_named (Only for the TryFrom pattern): Specifies the name for the enum error that
//! it's returned the TryFrom function fails.
//!
//! - error_enum_metadata (Only for the TryFrom pattern): Declares the metadata for the enum error
//! that it's returned the TryFrom function fails, you will most likely want to write
//! ```error_enum_metadata(#[derive(Debug)])``` in there.
//! <br><br>
//!
//! ## 2.1 Example 1: Empty constructor
//!
//! If you just apply the [constructor] attribute, it will just implement the [From] trait where it
//! will take a tuple formed out of all your fields, in this case,
//! ```from(value: (String, u8)) -> CharacterInfo```.
//!
//! ``` rust
//! #[derive(Debug, PartialEq)]
//! #[derive_constructors::constructor]
//! struct CharacterInfo{
//!     name: String,
//!     age: u8,
//! }
//!
//! let character_using_from = CharacterInfo::from(("Jorge".to_string(), 23));
//! let expected_character = CharacterInfo { name: "Jorge".to_string(), age: 23 };
//! assert_eq!(character_using_from, expected_character);
//! ```
//! <br>
//!
//! ## 2.2 Example 2: A 'new' constructor using specific fields
//!
//! The following example creates a function named ```new(name: String, age: u8) -> CharacterInfo```
//! .<br><br>
//! Since ```years_studied``` is specified, it will be initialized as 4, and since
//! ```times_appeared``` is not, it will be initialized as u8::default() (which is 0).
//!
//! ``` rust
//! #[derive(Debug, PartialEq)]
//! #[derive_constructors::constructor(named(new), fields(name, age), defaults(years_studied(4)))]
//! struct CharacterInfo{
//!     name: String,
//!     age: u8,
//!     times_appeared: u8,
//!     years_studied: u8
//! }
//!
//! let character_using_from = CharacterInfo::new("Jorge".to_string(), 23);
//! let expected_character = CharacterInfo { name: "Jorge".to_string(), age: 23, times_appeared: 0, years_studied: 4};
//! assert_eq!(character_using_from, expected_character);
//! ```
//! <br>
//!
//! ## 2.3 Example 3: A 'new' constructor with the TryFrom pattern
//!
//! The following example creates a function named ```new(name: T where String: TryFrom<T>, age: U
//! where String: TryFrom<U>) -> Result<CharacterInfo, MyEnumError>```.<br><br>
//! Since ```years_studied``` is specified, it will be initialized as 4, and since
//! ```times_appeared``` is not, it will be initialized as u8::default() (which is 0).<br><br>
//! In case of an error, it returns a variant of an enum named ```MyEnumError```, this enum is
//! specified to derive [Debug] and [PartialEq].
//!
//! ``` rust
//! let character_using_try_from = CharacterInfo::new("Jorge", 23_u16).unwrap();
//! let expected_character = CharacterInfo { name: "Jorge".to_string(), age: 23, times_appeared: 0, years_studied: 4};
//! assert_eq!(character_using_try_from, expected_character);
//!
//! let produced_error = u8::try_from(23000_u16).unwrap_err();
//! let forced_error_using_try_from = CharacterInfo::new("Jorge", 23000_u16).unwrap_err();
//! let expected_error_on_try_from = MyEnumError::AgeError(produced_error);
//! assert_eq!(forced_error_using_try_from, expected_error_on_try_from);
//!
//! #[derive(Debug, PartialEq)]
//! #[derive_constructors::constructor(
//!     named(new),
//!     fields(name, age),
//!     defaults(years_studied(4)),
//!     pattern(TryFrom),
//!     error_enum_named(MyEnumError),
//!     error_enum_metadata(#[derive(Debug, PartialEq)])
//! )]
//! struct CharacterInfo{
//!     name: String,
//!     age: u8,
//!     times_appeared: u8,
//!     years_studied: u8,
//! }
//! ```
//!
//! ## 3 The Derive macro for enums: From
//!
//! > Ref: [derive_constructors_proc::From]
//!
//! This implement the From trait for each enum by creating a From::from function on each taking
//! every field as value, for example:
//!
//! ```rust
//! #[derive(derive_constructors::From, Debug, PartialEq)]
//! enum MyValue{
//!     StaticString(&'static str),
//!     Number(i32),
//!     Boolean(bool),
//! }
//!
//! let scattered_values = vec![MyValue::from("Age "), MyValue::from(23), MyValue::from(", over age "), MyValue::from(true)];
//! let specified = vec![MyValue::StaticString("Age "), MyValue::Number(23), MyValue::StaticString(", over age "), MyValue::Boolean(true)];
//! assert_eq!(scattered_values, specified);
//! ```

extern crate derive_constructors_proc;

pub use derive_constructors_proc::*;