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
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
#![no_std]
//! [![github]](https://github.com/miam-miam100/named-tup) [![crates-io]](https://crates.io/crates/named-tup) [![docs-rs]](https://docs.rs/named-tup)
//!
//! [github]: https://img.shields.io/badge/github-8da0cb?style=for-the-badge&labelColor=555555&logo=github
//! [crates-io]: https://img.shields.io/badge/crates.io-fc8d62?style=for-the-badge&labelColor=555555&logo=rust
//! [docs-rs]: https://img.shields.io/badge/docs.rs-66c2a5?style=for-the-badge&labelColor=555555&logoColor=white&logo=data:image/svg+xml;base64,PHN2ZyByb2xlPSJpbWciIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgdmlld0JveD0iMCAwIDUxMiA1MTIiPjxwYXRoIGZpbGw9IiNmNWY1ZjUiIGQ9Ik00ODguNiAyNTAuMkwzOTIgMjE0VjEwNS41YzAtMTUtOS4zLTI4LjQtMjMuNC0zMy43bC0xMDAtMzcuNWMtOC4xLTMuMS0xNy4xLTMuMS0yNS4zIDBsLTEwMCAzNy41Yy0xNC4xIDUuMy0yMy40IDE4LjctMjMuNCAzMy43VjIxNGwtOTYuNiAzNi4yQzkuMyAyNTUuNSAwIDI2OC45IDAgMjgzLjlWMzk0YzAgMTMuNiA3LjcgMjYuMSAxOS45IDMyLjJsMTAwIDUwYzEwLjEgNS4xIDIyLjEgNS4xIDMyLjIgMGwxMDMuOS01MiAxMDMuOSA1MmMxMC4xIDUuMSAyMi4xIDUuMSAzMi4yIDBsMTAwLTUwYzEyLjItNi4xIDE5LjktMTguNiAxOS45LTMyLjJWMjgzLjljMC0xNS05LjMtMjguNC0yMy40LTMzLjd6TTM1OCAyMTQuOGwtODUgMzEuOXYtNjguMmw4NS0zN3Y3My4zek0xNTQgMTA0LjFsMTAyLTM4LjIgMTAyIDM4LjJ2LjZsLTEwMiA0MS40LTEwMi00MS40di0uNnptODQgMjkxLjFsLTg1IDQyLjV2LTc5LjFsODUtMzguOHY3NS40em0wLTExMmwtMTAyIDQxLjQtMTAyLTQxLjR2LS42bDEwMi0zOC4yIDEwMiAzOC4ydi42em0yNDAgMTEybC04NSA0Mi41di03OS4xbDg1LTM4Ljh2NzUuNHptMC0xMTJsLTEwMiA0MS40LTEwMi00MS40di0uNmwxMDItMzguMiAxMDIgMzguMnYuNnoiPjwvcGF0aD48L3N2Zz4K
//!
//! <br>
//!
//! This crate provides the [`tup!`] macro to produce named tuples, a struct that
//! can contain a set of named arguments. Each named tuple can be added together or even
//! default to a value if it does not already exist.
//!
//!
//! The idea of named tuples is to provide a way to quickly iterate on ideas without having
//! to create a builder struct or losing the ability to type check at compile time.
//! Named tuples also allow the creation of default values that can replace nonexistent arguments.
//!
//! ```toml
//! [dependencies]
//! named-tup = "0.2.0"
//!
//! [package.metadata.inwelling]
//! named-tup-derive = true
//! ```
//!
//! <br>
//!
//! # Examples
//! ```
//! use named_tup::tup;
//! let count = 5;
//!
//! // This will have the type of Tup!(count: i32, ingredients: [&str; 3], eggs: bool)
//! let cakes = tup!(count, ingredients: ["milk", "flower", "sugar"], eggs: true);
//!
//! // We can just add a price afterwards
//! let mut cakes = cakes + tup!(price: 3);
//! // And now it has the type of Tup!(eggs: bool, ingredients: [&str; 3], count: i32, price: i32)
//!
//! // Once the price is in the tup we can just update it!
//! cakes.price = 4;
//!
//! // Will print tup { count: 5, eggs: true, ingredients: ["milk", "flower", "sugar"], price: 4 }
//! println!("{cakes:?}");
//! ```
//!
//! <br>
//!
//! To use defaults just annotate the item where you set a field with [`#[tup_default]`](tup_default).
//! Additionally since the defaulted [`Tup!`] is a type you need to convert into it by calling
//! [`.into_tup()`](TupInto) which can be accessed through the [`TupInto`] trait.
//!
//! ```
//! use named_tup::{tup,Tup, tup_default, TupInto};
//!
//! let options = tup!(read: false, write: true);
//!
//! // Converts to Tup!(read: false, write: true, create: false, timeout: 5)
//! open_file("main.rs", options.into_tup());
//!
//! #[tup_default]
//! fn open_file(
//!     path: &str,
//!     options: Tup!(
//!         read: bool = true,
//!         write: bool = false,
//!         create: bool = false,
//!         timeout: i32 = 5
//!     ))
//! {
//!     // Open the file
//! }
//! ```
// Tup types in rustdoc of other crates get linked to here.
#![doc(html_root_url = "https://docs.rs/named_tup/0.2.0")]

pub use convert::{TupFrom, TupInto};
/// The whole point.
///
/// Produces a named tuple, a struct that
/// can contain a set of named arguments. Each named tuple can be added together or even
/// default to a value if it does not already exist.
///
/// There are two different macros the [`tup!`] macro for defining an expression and the [`Tup!`]
/// macro for defining a type.
///
/// <br>
///
/// # tup as an expression
///
/// In it's most basic form a [`tup!`] is formed just like a struct instantiation.
/// ```rust
/// # use named_tup::tup;
/// let mut farm = tup!(horse: 4, chicken: 3, ants: 999_999_999);
///
/// assert_eq!(farm.horse, 4);
/// assert_eq!(farm.chicken, 3);
///
/// // Got some ant killer
/// farm.ants = 0;
/// assert_eq!(farm.ants, 0);
/// ```
///
/// And just like it, [`tup!`] can use pre-existing variables.
/// ```rust
/// # use named_tup::tup;
/// let kingfisher = true;
/// let eagle = false;
/// let nest = tup!(kingfisher, toucan: true, eagle);
///
/// assert_eq!(nest, tup!(kingfisher: true, eagle: false, toucan: true))
/// ```
///
/// <br>
///
/// # Tup as a type
///
/// However in certain cases defining the type exactly is necessary.
///
/// ```rust
/// # use named_tup::{tup, Tup};
/// let recipe: Tup!(eggs: u8, milk: &str, flour: f32) = tup!(milk: "500ml", eggs: 4, flour: 203.6);
/// let person = tup!(name: "Joe", blue_eyes: true);
/// face_recognizer(vec![person]);
///
/// fn face_recognizer(
///     people: Vec<Tup!(name: &'static str, blue_eyes: bool)>,
/// ) -> Tup!(confidence: f64, name: &'static str) {
///     tup!(confidence: 0.3, name: "Joe")
/// }
/// ```
///
/// The type macro is also used to specify defaults using the [`#[tup_default]`](tup_default)
/// attribute and the [`TupInto`] trait to change the type.
///
/// ```rust
/// # use named_tup::{tup, Tup, tup_default, TupInto};
/// #[tup_default]
/// pub fn main() {
///     # let input = false;
///     let result: Tup!(foo: i32 = 3, bar: Option<i32> = None) = match input {
///         true => tup!(foo: 4).into_tup(),
///         false => tup!(bar: Some(4)).into_tup(),
///     };
///     
///     read(tup!().into_tup());
/// }
///
/// #[tup_default]
/// fn read(books: Tup!(names: &'static [&'static str] = &[], ETA: i32 = 0)) {
///     // Read
/// }
/// ```
///
/// <br>
///
/// # Tup type
///
/// Each [`Tup!`] call produces a Tup type, the type itself eagerly implements
/// [`Copy`], [`Clone`], [`Eq`], [`PartialEq`], [`Ord`], [`PartialOrd`], [`Hash`]
/// assuming all the types it contains implement them. (Ord/PartialOrd is in lexicographic
/// ordering and Ord/Eq cannot be implemented on types that use different defaults
/// so if this is the case just convert them to non-defaulted versions before using them).
/// As well as this a [`Default`] and [`Debug`] trait is always implemented.
///
/// ```rust
/// # use named_tup::tup;
/// assert_eq!(tup!(rooms: ["garden", "shed"]), tup!(rooms: ["garden", "shed"]));
///
/// let rooms = vec!["bathroom", "bedroom"];
/// let non_copy = tup!(rooms);
/// assert_eq!(non_copy, non_copy.clone());
///
/// let copy = tup!(cows: 4, bulls: 2);
/// drop(copy);
/// assert!(copy > tup!(cows: 5, bulls: 1));
///
/// // Will print tup { farmer: "Joe", married: true }
/// println!("{:?}", tup!( married: true, farmer: "Joe"));
/// ```
///
/// Finally the [`Add`](core::ops::Add) trait is implemented so that you can transform between
/// different tup types. If both sides contain a certain argument, precedence is given to the
/// right hand side.
/// ```rust
/// # use named_tup::tup;
/// let farm1 = tup!(roosters: 4, dragons: 7, dogs: 1);
/// let farm2 = tup!(hens: 56, dogs: 3);
/// let combined_farm = farm1 + farm2;
///
/// assert_eq!(combined_farm, tup!(roosters: 4, hens: 56, dragons: 7, dogs: 3));
/// ```
pub use named_tup_derive::tup;
/// An attribute macro that allows you to derive defaults.
///
/// Defaults are added to any [`Tup!`] macro by using the equals sign.
/// [`#[tup_default]`](tup_default) will then change the invocation so that it is a part of the
/// type information itself. As such [`#[tup_default]`](tup_default) needs to be used on any
/// item that uses defaults in a [`Tup!`] invocation. Since a defaulted Tup is a type
/// [`TupInto`] must be used to convert it.
///
/// ```rust
/// # use named_tup::{TupInto, tup, tup_default, Tup};
/// #[tup_default]
/// pub fn main() {
///     let default: Tup!(foo: i32 = 2) = tup!().into_tup();
///     let result = default_to_non(tup!().into_tup());
///
///     assert_eq!(result, tup!(foo: 2));
///     assert_eq!(result.foo, default.foo);
/// }
/// #[tup_default]
/// fn default_to_non(n_tup: Tup!(foo: i32 = 2)) -> Tup!(foo: i32) {
///     n_tup.into_tup()
/// }
/// ```
pub use named_tup_derive::tup_default;
/// Produces a type annotation for the tup struct. If an expression is needed
/// instead please use the [`tup!`] macro.
///
/// It is used in a very similar way to the [`tup!`] macro but with any expression
/// replaced with a type.
/// ```rust
/// # use named_tup::{tup, Tup};
/// let empty: Tup!() = tup!();
/// // Since it's just a normal type it can coerce certain literals
/// let num: Tup!(foo: u8) = tup!(foo: 5);
///
/// assert_eq!(test(tup!(foo: 5, bar: 6)), tup!(foo: 5));
///
/// // It can also just be used as an argument in functions
/// fn test(arg: Tup!(foo: i32, bar: i64)) -> Tup!(foo: i32) {
///     tup!(foo: arg.foo)
/// }
/// ```
///
/// However it's main use case is to provide default values using the
/// [`#[tup_default]`](tup_default) attribute macro and the
/// [`TupInto`] trait to convert between different types.
///
/// ```rust
/// # use named_tup::{TupInto, tup, tup_default, Tup};
/// #[tup_default]
/// pub fn main() {
///     let default: Tup!(foo: i32 = 2) = tup!().into_tup();
///     let result = default_to_non(tup!().into_tup());
///
///     assert_eq!(result, tup!(foo: 2));
///     assert_eq!(result.foo, default.foo);
///
///     // Will print tup { foo: 2 }
///     println!("{result:?}");
///
///     // Will print tup { foo: 2 (=2) } where (=2) is the default value
///     println!("{default:?}");
/// }
/// #[tup_default]
/// fn default_to_non(n_tup: Tup!(foo: i32 = 2)) -> Tup!(foo: i32) {
///     n_tup.into_tup()
/// }
/// ```
pub use named_tup_derive::Tup;

mod combine;
mod convert;
mod tup_struct;

//Not part of public api.
#[doc(hidden)]
pub mod __private {
    pub use super::tup_struct::{Tup, TupDefault, Unused, Used};
}