named_tup/
lib.rs

1#![no_std]
2//! [![github]](https://github.com/miam-miam/named-tup) [![crates-io]](https://crates.io/crates/named-tup) [![docs-rs]](https://docs.rs/named-tup)
3//!
4//! [github]: https://img.shields.io/badge/github-8da0cb?style=for-the-badge&labelColor=555555&logo=github
5//! [crates-io]: https://img.shields.io/badge/crates.io-fc8d62?style=for-the-badge&labelColor=555555&logo=rust
6//! [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
7//!
8//! <br>
9//!
10//! This crate provides the [`tup!`] macro to produce named tuples, a struct that
11//! can contain a set of named arguments. Each named tuple can be added together or even
12//! default to a value if it does not already exist.
13//!
14//!
15//! The idea of named tuples is to provide a way to quickly iterate on ideas without having
16//! to create a builder struct or losing the ability to type check at compile time.
17//! Named tuples also allow the creation of default values that can replace nonexistent arguments.
18//!
19//! ```toml
20//! [dependencies]
21//! named-tup = "0.3.1"
22//!
23//! [build-dependencies]
24//! inwelling = "0.4.0"
25//!
26//! [package.metadata.inwelling.named-tup-derive]
27//! ```
28//!
29//! And put the following in your `build.rs` file.
30//!
31//! ```ignore
32//! fn main() {
33//!     inwelling::register();
34//! }
35//! ```
36//!
37//! If you would prefer for this crate to not scan your project files to determine what named arguments are being used add a list
38//! of the named tup arguments you used in your Cargo.toml like so.
39//!
40//! ```toml
41//! [package.metadata.inwelling.named-tup-derive]
42//! arguments = ["count", "ingredients", "eggs", "price"]
43//! ```
44//!
45//! <br>
46//!
47//! # Examples
48//! ```
49//! use named_tup::tup;
50//! let count = 5;
51//!
52//! // This will have the type of Tup!(count: i32, ingredients: [&str; 3], eggs: bool)
53//! let cakes = tup!(count, ingredients: ["milk", "flower", "sugar"], eggs: true);
54//!
55//! // We can just add a price afterwards
56//! let mut cakes = cakes + tup!(price: 3);
57//! // And now it has the type of Tup!(eggs: bool, ingredients: [&str; 3], count: i32, price: i32)
58//!
59//! // Once the price is in the tup we can just update it!
60//! cakes.price = 4;
61//!
62//! // Will print tup { count: 5, eggs: true, ingredients: ["milk", "flower", "sugar"], price: 4 }
63//! println!("{cakes:?}");
64//! ```
65//!
66//! <br>
67//!
68//! To use defaults just annotate the item where you set a field with [`#[tup_default]`](tup_default).
69//! Additionally since the defaulted [`Tup!`] is a type you need to convert into it by calling
70//! [`.into_tup()`](TupInto) which can be accessed through the [`TupInto`] trait.
71//!
72//! ```
73//! use named_tup::{tup,Tup, tup_default, TupInto};
74//!
75//! let options = tup!(read: false, write: true);
76//!
77//! // Converts to Tup!(read: false, write: true, create: false, timeout: 5)
78//! open_file("main.rs", options.into_tup());
79//!
80//! #[tup_default]
81//! fn open_file(
82//!     path: &str,
83//!     options: Tup!(
84//!         read: bool = true,
85//!         write: bool = false,
86//!         create: bool = false,
87//!         timeout: i32 = 5
88//!     ))
89//! {
90//!     // Open the file
91//! }
92//! ```
93// Tup types in rustdoc of other crates get linked to here.
94#![doc(html_root_url = "https://docs.rs/named_tup/0.3.1")]
95
96pub use convert::{TupFrom, TupInto};
97/// The whole point.
98///
99/// Produces a named tuple, a struct that
100/// can contain a set of named arguments. Each named tuple can be added together or even
101/// default to a value if it does not already exist.
102///
103/// There are two different macros the [`tup!`] macro for defining an expression and the [`Tup!`]
104/// macro for defining a type.
105///
106/// <br>
107///
108/// # tup as an expression
109///
110/// In it's most basic form a [`tup!`] is formed just like a struct instantiation.
111/// ```rust
112/// # use named_tup::tup;
113/// let mut farm = tup!(horse: 4, chicken: 3, ants: 999_999_999);
114///
115/// assert_eq!(farm.horse, 4);
116/// assert_eq!(farm.chicken, 3);
117///
118/// // Got some ant killer
119/// farm.ants = 0;
120/// assert_eq!(farm.ants, 0);
121/// ```
122///
123/// And just like it, [`tup!`] can use pre-existing variables.
124/// ```rust
125/// # use named_tup::tup;
126/// let kingfisher = true;
127/// let eagle = false;
128/// let nest = tup!(kingfisher, toucan: true, eagle);
129///
130/// assert_eq!(nest, tup!(kingfisher: true, eagle: false, toucan: true))
131/// ```
132///
133/// <br>
134///
135/// # Tup as a type
136///
137/// However in certain cases defining the type exactly is necessary.
138///
139/// ```rust
140/// # use named_tup::{tup, Tup};
141/// let recipe: Tup!(eggs: u8, milk: &str, flour: f32) = tup!(milk: "500ml", eggs: 4, flour: 203.6);
142/// let person = tup!(name: "Joe", blue_eyes: true);
143/// face_recognizer(vec![person]);
144///
145/// fn face_recognizer(
146///     people: Vec<Tup!(name: &'static str, blue_eyes: bool)>,
147/// ) -> Tup!(confidence: f64, name: &'static str) {
148///     tup!(confidence: 0.3, name: "Joe")
149/// }
150/// ```
151///
152/// The type macro is also used to specify defaults using the [`#[tup_default]`](tup_default)
153/// attribute and the [`TupInto`] trait to change the type.
154///
155/// ```rust
156/// # use named_tup::{tup, Tup, tup_default, TupInto};
157/// #[tup_default]
158/// pub fn main() {
159///     # let input = false;
160///     let result: Tup!(foo: i32 = 3, bar: Option<i32> = None) = match input {
161///         true => tup!(foo: 4).into_tup(),
162///         false => tup!(bar: Some(4)).into_tup(),
163///     };
164///
165///     read(tup!().into_tup());
166/// }
167///
168/// #[tup_default]
169/// fn read(books: Tup!(names: &'static [&'static str] = &[], ETA: i32 = 0)) {
170///     // Read
171/// }
172/// ```
173///
174/// <br>
175///
176/// # Tup type
177///
178/// Each [`Tup!`] call produces a Tup type, the type itself eagerly implements
179/// [`Copy`], [`Clone`], [`Eq`], [`PartialEq`], [`Ord`], [`PartialOrd`], [`Hash`]
180/// assuming all the types it contains implement them. (Ord/PartialOrd is in lexicographic
181/// ordering and Ord/Eq cannot be implemented on types that use different defaults
182/// so if this is the case just convert them to non-defaulted versions before using them).
183/// As well as this a [`Default`] and [`Debug`] trait is always implemented.
184///
185/// ```rust
186/// # use named_tup::tup;
187/// assert_eq!(tup!(rooms: ["garden", "shed"]), tup!(rooms: ["garden", "shed"]));
188///
189/// let rooms = vec!["bathroom", "bedroom"];
190/// let non_copy = tup!(rooms);
191/// assert_eq!(non_copy, non_copy.clone());
192///
193/// let copy = tup!(cows: 4, bulls: 2);
194/// drop(copy);
195/// assert!(copy > tup!(cows: 5, bulls: 1));
196///
197/// // Will print tup { farmer: "Joe", married: true }
198/// println!("{:?}", tup!( married: true, farmer: "Joe"));
199/// ```
200///
201/// Finally the [`Add`](core::ops::Add) trait is implemented so that you can transform between
202/// different tup types. If both sides contain a certain argument, precedence is given to the
203/// right hand side.
204/// ```rust
205/// # use named_tup::tup;
206/// let farm1 = tup!(roosters: 4, dragons: 7, dogs: 1);
207/// let farm2 = tup!(hens: 56, dogs: 3);
208/// let combined_farm = farm1 + farm2;
209///
210/// assert_eq!(combined_farm, tup!(roosters: 4, hens: 56, dragons: 7, dogs: 3));
211/// ```
212pub use named_tup_derive::tup;
213/// An attribute macro that allows you to derive defaults.
214///
215/// Defaults are added to any [`Tup!`] macro by using the equals sign.
216/// [`#[tup_default]`](tup_default) will then change the invocation so that it is a part of the
217/// type information itself. As such [`#[tup_default]`](tup_default) needs to be used on any
218/// item that uses defaults in a [`Tup!`] invocation. Since a defaulted Tup is a type
219/// [`TupInto`] must be used to convert it.
220///
221/// ```rust
222/// # use named_tup::{TupInto, tup, tup_default, Tup};
223/// #[tup_default]
224/// pub fn main() {
225///     let default: Tup!(foo: i32 = 2) = tup!().into_tup();
226///     let result = default_to_non(tup!().into_tup());
227///
228///     assert_eq!(result, tup!(foo: 2));
229///     assert_eq!(result.foo, default.foo);
230/// }
231/// #[tup_default]
232/// fn default_to_non(n_tup: Tup!(foo: i32 = 2)) -> Tup!(foo: i32) {
233///     n_tup.into_tup()
234/// }
235/// ```
236pub use named_tup_derive::tup_default;
237/// Produces a type annotation for the tup struct. If an expression is needed
238/// instead please use the [`tup!`] macro.
239///
240/// It is used in a very similar way to the [`tup!`] macro but with any expression
241/// replaced with a type.
242/// ```rust
243/// # use named_tup::{tup, Tup};
244/// let empty: Tup!() = tup!();
245/// // Since it's just a normal type it can coerce certain literals
246/// let num: Tup!(foo: u8) = tup!(foo: 5);
247///
248/// assert_eq!(test(tup!(foo: 5, bar: 6)), tup!(foo: 5));
249///
250/// // It can also just be used as an argument in functions
251/// fn test(arg: Tup!(foo: i32, bar: i64)) -> Tup!(foo: i32) {
252///     tup!(foo: arg.foo)
253/// }
254/// ```
255///
256/// However it's main use case is to provide default values using the
257/// [`#[tup_default]`](tup_default) attribute macro and the
258/// [`TupInto`] trait to convert between different types.
259///
260/// ```rust
261/// # use named_tup::{TupInto, tup, tup_default, Tup};
262/// #[tup_default]
263/// pub fn main() {
264///     let default: Tup!(foo: i32 = 2) = tup!().into_tup();
265///     let result = default_to_non(tup!().into_tup());
266///
267///     assert_eq!(result, tup!(foo: 2));
268///     assert_eq!(result.foo, default.foo);
269///
270///     // Will print tup { foo: 2 }
271///     println!("{result:?}");
272///
273///     // Will print tup { foo: 2 (=2) } where (=2) is the default value
274///     println!("{default:?}");
275/// }
276/// #[tup_default]
277/// fn default_to_non(n_tup: Tup!(foo: i32 = 2)) -> Tup!(foo: i32) {
278///     n_tup.into_tup()
279/// }
280/// ```
281pub use named_tup_derive::Tup;
282
283mod combine;
284mod convert;
285mod tup_struct;
286
287//Not part of public api.
288#[doc(hidden)]
289pub mod __private {
290    pub use super::tup_struct::{Tup, TupDefault, Unused, Used};
291}