Skip to main content

newtypes/
lib.rs

1/*
2 * SPDX-FileCopyrightText: 2025 CTRLback SCCL.
3 * SPDX-License-Identifier: MIT
4 */
5
6//!
7//! # Newtypes
8//!
9//! The `newtypes` crate is meant to ease the implementation of the
10//! [Newtype](https://rust-unofficial.github.io/patterns/patterns/behavioural/newtype.html)
11//! pattern while trying to make as few assumptions as possible.
12//!
13//! ## Layout guarantee
14//!
15//! Every type produced by every macro in this crate is annotated with
16//! [`#[repr(transparent)]`](https://doc.rust-lang.org/reference/type-layout.html#the-transparent-representation),
17//! so its size and alignment match the inner type's. This is a stable part
18//! of the crate's contract and will not be removed.
19//!
20//! ## `newtype!` Macro
21//!
22//! The `newtype!` macro creates a barebones newtype by wrapping an inner type with
23//! a struct, and, if possible, implementing some extra traits for it.
24//!
25//! By default, all declared structs have visibility `pub`.
26//!
27//! ```rust
28//! use newtypes::*;
29//! use serde::{Deserialize, Serialize};
30//!
31//! newtype!(NewTypeName, u32);
32//!
33//! // In case we want to automatically derive traits (Note that we can
34//! // add as many traits as we need after the `;` character):
35//! newtype!(AnotherTypeName, u32; Deserialize, Serialize);
36//! ```
37//!
38//! Example:
39//! ```rust
40//! use newtypes::*;
41//! use serde::{Deserialize, Serialize};
42//!
43//! newtype!(UserId, u32);
44//!
45//! newtype!(GroupId, u32; Serialize, Deserialize);
46//! ```
47//!
48//! ### Implemented traits
49//!
50//! - For all:
51//!   - [`Debug`](https://doc.rust-lang.org/std/fmt/trait.Debug.html)
52//!   - [`Into<inner_type>`](https://doc.rust-lang.org/std/convert/trait.Into.html)
53//! - For integers:
54//!   - [`Clone`](https://doc.rust-lang.org/std/clone/trait.Clone.html)
55//!   - [`Copy`](https://doc.rust-lang.org/std/marker/trait.Copy.html)
56//!   - [`Hash`](https://doc.rust-lang.org/std/hash/trait.Hash.html)
57//!   - [`PartialEq`](https://doc.rust-lang.org/std/cmp/trait.PartialEq.html)
58//!   - [`Eq`](https://doc.rust-lang.org/std/cmp/trait.Eq.html)
59//! - For floating point numbers:
60//!   - [`Clone`](https://doc.rust-lang.org/std/clone/trait.Clone.html)
61//!   - [`Copy`](https://doc.rust-lang.org/std/marker/trait.Copy.html)
62//!   - [`PartialEq`](https://doc.rust-lang.org/std/cmp/trait.PartialEq.html)
63//! - For `String`:
64//!   - [`Clone`](https://doc.rust-lang.org/std/clone/trait.Clone.html)
65//!   - [`Hash`](https://doc.rust-lang.org/std/hash/trait.Hash.html)
66//!   - [`PartialEq`](https://doc.rust-lang.org/std/cmp/trait.PartialEq.html)
67//!   - [`Eq`](https://doc.rust-lang.org/std/cmp/trait.Eq.html)
68//!
69//! > **IMPORTANT:** The inner value is private. If there are no constraints on the
70//! > inner value, then we can rely on [`newtype_from!`](#newtype_from-macro) macro
71//! > to implement the `From` and `FromStr` traits for us.
72//! >
73//! > Otherwise we can choose to implement
74//! > [`From`](https://doc.rust-lang.org/std/convert/trait.From.html),
75//! > [`FromStr`](https://doc.rust-lang.org/std/str/trait.FromStr.html) and
76//! > [`TryFrom`](https://doc.rust-lang.org/std/convert/trait.TryFrom.html)
77//! > manually.
78//!
79//! ## `newtype_ord!` Macro
80//!
81//! The `newtype_ord!` macro extends the functionality provided with
82//! [`newtype!`](#newtype-macro) by implementing the
83//! [`PartialOrd`](https://doc.rust-lang.org/std/cmp/trait.PartialOrd.html) and
84//! [`Ord`](https://doc.rust-lang.org/std/cmp/trait.Ord.html) traits
85//! (when possible).
86//!
87//! Example:
88//! ```rust
89//! use newtypes::*;
90//! use serde::{Deserialize, Serialize};
91//!
92//! newtype_ord!(Rank, u16);
93//!
94//! newtype_ord!(TicketNumber, u16; Serialize, Deserialize);
95//! ```
96//!
97//! > **NOTE:** It only works for integers, floating point numbers, and `String`.
98//!
99//! ## `newtype_unit!` Macro
100//!
101//! The `newtype_unit!` macro extends the functionality provided with
102//! [`newtype_ord!`](#newtype_ord-macro) by implementing the
103//! [`Add`](https://doc.rust-lang.org/std/ops/trait.Add.html),
104//! [`Sub`](https://doc.rust-lang.org/std/ops/trait.Sub.html),
105//! [`AddAssign`](https://doc.rust-lang.org/std/ops/trait.AddAssign.html),
106//! [`SubAssign`](https://doc.rust-lang.org/std/ops/trait.SubAssign.html), and
107//! [`Default`](https://doc.rust-lang.org/std/default/trait.Default.html) traits.
108//!
109//! Example:
110//! ```rust
111//! use newtypes::*;
112//! use serde::Deserialize;
113//!
114//! newtype_unit!(Weight, f32);
115//!
116//! newtype_unit!(Length, f32; Deserialize);
117//! ```
118//!
119//! > **NOTE:** It only works for integers and floating point numbers.
120//!
121//! > **NOTE:** It does not implement arithmetic operations beyond addition and
122//! > subtraction. Doing that properly would require a more complex library focused
123//! > on dealing with "units" (example: multiplying lengths gives us an area).
124//!
125//! ## `newtype_struct!` Macro
126//!
127//! The `newtype_struct!` macro creates a newtype that wraps a user-defined
128//! struct (or any non-scalar inner type), implementing
129//! [`Debug`](https://doc.rust-lang.org/std/fmt/trait.Debug.html),
130//! [`Clone`](https://doc.rust-lang.org/std/clone/trait.Clone.html),
131//! [`PartialEq`](https://doc.rust-lang.org/std/cmp/trait.PartialEq.html), and
132//! [`Into<inner_type>`](https://doc.rust-lang.org/std/convert/trait.Into.html).
133//!
134//! The inner type must itself implement `Debug + Clone + PartialEq`. Extra
135//! traits (`Copy`, `Hash`, `Eq`, `Ord`, `PartialOrd`, `Serialize`, …) can be
136//! requested by passing them after the `;` separator and will be derived on
137//! the generated struct.
138//!
139//! Example:
140//! ```rust
141//! use newtypes::*;
142//!
143//! #[derive(Debug, Clone, PartialEq)]
144//! pub struct Vec3 { pub x: f32, pub y: f32, pub z: f32 }
145//!
146//! newtype_struct!(Vertex, Vec3);
147//! ```
148//!
149//! ## `newtype_array!` Macro
150//!
151//! The `newtype_array!` macro creates a newtype that wraps a fixed-size array
152//! `[T; N]` and exposes array-like ergonomics: indexing (single element and
153//! ranges), iteration in all three forms (`Self`, `&Self`, `&mut Self`),
154//! inherent `len`, `is_empty`, `iter`, `iter_mut`, `as_array`, `as_array_mut`,
155//! plus `AsRef<[T]>`, `AsMut<[T]>`, and `Into<[T; N]>`.
156//!
157//! `Deref<Target = [T]>` is **not** emitted by default. Use
158//! [`newtype_array_deref!`](#newtype_array_deref-macro) when full
159//! transparent-slice access is desired.
160//!
161//! Default trait derives depend on the element type: integers get
162//! `Copy + Eq + Hash`, floats get `Copy + PartialEq`, `String` gets
163//! `Eq + Hash` (no `Copy`), arbitrary types get the conservative
164//! `Debug + Clone + PartialEq` baseline. Extra derives can be requested
165//! after `;` like every other macro in this crate.
166//!
167//! Example:
168//! ```rust
169//! use newtypes::*;
170//!
171//! newtype_array!(MacAddr, u8, 6);
172//!
173//! let m = MacAddr([0xde, 0xad, 0xbe, 0xef, 0xca, 0xfe]);
174//! assert_eq!(0xde, m[0]);
175//! assert_eq!(6, m.len());
176//! let _slice: &[u8] = &m[1..3];
177//! ```
178//!
179//! With extra derives:
180//! ```rust
181//! use newtypes::*;
182//! use serde::{Deserialize, Serialize};
183//!
184//! newtype_array!(MacAddr, u8, 6; Serialize, Deserialize);
185//! ```
186//!
187//! `From<[T; N]>` is **not** emitted by default. Combine with
188//! [`newtype_from_only!`](#newtype_from_only-macro) if implicit construction
189//! from an array is desired.
190//!
191//! ## `newtype_array_deref!` Macro
192//!
193//! The `newtype_array_deref!` macro behaves exactly like
194//! [`newtype_array!`](#newtype_array-macro) but additionally implements
195//! [`Deref<Target = [T]>`](https://doc.rust-lang.org/std/ops/trait.Deref.html)
196//! and
197//! [`DerefMut`](https://doc.rust-lang.org/std/ops/trait.DerefMut.html).
198//!
199//! This exposes every slice method (`first`, `last`, `contains`, `fill`,
200//! `chunks`, `windows`, `split`, …) directly on the newtype and lets `&Name`
201//! coerce to `&[T]` implicitly. The convenience comes at the cost of
202//! partially erasing the wrapper at call sites, which can defeat the
203//! type-safety motivation of the newtype pattern. Prefer
204//! [`newtype_array!`](#newtype_array-macro) unless you specifically want the
205//! full slice surface.
206//!
207//! Example:
208//! ```rust
209//! use newtypes::*;
210//!
211//! newtype_array_deref!(Buf, u8, 4);
212//!
213//! let b = Buf([1, 2, 3, 4]);
214//! assert_eq!(Some(&1u8), b.first());
215//! assert_eq!(Some(&4u8), b.last());
216//! assert!(b.contains(&3));
217//! ```
218//!
219//! ## `newtype_validated!` Macro
220//!
221//! The `newtype_validated!` macro creates a newtype whose constructor enforces
222//! an invariant. Validation always runs; there is no `unsafe` escape hatch.
223//! Invalid values yield an error.
224//!
225//! The error type is generated alongside the newtype as a zero-sized struct.
226//! Its name must be supplied explicitly because `macro_rules!` cannot
227//! synthesise `{Name}Error` on stable Rust without third-party dependencies.
228//!
229//! `From<inner>` is **not** emitted (it would bypass validation).
230//! [`TryFrom<inner>`](https://doc.rust-lang.org/std/convert/trait.TryFrom.html)
231//! is emitted and delegates to `Self::new`.
232//!
233//! Example:
234//! ```rust
235//! use newtypes::*;
236//!
237//! newtype_validated!(Probability, ProbabilityError, f32, |x: &f32| (0.0..=1.0).contains(x));
238//!
239//! assert!(Probability::new(0.5).is_ok());
240//! assert!(Probability::new(2.0).is_err());
241//! ```
242//!
243//! > **WARNING:** Validation runs only at construction time. Wrapping a type
244//! > with interior mutability (e.g. `RefCell`, `Cell`) defeats the invariant
245//! > because the inner value can mutate after construction.
246//!
247//! > **WARNING:** Combining `newtype_validated!` with `newtype_from!` (or
248//! > `newtype_from_only!`) on the same newtype emits `From<inner>` and
249//! > silently bypasses validation.
250//!
251//! ## `newtype_from!` Macro
252//!
253//! The macro `newtype_from!` implements the `From` and `FromStr` traits for us
254//! in case it's possible.
255//!
256//! It has to be used in combination with one of the other ones
257//! ([`newtype!`](#newtype-macro), [`newtype_ord!`](#newtype_ord-macro), or
258//! [`newtype_unit!`](#newtype_unit-macro)).
259//!
260//! Example:
261//! ```rust
262//! use newtypes::*;
263//!
264//! newtype!(Weight, f32);
265//! newtype_from!(Weight, f32);
266//! ```
267//!
268//! > **NOTE:** It only works for integers, floating point numbers, and `String`.
269//!
270//! ## `newtype_from_only!` Macro
271//!
272//! The macro `newtype_from_only!` implements only the `From` trait, leaving
273//! `FromStr` to the caller. Use it when a type should be constructible from
274//! its inner value but should not parse from text.
275//!
276//! Example:
277//! ```rust
278//! use newtypes::*;
279//!
280//! newtype!(VertexIndex, u32);
281//! newtype_from_only!(VertexIndex, u32);
282//! ```
283//!
284//! > **NOTE:** It works for integers, floating point numbers, `String`, and
285//! > arbitrary inner types.
286//!
287//! ## `newtype_fromstr!` Macro
288//!
289//! The macro `newtype_fromstr!` implements only the `FromStr` trait, leaving
290//! `From<inner>` to the caller. Use it when a type should parse from text but
291//! should not be implicitly constructible from its inner value.
292//!
293//! Example:
294//! ```rust
295//! use newtypes::*;
296//! use std::str::FromStr;
297//!
298//! newtype!(Age, u8);
299//! newtype_fromstr!(Age, u8);
300//!
301//! let a = Age::from_str("42").unwrap();
302//! ```
303//!
304//! > **NOTE:** It only works for integers, floating point numbers, and
305//! > `String`. For arbitrary inner types implement `FromStr` manually.
306//!
307
308#[doc(hidden)]
309#[macro_export]
310macro_rules! _nt_base {
311    ($name:ident, $inner:ty) => {
312        #[repr(transparent)]
313        #[derive(Debug)]
314        pub struct $name($inner);
315
316        impl From<$name> for $inner {
317            fn from(value: $name) -> $inner {
318                value.0
319            }
320        }
321    };
322
323    ($name:ident, $inner:ty; $($derive:path),+) => {
324        #[repr(transparent)]
325        #[derive(Debug, $($derive),+)]
326        pub struct $name($inner);
327
328        impl From<$name> for $inner {
329            fn from(value: $name) -> $inner {
330                value.0
331            }
332        }
333    };
334}
335
336#[doc(hidden)]
337#[macro_export]
338macro_rules! _nt_clone_traits {
339    ($name:ident) => {
340        impl Clone for $name {
341            fn clone(&self) -> Self {
342                Self(self.0.clone())
343            }
344        }
345    };
346}
347
348#[doc(hidden)]
349#[macro_export]
350macro_rules! _nt_copy_traits {
351    ($name:ident) => {
352        impl Clone for $name {
353            fn clone(&self) -> Self {
354                *self
355            }
356        }
357
358        impl Copy for $name {}
359    };
360}
361
362#[doc(hidden)]
363#[macro_export]
364macro_rules! _nt_partialeq_traits {
365    ($name:ident) => {
366        impl PartialEq for $name {
367            fn eq(&self, other: &Self) -> bool {
368                self.0 == other.0
369            }
370        }
371    };
372}
373
374#[doc(hidden)]
375#[macro_export]
376macro_rules! _nt_eq_traits {
377    ($name:ident) => {
378        $crate::_nt_partialeq_traits!($name);
379        impl Eq for $name {}
380    };
381}
382
383#[doc(hidden)]
384#[macro_export]
385macro_rules! _nt_partialord_traits {
386    ($name:ident) => {
387        impl PartialOrd for $name {
388            fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
389                self.0.partial_cmp(&other.0)
390            }
391        }
392    };
393}
394
395#[doc(hidden)]
396#[macro_export]
397macro_rules! _nt_ord_traits {
398    ($name:ident) => {
399        impl Ord for $name {
400            fn cmp(&self, other: &Self) -> std::cmp::Ordering {
401                self.0.cmp(&other.0)
402            }
403        }
404
405        impl PartialOrd for $name {
406            fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
407                Some(self.cmp(other))
408            }
409        }
410    };
411}
412
413#[doc(hidden)]
414#[macro_export]
415macro_rules! _nt_hash_traits {
416    ($name:ident) => {
417        impl std::hash::Hash for $name {
418            fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
419                self.0.hash(state);
420            }
421        }
422    };
423}
424
425#[doc(hidden)]
426#[macro_export]
427macro_rules! _nt_addsub_traits {
428    ($name:ident) => {
429        impl Default for $name {
430            fn default() -> Self {
431                Self(Default::default())
432            }
433        }
434
435        impl std::ops::Add<$name> for $name {
436            type Output = $name;
437
438            fn add(self, rhs: Self) -> Self::Output {
439                $name(self.0 + rhs.0)
440            }
441        }
442
443        impl std::ops::Add<&$name> for $name {
444            type Output = $name;
445
446            fn add(self, rhs: &$name) -> Self::Output {
447                $name(self.0 + rhs.0)
448            }
449        }
450
451        impl std::ops::Add<$name> for &$name {
452            type Output = $name;
453
454            fn add(self, rhs: $name) -> Self::Output {
455                $name(self.0 + rhs.0)
456            }
457        }
458
459        impl std::ops::Add<&$name> for &$name {
460            type Output = $name;
461
462            fn add(self, rhs: &$name) -> Self::Output {
463                $name(self.0 + rhs.0)
464            }
465        }
466
467        impl std::ops::Sub<$name> for $name {
468            type Output = $name;
469
470            fn sub(self, rhs: Self) -> Self::Output {
471                $name(self.0 - rhs.0)
472            }
473        }
474
475        impl std::ops::Sub<&$name> for $name {
476            type Output = $name;
477
478            fn sub(self, rhs: &$name) -> Self::Output {
479                $name(self.0 - rhs.0)
480            }
481        }
482
483        impl std::ops::Sub<$name> for &$name {
484            type Output = $name;
485
486            fn sub(self, rhs: $name) -> Self::Output {
487                $name(self.0 - rhs.0)
488            }
489        }
490
491        impl std::ops::Sub<&$name> for &$name {
492            type Output = $name;
493
494            fn sub(self, rhs: &$name) -> Self::Output {
495                $name(self.0 - rhs.0)
496            }
497        }
498
499        impl std::ops::AddAssign<$name> for $name {
500            fn add_assign(&mut self, rhs: $name) {
501                self.0 += rhs.0;
502            }
503        }
504
505        impl std::ops::AddAssign<&$name> for $name {
506            fn add_assign(&mut self, rhs: &$name) {
507                self.0 += rhs.0;
508            }
509        }
510
511        impl std::ops::SubAssign<$name> for $name {
512            fn sub_assign(&mut self, rhs: $name) {
513                self.0 -= rhs.0;
514            }
515        }
516
517        impl std::ops::SubAssign<&$name> for $name {
518            fn sub_assign(&mut self, rhs: &$name) {
519                self.0 -= rhs.0;
520            }
521        }
522    };
523}
524
525#[doc(hidden)]
526#[macro_export]
527macro_rules! _nt_clone {
528    ($name:ident, $inner:ty) => {
529        $crate::_nt_base!($name, $inner);
530        $crate::_nt_clone_traits!($name);
531    };
532
533    ($name:ident, $inner:ty; $($derive:path),+) => {
534        $crate::_nt_base!($name, $inner; $($derive),+);
535        $crate::_nt_clone_traits!($name);
536    };
537}
538
539#[doc(hidden)]
540#[macro_export]
541macro_rules! _nt_copy {
542    ($name:ident, $inner:ty) => {
543        $crate::_nt_base!($name, $inner);
544        $crate::_nt_copy_traits!($name);
545    };
546
547    ($name:ident, $inner:ty; $($derive:path),+) => {
548        $crate::_nt_base!($name, $inner; $($derive),+);
549        $crate::_nt_copy_traits!($name);
550    };
551}
552
553#[doc(hidden)]
554#[macro_export]
555macro_rules! _nt_int {
556    ($name:ident, $inner:ty) => {
557        $crate::_nt_copy!($name, $inner);
558        $crate::_nt_eq_traits!($name);
559        $crate::_nt_hash_traits!($name);
560    };
561
562    ($name:ident, $inner:ty; $($derive:path),+) => {
563        $crate::_nt_copy!($name, $inner; $($derive),+);
564        $crate::_nt_eq_traits!($name);
565        $crate::_nt_hash_traits!($name);
566    };
567}
568
569#[doc(hidden)]
570#[macro_export]
571macro_rules! _nt_float {
572    ($name:ident, $inner:ty) => {
573        $crate::_nt_copy!($name, $inner);
574        $crate::_nt_partialeq_traits!($name);
575    };
576
577    ($name:ident, $inner:ty; $($derive:path),+) => {
578        $crate::_nt_copy!($name, $inner; $($derive),+);
579        $crate::_nt_partialeq_traits!($name);
580    };
581}
582
583#[doc(hidden)]
584#[macro_export]
585macro_rules! _nt_string {
586    ($name:ident) => {
587        $crate::_nt_clone!($name, String);
588        $crate::_nt_eq_traits!($name);
589        $crate::_nt_hash_traits!($name);
590    };
591
592    ($name:ident; $($derive:path),+) => {
593        $crate::_nt_clone!($name, String; $($derive),+);
594        $crate::_nt_eq_traits!($name);
595        $crate::_nt_hash_traits!($name);
596    };
597}
598
599#[doc(hidden)]
600#[macro_export]
601macro_rules! _nt_int_ord {
602    ($name:ident, $inner:ty) => {
603        $crate::_nt_int!($name, $inner);
604        $crate::_nt_ord_traits!($name);
605    };
606
607    ($name:ident, $inner:ty; $($derive:path),+) => {
608        $crate::_nt_int!($name, $inner; $($derive),+);
609        $crate::_nt_ord_traits!($name);
610    };
611}
612
613#[doc(hidden)]
614#[macro_export]
615macro_rules! _nt_float_ord {
616    ($name:ident, $inner:ty) => {
617        $crate::_nt_float!($name, $inner);
618        $crate::_nt_partialord_traits!($name);
619    };
620
621    ($name:ident, $inner:ty; $($derive:path),+) => {
622        $crate::_nt_float!($name, $inner; $($derive),+);
623        $crate::_nt_partialord_traits!($name);
624    };
625}
626
627#[doc(hidden)]
628#[macro_export]
629macro_rules! _nt_string_ord {
630    ($name:ident) => {
631        $crate::_nt_string!($name);
632        $crate::_nt_ord_traits!($name);
633    };
634
635    ($name:ident; $($derive:path),+) => {
636        $crate::_nt_string!($name; $($derive),+);
637        $crate::_nt_ord_traits!($name);
638    };
639}
640
641#[doc(hidden)]
642#[macro_export]
643macro_rules! _nt_int_unit {
644    ($name:ident, $inner:ty) => {
645        $crate::_nt_int_ord!($name, $inner);
646        $crate::_nt_addsub_traits!($name);
647    };
648
649    ($name:ident, $inner:ty; $($derive:path),+) => {
650        $crate::_nt_int_ord!($name, $inner; $($derive),+);
651        $crate::_nt_addsub_traits!($name);
652    };
653}
654
655#[doc(hidden)]
656#[macro_export]
657macro_rules! _nt_float_unit {
658    ($name:ident, $inner:ty) => {
659        $crate::_nt_float_ord!($name, $inner);
660        $crate::_nt_addsub_traits!($name);
661    };
662
663    ($name:ident, $inner:ty; $($derive:path),+) => {
664        $crate::_nt_float_ord!($name, $inner; $($derive),+);
665        $crate::_nt_addsub_traits!($name);
666    };
667}
668
669#[doc(hidden)]
670#[macro_export]
671macro_rules! _nt_from_traits {
672    ($name:ident, $inner:ty) => {
673        impl From<$inner> for $name {
674            #[inline(always)]
675            fn from(value: $inner) -> Self {
676                $name(value)
677            }
678        }
679    };
680}
681
682#[doc(hidden)]
683#[macro_export]
684macro_rules! _nt_fromstr_traits {
685    ($name:ident, $inner:ty, $err:ty) => {
686        impl std::str::FromStr for $name {
687            type Err = $err;
688
689            fn from_str(s: &str) -> Result<Self, Self::Err> {
690                match <$inner>::from_str(s) {
691                    Ok(v) => Ok($name(v)),
692                    Err(e) => Err(e),
693                }
694            }
695        }
696    };
697}
698
699#[doc(hidden)]
700#[macro_export]
701macro_rules! _nt_int_from {
702    ($name:ident, $inner:ty) => {
703        $crate::_nt_from_traits!($name, $inner);
704        $crate::_nt_fromstr_traits!($name, $inner, std::num::ParseIntError);
705    };
706}
707
708#[doc(hidden)]
709#[macro_export]
710macro_rules! _nt_float_from {
711    ($name:ident, $inner:ty) => {
712        $crate::_nt_from_traits!($name, $inner);
713        $crate::_nt_fromstr_traits!($name, $inner, std::num::ParseFloatError);
714    };
715}
716
717/// The `newtype!` macro creates a barebones newtype by wrapping an inner type with
718/// a struct, and, if possible, implementing some extra traits for it.
719///
720/// By default, all declared structs have visibility `pub`.
721///
722/// ```rust
723/// use newtypes::*;
724///
725/// newtype!(NewTypeName, u32);
726/// ```
727///
728/// In case we want to automatically derive traits (like serde's
729/// `Serialize` or `Deserialize`):
730/// ```rust
731/// use newtypes::*;
732/// use serde::{Deserialize, Serialize};
733///
734/// newtype!(NewTypeName, u32; Deserialize, Serialize);
735/// ```
736///
737/// Example:
738/// ```rust
739/// use newtypes::*;
740/// use serde::{Deserialize, Serialize};
741///
742/// newtype!(UserId, u32);
743///
744/// newtype!(GroupId, u32; Serialize, Deserialize);
745/// ```
746#[macro_export]
747macro_rules! newtype {
748    ($name:ident, i8) => { $crate::_nt_int!($name, i8); };
749    ($name:ident, u8) => { $crate::_nt_int!($name, u8); };
750    ($name:ident, i16) => { $crate::_nt_int!($name, i16); };
751    ($name:ident, u16) => { $crate::_nt_int!($name, u16); };
752    ($name:ident, i32) => { $crate::_nt_int!($name, i32); };
753    ($name:ident, u32) => { $crate::_nt_int!($name, u32); };
754    ($name:ident, i64) => { $crate::_nt_int!($name, i64); };
755    ($name:ident, u64) => { $crate::_nt_int!($name, u64); };
756    ($name:ident, i128) => { $crate::_nt_int!($name, i128); };
757    ($name:ident, u128) => { $crate::_nt_int!($name, u128); };
758    ($name:ident, isize) => { $crate::_nt_int!($name, isize); };
759    ($name:ident, usize) => { $crate::_nt_int!($name, usize); };
760    ($name:ident, i8; $($derive:path),+) => { $crate::_nt_int!($name, i8; $($derive),+); };
761    ($name:ident, u8; $($derive:path),+) => { $crate::_nt_int!($name, u8; $($derive),+); };
762    ($name:ident, i16; $($derive:path),+) => { $crate::_nt_int!($name, i16; $($derive),+); };
763    ($name:ident, u16; $($derive:path),+) => { $crate::_nt_int!($name, u16; $($derive),+); };
764    ($name:ident, i32; $($derive:path),+) => { $crate::_nt_int!($name, i32; $($derive),+); };
765    ($name:ident, u32; $($derive:path),+) => { $crate::_nt_int!($name, u32; $($derive),+); };
766    ($name:ident, i64; $($derive:path),+) => { $crate::_nt_int!($name, i64; $($derive),+); };
767    ($name:ident, u64; $($derive:path),+) => { $crate::_nt_int!($name, u64; $($derive),+); };
768    ($name:ident, i128; $($derive:path),+) => { $crate::_nt_int!($name, i128; $($derive),+); };
769    ($name:ident, u128; $($derive:path),+) => { $crate::_nt_int!($name, u128; $($derive),+); };
770    ($name:ident, isize; $($derive:path),+) => { $crate::_nt_int!($name, isize; $($derive),+); };
771    ($name:ident, usize; $($derive:path),+) => { $crate::_nt_int!($name, usize; $($derive),+); };
772
773    ($name:ident, f32) => { $crate::_nt_float!($name, f32); };
774    ($name:ident, f64) => { $crate::_nt_float!($name, f64); };
775    ($name:ident, f32; $($derive:path),+) => { $crate::_nt_float!($name, f32; $($derive),+); };
776    ($name:ident, f64; $($derive:path),+) => { $crate::_nt_float!($name, f64; $($derive),+); };
777
778    ($name:ident, String) => { $crate::_nt_string!($name); };
779    ($name:ident, String; $($derive:path),+) => { $crate::_nt_string!($name; $($derive),+); };
780
781    ($name:ident, $inner:ty) => {
782        $crate::_nt_base!($name, $inner);
783    };
784    ($name:ident, $inner:ty; $($derive:path),+) => {
785        $crate::_nt_base!($name, $inner; $($derive),+);
786    }
787}
788
789/// The `newtype_ord!` macro extends the functionality provided with
790/// `newtype!` by implementing the
791/// [`PartialOrd`](https://doc.rust-lang.org/std/cmp/trait.PartialOrd.html) and
792/// [`Ord`](https://doc.rust-lang.org/std/cmp/trait.Ord.html) traits
793/// (when possible).
794///
795/// Example:
796/// ```rust
797/// use newtypes::*;
798/// use serde::{Deserialize, Serialize};
799///
800/// newtype_ord!(Rank, u16);
801///
802/// newtype_ord!(TicketNumber, u16; Serialize, Deserialize);
803/// ```
804///
805/// > **NOTE:** It only works for integers, floating point numbers, and `String`.
806#[macro_export]
807macro_rules! newtype_ord {
808    ($name:ident, i8) => { $crate::_nt_int_ord!($name, i8); };
809    ($name:ident, u8) => { $crate::_nt_int_ord!($name, u8); };
810    ($name:ident, i16) => { $crate::_nt_int_ord!($name, i16); };
811    ($name:ident, u16) => { $crate::_nt_int_ord!($name, u16); };
812    ($name:ident, i32) => { $crate::_nt_int_ord!($name, i32); };
813    ($name:ident, u32) => { $crate::_nt_int_ord!($name, u32); };
814    ($name:ident, i64) => { $crate::_nt_int_ord!($name, i64); };
815    ($name:ident, u64) => { $crate::_nt_int_ord!($name, u64); };
816    ($name:ident, i128) => { $crate::_nt_int_ord!($name, i128); };
817    ($name:ident, u128) => { $crate::_nt_int_ord!($name, u128); };
818    ($name:ident, isize) => { $crate::_nt_int_ord!($name, isize); };
819    ($name:ident, usize) => { $crate::_nt_int_ord!($name, usize); };
820    ($name:ident, i8; $($derive:path),+) => { $crate::_nt_int_ord!($name, i8; $($derive),+); };
821    ($name:ident, u8; $($derive:path),+) => { $crate::_nt_int_ord!($name, u8; $($derive),+); };
822    ($name:ident, i16; $($derive:path),+) => { $crate::_nt_int_ord!($name, i16; $($derive),+); };
823    ($name:ident, u16; $($derive:path),+) => { $crate::_nt_int_ord!($name, u16; $($derive),+); };
824    ($name:ident, i32; $($derive:path),+) => { $crate::_nt_int_ord!($name, i32; $($derive),+); };
825    ($name:ident, u32; $($derive:path),+) => { $crate::_nt_int_ord!($name, u32; $($derive),+); };
826    ($name:ident, i64; $($derive:path),+) => { $crate::_nt_int_ord!($name, i64; $($derive),+); };
827    ($name:ident, u64; $($derive:path),+) => { $crate::_nt_int_ord!($name, u64; $($derive),+); };
828    ($name:ident, i128; $($derive:path),+) => { $crate::_nt_int_ord!($name, i128; $($derive),+); };
829    ($name:ident, u128; $($derive:path),+) => { $crate::_nt_int_ord!($name, u128; $($derive),+); };
830    ($name:ident, isize; $($derive:path),+) => { $crate::_nt_int_ord!($name, isize; $($derive),+); };
831    ($name:ident, usize; $($derive:path),+) => { $crate::_nt_int_ord!($name, usize; $($derive),+); };
832
833    ($name:ident, f32) => { $crate::_nt_float_ord!($name, f32); };
834    ($name:ident, f64) => { $crate::_nt_float_ord!($name, f64); };
835    ($name:ident, f32; $($derive:path),+) => { $crate::_nt_float_ord!($name, f32; $($derive),+); };
836    ($name:ident, f64; $($derive:path),+) => { $crate::_nt_float_ord!($name, f64; $($derive),+); };
837
838    ($name:ident, String) => { $crate::_nt_string_ord!($name); };
839    ($name:ident, String; $($derive:path),+) => { $crate::_nt_string_ord!($name; $($derive),+); };
840}
841
842/// The `newtype_unit!` macro extends the functionality provided with
843/// `newtype_ord!` by implementing the
844/// [`Add`](https://doc.rust-lang.org/std/ops/trait.Add.html),
845/// [`Sub`](https://doc.rust-lang.org/std/ops/trait.Sub.html),
846/// [`AddAssign`](https://doc.rust-lang.org/std/ops/trait.AddAssign.html),
847/// [`SubAssign`](https://doc.rust-lang.org/std/ops/trait.SubAssign.html), and
848/// [`Default`](https://doc.rust-lang.org/std/default/trait.Default.html) traits.
849///
850/// Example:
851/// ```rust
852/// use newtypes::*;
853/// use serde::Deserialize;
854///
855/// newtype_unit!(Weight, f32);
856///
857/// newtype_unit!(Length, f32; Deserialize);
858/// ```
859///
860/// > **NOTE:** It only works for integers and floating point numbers.
861///
862/// > **NOTE:** It does not implement arithmetic operations beyond addition and
863/// > subtraction. Doing that properly would require a more complex library focused
864/// > on dealing with "units" (example: multiplying lengths gives us an area).
865#[macro_export]
866macro_rules! newtype_unit {
867    ($name:ident, i8) => { $crate::_nt_int_unit!($name, i8); };
868    ($name:ident, u8) => { $crate::_nt_int_unit!($name, u8); };
869    ($name:ident, i16) => { $crate::_nt_int_unit!($name, i16); };
870    ($name:ident, u16) => { $crate::_nt_int_unit!($name, u16); };
871    ($name:ident, i32) => { $crate::_nt_int_unit!($name, i32); };
872    ($name:ident, u32) => { $crate::_nt_int_unit!($name, u32); };
873    ($name:ident, i64) => { $crate::_nt_int_unit!($name, i64); };
874    ($name:ident, u64) => { $crate::_nt_int_unit!($name, u64); };
875    ($name:ident, i128) => { $crate::_nt_int_unit!($name, i128); };
876    ($name:ident, u128) => { $crate::_nt_int_unit!($name, u128); };
877    ($name:ident, isize) => { $crate::_nt_int_unit!($name, isize); };
878    ($name:ident, usize) => { $crate::_nt_int_unit!($name, usize); };
879    ($name:ident, i8; $($derive:path),+) => { $crate::_nt_int_unit!($name, i8; $($derive),+); };
880    ($name:ident, u8; $($derive:path),+) => { $crate::_nt_int_unit!($name, u8; $($derive),+); };
881    ($name:ident, i16; $($derive:path),+) => { $crate::_nt_int_unit!($name, i16; $($derive),+); };
882    ($name:ident, u16; $($derive:path),+) => { $crate::_nt_int_unit!($name, u16; $($derive),+); };
883    ($name:ident, i32; $($derive:path),+) => { $crate::_nt_int_unit!($name, i32; $($derive),+); };
884    ($name:ident, u32; $($derive:path),+) => { $crate::_nt_int_unit!($name, u32; $($derive),+); };
885    ($name:ident, i64; $($derive:path),+) => { $crate::_nt_int_unit!($name, i64; $($derive),+); };
886    ($name:ident, u64; $($derive:path),+) => { $crate::_nt_int_unit!($name, u64; $($derive),+); };
887    ($name:ident, i128; $($derive:path),+) => { $crate::_nt_int_unit!($name, i128; $($derive),+); };
888    ($name:ident, u128; $($derive:path),+) => { $crate::_nt_int_unit!($name, u128; $($derive),+); };
889    ($name:ident, isize; $($derive:path),+) => { $crate::_nt_int_unit!($name, isize; $($derive),+); };
890    ($name:ident, usize; $($derive:path),+) => { $crate::_nt_int_unit!($name, usize; $($derive),+); };
891
892    ($name:ident, f32) => { $crate::_nt_float_unit!($name, f32); };
893    ($name:ident, f64) => { $crate::_nt_float_unit!($name, f64); };
894    ($name:ident, f32; $($derive:path),+) => { $crate::_nt_float_unit!($name, f32; $($derive),+); };
895    ($name:ident, f64; $($derive:path),+) => { $crate::_nt_float_unit!($name, f64; $($derive),+); };
896}
897
898/// The `newtype_struct!` macro creates a newtype that wraps a user-defined
899/// struct (or any non-scalar inner type), implementing `Debug`, `Clone`,
900/// `PartialEq`, and `Into<inner>`.
901///
902/// The inner type must itself implement `Debug + Clone + PartialEq`. If
903/// extra traits are needed (`Copy`, `Hash`, `Eq`, `Ord`, `PartialOrd`,
904/// `Serialize`, …) they can be passed after the `;` separator and will be
905/// derived on the generated struct.
906///
907/// Example:
908/// ```rust
909/// use newtypes::*;
910///
911/// #[derive(Debug, Clone, PartialEq)]
912/// pub struct Vec3 { pub x: f32, pub y: f32, pub z: f32 }
913///
914/// newtype_struct!(Vertex, Vec3);
915/// ```
916///
917/// With extra derives:
918/// ```rust
919/// use newtypes::*;
920/// use serde::{Deserialize, Serialize};
921///
922/// #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
923/// pub struct Vec3 { pub x: f32, pub y: f32, pub z: f32 }
924///
925/// newtype_struct!(Vertex, Vec3; Serialize, Deserialize);
926/// ```
927#[macro_export]
928macro_rules! newtype_struct {
929    ($name:ident, $inner:ty) => {
930        $crate::_nt_base!($name, $inner);
931        $crate::_nt_clone_traits!($name);
932        $crate::_nt_partialeq_traits!($name);
933    };
934
935    ($name:ident, $inner:ty; $($derive:path),+) => {
936        $crate::_nt_base!($name, $inner; $($derive),+);
937        $crate::_nt_clone_traits!($name);
938        $crate::_nt_partialeq_traits!($name);
939    };
940}
941
942#[doc(hidden)]
943#[macro_export]
944macro_rules! _nt_validated_impls {
945    ($name:ident, $err:ident, $inner:ty, $validator:expr) => {
946        #[derive(Debug, Clone, Copy, PartialEq, Eq)]
947        pub struct $err;
948
949        impl ::std::fmt::Display for $err {
950            fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
951                write!(f, concat!("invalid ", stringify!($name), " value"))
952            }
953        }
954
955        impl ::std::error::Error for $err {}
956
957        impl $name {
958            pub fn new(value: $inner) -> ::std::result::Result<Self, $err> {
959                if ($validator)(&value) {
960                    Ok($name(value))
961                } else {
962                    Err($err)
963                }
964            }
965        }
966
967        impl ::std::convert::TryFrom<$inner> for $name {
968            type Error = $err;
969
970            fn try_from(value: $inner) -> ::std::result::Result<Self, Self::Error> {
971                Self::new(value)
972            }
973        }
974    };
975}
976
977/// The `newtype_validated!` macro creates a newtype whose constructor enforces
978/// an invariant. Validation always runs; there is no `unsafe` escape hatch.
979/// Invalid values yield `Err(<ErrorName>)`.
980///
981/// The error type is generated alongside the newtype as a zero-sized struct
982/// implementing `Debug + Clone + Copy + PartialEq + Eq + Display + Error`.
983/// Its name must be supplied explicitly because `macro_rules!` cannot
984/// synthesise `{Name}Error` without third-party dependencies.
985///
986/// `From<inner>` is **not** emitted (it would bypass validation). `TryFrom<inner>`
987/// is emitted and delegates to `Self::new`.
988///
989/// The validator must be an expression callable as `Fn(&inner) -> bool`.
990/// Closures and free-function paths both work.
991///
992/// The inner type must implement `Debug + Clone + PartialEq`.
993///
994/// > **WARNING:** Validation runs only at construction time. Wrapping a type
995/// > with interior mutability (e.g. `RefCell`, `Cell`) defeats the invariant
996/// > because the inner value can mutate after construction.
997///
998/// > **WARNING:** Combining `newtype_validated!` with `newtype_from!` (or
999/// > `newtype_from_only!`) on the same newtype emits `From<inner>` and
1000/// > silently bypasses validation. Do not do this.
1001///
1002/// Example with a closure:
1003/// ```rust
1004/// use newtypes::*;
1005///
1006/// newtype_validated!(Probability, ProbabilityError, f32, |x: &f32| (0.0..=1.0).contains(x));
1007///
1008/// assert!(Probability::new(0.5).is_ok());
1009/// assert!(Probability::new(2.0).is_err());
1010/// ```
1011///
1012/// Example with a free function:
1013/// ```rust
1014/// use newtypes::*;
1015///
1016/// fn is_even(x: &u32) -> bool { x % 2 == 0 }
1017/// newtype_validated!(EvenU32, EvenU32Error, u32, is_even);
1018///
1019/// assert!(EvenU32::new(4).is_ok());
1020/// assert!(EvenU32::new(5).is_err());
1021/// ```
1022#[macro_export]
1023macro_rules! newtype_validated {
1024    ($name:ident, $err:ident, $inner:ty, $validator:expr) => {
1025        $crate::_nt_base!($name, $inner);
1026        $crate::_nt_clone_traits!($name);
1027        $crate::_nt_partialeq_traits!($name);
1028        $crate::_nt_validated_impls!($name, $err, $inner, $validator);
1029    };
1030
1031    ($name:ident, $err:ident, $inner:ty, $validator:expr; $($derive:path),+) => {
1032        $crate::_nt_base!($name, $inner; $($derive),+);
1033        $crate::_nt_clone_traits!($name);
1034        $crate::_nt_partialeq_traits!($name);
1035        $crate::_nt_validated_impls!($name, $err, $inner, $validator);
1036    };
1037}
1038
1039#[doc(hidden)]
1040#[macro_export]
1041macro_rules! _nt_array_base {
1042    ($name:ident, $t:ty, $n:expr) => {
1043        #[repr(transparent)]
1044        #[derive(Debug)]
1045        pub struct $name([$t; $n]);
1046
1047        impl From<$name> for [$t; $n] {
1048            fn from(value: $name) -> [$t; $n] {
1049                value.0
1050            }
1051        }
1052    };
1053
1054    ($name:ident, $t:ty, $n:expr; $($derive:path),+) => {
1055        #[repr(transparent)]
1056        #[derive(Debug, $($derive),+)]
1057        pub struct $name([$t; $n]);
1058
1059        impl From<$name> for [$t; $n] {
1060            fn from(value: $name) -> [$t; $n] {
1061                value.0
1062            }
1063        }
1064    };
1065}
1066
1067#[doc(hidden)]
1068#[macro_export]
1069macro_rules! _nt_array_ops {
1070    ($name:ident, $t:ty, $n:expr) => {
1071        impl<I: std::slice::SliceIndex<[$t]>> std::ops::Index<I> for $name {
1072            type Output = I::Output;
1073
1074            #[inline]
1075            fn index(&self, index: I) -> &Self::Output {
1076                std::ops::Index::index(&self.0[..], index)
1077            }
1078        }
1079
1080        impl<I: std::slice::SliceIndex<[$t]>> std::ops::IndexMut<I> for $name {
1081            #[inline]
1082            fn index_mut(&mut self, index: I) -> &mut Self::Output {
1083                std::ops::IndexMut::index_mut(&mut self.0[..], index)
1084            }
1085        }
1086
1087        impl AsRef<[$t]> for $name {
1088            #[inline]
1089            fn as_ref(&self) -> &[$t] {
1090                &self.0[..]
1091            }
1092        }
1093
1094        impl AsMut<[$t]> for $name {
1095            #[inline]
1096            fn as_mut(&mut self) -> &mut [$t] {
1097                &mut self.0[..]
1098            }
1099        }
1100
1101        impl<'a> IntoIterator for &'a $name {
1102            type Item = &'a $t;
1103            type IntoIter = std::slice::Iter<'a, $t>;
1104
1105            #[inline]
1106            fn into_iter(self) -> Self::IntoIter {
1107                self.0.iter()
1108            }
1109        }
1110
1111        impl<'a> IntoIterator for &'a mut $name {
1112            type Item = &'a mut $t;
1113            type IntoIter = std::slice::IterMut<'a, $t>;
1114
1115            #[inline]
1116            fn into_iter(self) -> Self::IntoIter {
1117                self.0.iter_mut()
1118            }
1119        }
1120
1121        impl IntoIterator for $name {
1122            type Item = $t;
1123            type IntoIter = std::array::IntoIter<$t, $n>;
1124
1125            #[inline]
1126            fn into_iter(self) -> Self::IntoIter {
1127                self.0.into_iter()
1128            }
1129        }
1130
1131        impl $name {
1132            #[inline]
1133            pub const fn len(&self) -> usize {
1134                $n
1135            }
1136
1137            #[inline]
1138            pub const fn is_empty(&self) -> bool {
1139                $n == 0
1140            }
1141
1142            #[inline]
1143            pub fn iter(&self) -> std::slice::Iter<'_, $t> {
1144                self.0.iter()
1145            }
1146
1147            #[inline]
1148            pub fn iter_mut(&mut self) -> std::slice::IterMut<'_, $t> {
1149                self.0.iter_mut()
1150            }
1151
1152            #[inline]
1153            pub const fn as_array(&self) -> &[$t; $n] {
1154                &self.0
1155            }
1156
1157            #[inline]
1158            pub const fn as_array_mut(&mut self) -> &mut [$t; $n] {
1159                &mut self.0
1160            }
1161        }
1162    };
1163}
1164
1165#[doc(hidden)]
1166#[macro_export]
1167macro_rules! _nt_array_deref_impls {
1168    ($name:ident, $t:ty) => {
1169        impl std::ops::Deref for $name {
1170            type Target = [$t];
1171
1172            #[inline]
1173            fn deref(&self) -> &[$t] {
1174                &self.0[..]
1175            }
1176        }
1177
1178        impl std::ops::DerefMut for $name {
1179            #[inline]
1180            fn deref_mut(&mut self) -> &mut [$t] {
1181                &mut self.0[..]
1182            }
1183        }
1184    };
1185}
1186
1187#[doc(hidden)]
1188#[macro_export]
1189macro_rules! _nt_array_int {
1190    ($name:ident, $t:ty, $n:expr) => {
1191        $crate::_nt_array_base!($name, $t, $n);
1192        $crate::_nt_copy_traits!($name);
1193        $crate::_nt_eq_traits!($name);
1194        $crate::_nt_hash_traits!($name);
1195        $crate::_nt_array_ops!($name, $t, $n);
1196    };
1197
1198    ($name:ident, $t:ty, $n:expr; $($derive:path),+) => {
1199        $crate::_nt_array_base!($name, $t, $n; $($derive),+);
1200        $crate::_nt_copy_traits!($name);
1201        $crate::_nt_eq_traits!($name);
1202        $crate::_nt_hash_traits!($name);
1203        $crate::_nt_array_ops!($name, $t, $n);
1204    };
1205}
1206
1207#[doc(hidden)]
1208#[macro_export]
1209macro_rules! _nt_array_float {
1210    ($name:ident, $t:ty, $n:expr) => {
1211        $crate::_nt_array_base!($name, $t, $n);
1212        $crate::_nt_copy_traits!($name);
1213        $crate::_nt_partialeq_traits!($name);
1214        $crate::_nt_array_ops!($name, $t, $n);
1215    };
1216
1217    ($name:ident, $t:ty, $n:expr; $($derive:path),+) => {
1218        $crate::_nt_array_base!($name, $t, $n; $($derive),+);
1219        $crate::_nt_copy_traits!($name);
1220        $crate::_nt_partialeq_traits!($name);
1221        $crate::_nt_array_ops!($name, $t, $n);
1222    };
1223}
1224
1225#[doc(hidden)]
1226#[macro_export]
1227macro_rules! _nt_array_string {
1228    ($name:ident, $n:expr) => {
1229        $crate::_nt_array_base!($name, String, $n);
1230        $crate::_nt_clone_traits!($name);
1231        $crate::_nt_eq_traits!($name);
1232        $crate::_nt_hash_traits!($name);
1233        $crate::_nt_array_ops!($name, String, $n);
1234    };
1235
1236    ($name:ident, $n:expr; $($derive:path),+) => {
1237        $crate::_nt_array_base!($name, String, $n; $($derive),+);
1238        $crate::_nt_clone_traits!($name);
1239        $crate::_nt_eq_traits!($name);
1240        $crate::_nt_hash_traits!($name);
1241        $crate::_nt_array_ops!($name, String, $n);
1242    };
1243}
1244
1245#[doc(hidden)]
1246#[macro_export]
1247macro_rules! _nt_array_generic {
1248    ($name:ident, $t:ty, $n:expr) => {
1249        $crate::_nt_array_base!($name, $t, $n);
1250        $crate::_nt_clone_traits!($name);
1251        $crate::_nt_partialeq_traits!($name);
1252        $crate::_nt_array_ops!($name, $t, $n);
1253    };
1254
1255    ($name:ident, $t:ty, $n:expr; $($derive:path),+) => {
1256        $crate::_nt_array_base!($name, $t, $n; $($derive),+);
1257        $crate::_nt_clone_traits!($name);
1258        $crate::_nt_partialeq_traits!($name);
1259        $crate::_nt_array_ops!($name, $t, $n);
1260    };
1261}
1262
1263/// The `newtype_array!` macro creates a newtype that wraps a fixed-size array
1264/// `[T; N]` and exposes array-like ergonomics: indexing (single element and
1265/// ranges), iteration in all three forms (`Self`, `&Self`, `&mut Self`),
1266/// inherent `len`, `is_empty`, `iter`, `iter_mut`, `as_array`, `as_array_mut`,
1267/// plus `AsRef<[T]>`, `AsMut<[T]>`, and `Into<[T; N]>`.
1268///
1269/// `Deref<Target = [T]>` is **not** emitted (it would erase the wrapper at
1270/// every method call and defeat the type-safety reason to introduce a
1271/// newtype). For users who explicitly want full transparent-slice access, use
1272/// [`newtype_array_deref!`](#newtype_array_deref-macro) instead.
1273///
1274/// `From<[T; N]>` is **not** emitted by default. Pair the macro with
1275/// [`newtype_from_only!`](#newtype_from_only-macro) if implicit construction
1276/// from an array is desired.
1277///
1278/// Default derives depend on the element type:
1279/// - integers (`i8`..`i128`, `u8`..`u128`, `isize`, `usize`):
1280///   `Debug, Clone, Copy, PartialEq, Eq, Hash`
1281/// - floats (`f32`, `f64`): `Debug, Clone, Copy, PartialEq`
1282/// - `String`: `Debug, Clone, PartialEq, Eq, Hash`
1283/// - any other element type: `Debug, Clone, PartialEq` (the inner type must
1284///   itself implement these)
1285///
1286/// Extra derives can be requested after `;`.
1287///
1288/// Example:
1289/// ```rust
1290/// use newtypes::*;
1291///
1292/// newtype_array!(MacAddr, u8, 6);
1293///
1294/// let m = MacAddr([0xde, 0xad, 0xbe, 0xef, 0xca, 0xfe]);
1295/// assert_eq!(0xde, m[0]);
1296/// assert_eq!(6, m.len());
1297/// for byte in &m { let _ = byte; }
1298/// ```
1299///
1300/// With extra derives:
1301/// ```rust
1302/// use newtypes::*;
1303/// use serde::{Deserialize, Serialize};
1304///
1305/// newtype_array!(MacAddr, u8, 6; Serialize, Deserialize);
1306/// ```
1307#[macro_export]
1308macro_rules! newtype_array {
1309    ($name:ident, i8, $n:expr) => { $crate::_nt_array_int!($name, i8, $n); };
1310    ($name:ident, u8, $n:expr) => { $crate::_nt_array_int!($name, u8, $n); };
1311    ($name:ident, i16, $n:expr) => { $crate::_nt_array_int!($name, i16, $n); };
1312    ($name:ident, u16, $n:expr) => { $crate::_nt_array_int!($name, u16, $n); };
1313    ($name:ident, i32, $n:expr) => { $crate::_nt_array_int!($name, i32, $n); };
1314    ($name:ident, u32, $n:expr) => { $crate::_nt_array_int!($name, u32, $n); };
1315    ($name:ident, i64, $n:expr) => { $crate::_nt_array_int!($name, i64, $n); };
1316    ($name:ident, u64, $n:expr) => { $crate::_nt_array_int!($name, u64, $n); };
1317    ($name:ident, i128, $n:expr) => { $crate::_nt_array_int!($name, i128, $n); };
1318    ($name:ident, u128, $n:expr) => { $crate::_nt_array_int!($name, u128, $n); };
1319    ($name:ident, isize, $n:expr) => { $crate::_nt_array_int!($name, isize, $n); };
1320    ($name:ident, usize, $n:expr) => { $crate::_nt_array_int!($name, usize, $n); };
1321    ($name:ident, i8, $n:expr; $($derive:path),+) => { $crate::_nt_array_int!($name, i8, $n; $($derive),+); };
1322    ($name:ident, u8, $n:expr; $($derive:path),+) => { $crate::_nt_array_int!($name, u8, $n; $($derive),+); };
1323    ($name:ident, i16, $n:expr; $($derive:path),+) => { $crate::_nt_array_int!($name, i16, $n; $($derive),+); };
1324    ($name:ident, u16, $n:expr; $($derive:path),+) => { $crate::_nt_array_int!($name, u16, $n; $($derive),+); };
1325    ($name:ident, i32, $n:expr; $($derive:path),+) => { $crate::_nt_array_int!($name, i32, $n; $($derive),+); };
1326    ($name:ident, u32, $n:expr; $($derive:path),+) => { $crate::_nt_array_int!($name, u32, $n; $($derive),+); };
1327    ($name:ident, i64, $n:expr; $($derive:path),+) => { $crate::_nt_array_int!($name, i64, $n; $($derive),+); };
1328    ($name:ident, u64, $n:expr; $($derive:path),+) => { $crate::_nt_array_int!($name, u64, $n; $($derive),+); };
1329    ($name:ident, i128, $n:expr; $($derive:path),+) => { $crate::_nt_array_int!($name, i128, $n; $($derive),+); };
1330    ($name:ident, u128, $n:expr; $($derive:path),+) => { $crate::_nt_array_int!($name, u128, $n; $($derive),+); };
1331    ($name:ident, isize, $n:expr; $($derive:path),+) => { $crate::_nt_array_int!($name, isize, $n; $($derive),+); };
1332    ($name:ident, usize, $n:expr; $($derive:path),+) => { $crate::_nt_array_int!($name, usize, $n; $($derive),+); };
1333
1334    ($name:ident, f32, $n:expr) => { $crate::_nt_array_float!($name, f32, $n); };
1335    ($name:ident, f64, $n:expr) => { $crate::_nt_array_float!($name, f64, $n); };
1336    ($name:ident, f32, $n:expr; $($derive:path),+) => { $crate::_nt_array_float!($name, f32, $n; $($derive),+); };
1337    ($name:ident, f64, $n:expr; $($derive:path),+) => { $crate::_nt_array_float!($name, f64, $n; $($derive),+); };
1338
1339    ($name:ident, String, $n:expr) => { $crate::_nt_array_string!($name, $n); };
1340    ($name:ident, String, $n:expr; $($derive:path),+) => { $crate::_nt_array_string!($name, $n; $($derive),+); };
1341
1342    ($name:ident, $t:ty, $n:expr) => { $crate::_nt_array_generic!($name, $t, $n); };
1343    ($name:ident, $t:ty, $n:expr; $($derive:path),+) => { $crate::_nt_array_generic!($name, $t, $n; $($derive),+); };
1344}
1345
1346/// The `newtype_array_deref!` macro behaves exactly like
1347/// [`newtype_array!`](#newtype_array-macro) but additionally implements
1348/// [`Deref<Target = [T]>`](https://doc.rust-lang.org/std/ops/trait.Deref.html)
1349/// and
1350/// [`DerefMut`](https://doc.rust-lang.org/std/ops/trait.DerefMut.html).
1351///
1352/// This exposes every slice method (`first`, `last`, `contains`, `fill`, `chunks`,
1353/// `windows`, `split`, …) on the newtype directly, as well as triggering
1354/// implicit `&Name -> &[T]` coercion. That convenience comes at the cost of
1355/// partially erasing the wrapper at the call site, which can defeat the
1356/// type-safety motivation of the newtype pattern. Prefer
1357/// [`newtype_array!`](#newtype_array-macro) and access the slice through
1358/// `.as_ref()` / `.iter()` / indexing unless you specifically want the full
1359/// slice surface.
1360///
1361/// Example:
1362/// ```rust
1363/// use newtypes::*;
1364///
1365/// newtype_array_deref!(Buf, u8, 4);
1366///
1367/// let b = Buf([1, 2, 3, 4]);
1368/// assert_eq!(Some(&1u8), b.first());
1369/// assert_eq!(Some(&4u8), b.last());
1370/// assert!(b.contains(&3));
1371/// ```
1372#[macro_export]
1373macro_rules! newtype_array_deref {
1374    ($name:ident, i8, $n:expr) => { $crate::_nt_array_int!($name, i8, $n); $crate::_nt_array_deref_impls!($name, i8); };
1375    ($name:ident, u8, $n:expr) => { $crate::_nt_array_int!($name, u8, $n); $crate::_nt_array_deref_impls!($name, u8); };
1376    ($name:ident, i16, $n:expr) => { $crate::_nt_array_int!($name, i16, $n); $crate::_nt_array_deref_impls!($name, i16); };
1377    ($name:ident, u16, $n:expr) => { $crate::_nt_array_int!($name, u16, $n); $crate::_nt_array_deref_impls!($name, u16); };
1378    ($name:ident, i32, $n:expr) => { $crate::_nt_array_int!($name, i32, $n); $crate::_nt_array_deref_impls!($name, i32); };
1379    ($name:ident, u32, $n:expr) => { $crate::_nt_array_int!($name, u32, $n); $crate::_nt_array_deref_impls!($name, u32); };
1380    ($name:ident, i64, $n:expr) => { $crate::_nt_array_int!($name, i64, $n); $crate::_nt_array_deref_impls!($name, i64); };
1381    ($name:ident, u64, $n:expr) => { $crate::_nt_array_int!($name, u64, $n); $crate::_nt_array_deref_impls!($name, u64); };
1382    ($name:ident, i128, $n:expr) => { $crate::_nt_array_int!($name, i128, $n); $crate::_nt_array_deref_impls!($name, i128); };
1383    ($name:ident, u128, $n:expr) => { $crate::_nt_array_int!($name, u128, $n); $crate::_nt_array_deref_impls!($name, u128); };
1384    ($name:ident, isize, $n:expr) => { $crate::_nt_array_int!($name, isize, $n); $crate::_nt_array_deref_impls!($name, isize); };
1385    ($name:ident, usize, $n:expr) => { $crate::_nt_array_int!($name, usize, $n); $crate::_nt_array_deref_impls!($name, usize); };
1386    ($name:ident, i8, $n:expr; $($derive:path),+) => { $crate::_nt_array_int!($name, i8, $n; $($derive),+); $crate::_nt_array_deref_impls!($name, i8); };
1387    ($name:ident, u8, $n:expr; $($derive:path),+) => { $crate::_nt_array_int!($name, u8, $n; $($derive),+); $crate::_nt_array_deref_impls!($name, u8); };
1388    ($name:ident, i16, $n:expr; $($derive:path),+) => { $crate::_nt_array_int!($name, i16, $n; $($derive),+); $crate::_nt_array_deref_impls!($name, i16); };
1389    ($name:ident, u16, $n:expr; $($derive:path),+) => { $crate::_nt_array_int!($name, u16, $n; $($derive),+); $crate::_nt_array_deref_impls!($name, u16); };
1390    ($name:ident, i32, $n:expr; $($derive:path),+) => { $crate::_nt_array_int!($name, i32, $n; $($derive),+); $crate::_nt_array_deref_impls!($name, i32); };
1391    ($name:ident, u32, $n:expr; $($derive:path),+) => { $crate::_nt_array_int!($name, u32, $n; $($derive),+); $crate::_nt_array_deref_impls!($name, u32); };
1392    ($name:ident, i64, $n:expr; $($derive:path),+) => { $crate::_nt_array_int!($name, i64, $n; $($derive),+); $crate::_nt_array_deref_impls!($name, i64); };
1393    ($name:ident, u64, $n:expr; $($derive:path),+) => { $crate::_nt_array_int!($name, u64, $n; $($derive),+); $crate::_nt_array_deref_impls!($name, u64); };
1394    ($name:ident, i128, $n:expr; $($derive:path),+) => { $crate::_nt_array_int!($name, i128, $n; $($derive),+); $crate::_nt_array_deref_impls!($name, i128); };
1395    ($name:ident, u128, $n:expr; $($derive:path),+) => { $crate::_nt_array_int!($name, u128, $n; $($derive),+); $crate::_nt_array_deref_impls!($name, u128); };
1396    ($name:ident, isize, $n:expr; $($derive:path),+) => { $crate::_nt_array_int!($name, isize, $n; $($derive),+); $crate::_nt_array_deref_impls!($name, isize); };
1397    ($name:ident, usize, $n:expr; $($derive:path),+) => { $crate::_nt_array_int!($name, usize, $n; $($derive),+); $crate::_nt_array_deref_impls!($name, usize); };
1398
1399    ($name:ident, f32, $n:expr) => { $crate::_nt_array_float!($name, f32, $n); $crate::_nt_array_deref_impls!($name, f32); };
1400    ($name:ident, f64, $n:expr) => { $crate::_nt_array_float!($name, f64, $n); $crate::_nt_array_deref_impls!($name, f64); };
1401    ($name:ident, f32, $n:expr; $($derive:path),+) => { $crate::_nt_array_float!($name, f32, $n; $($derive),+); $crate::_nt_array_deref_impls!($name, f32); };
1402    ($name:ident, f64, $n:expr; $($derive:path),+) => { $crate::_nt_array_float!($name, f64, $n; $($derive),+); $crate::_nt_array_deref_impls!($name, f64); };
1403
1404    ($name:ident, String, $n:expr) => { $crate::_nt_array_string!($name, $n); $crate::_nt_array_deref_impls!($name, String); };
1405    ($name:ident, String, $n:expr; $($derive:path),+) => { $crate::_nt_array_string!($name, $n; $($derive),+); $crate::_nt_array_deref_impls!($name, String); };
1406
1407    ($name:ident, $t:ty, $n:expr) => { $crate::_nt_array_generic!($name, $t, $n); $crate::_nt_array_deref_impls!($name, $t); };
1408    ($name:ident, $t:ty, $n:expr; $($derive:path),+) => { $crate::_nt_array_generic!($name, $t, $n; $($derive),+); $crate::_nt_array_deref_impls!($name, $t); };
1409}
1410
1411/// The macro `newtype_from!` implements the `From` and `FromStr` traits for us
1412/// in case it's possible.
1413///
1414/// It has to be used in combination with one of the other ones
1415/// (`newtype!`, `newtype_ord!`, or `newtype_unit!`).
1416///
1417/// Example:
1418/// ```rust
1419/// use newtypes::*;
1420///
1421/// newtype!(Weight, f32);
1422/// newtype_from!(Weight, f32);
1423/// ```
1424///
1425/// > **NOTE:** It only works for integers, floating point numbers, and `String`.
1426#[macro_export]
1427macro_rules! newtype_from {
1428    ($name:ident, i8) => {
1429        $crate::_nt_int_from!($name, i8);
1430    };
1431    ($name:ident, u8) => {
1432        $crate::_nt_int_from!($name, u8);
1433    };
1434    ($name:ident, i16) => {
1435        $crate::_nt_int_from!($name, i16);
1436    };
1437    ($name:ident, u16) => {
1438        $crate::_nt_int_from!($name, u16);
1439    };
1440    ($name:ident, i32) => {
1441        $crate::_nt_int_from!($name, i32);
1442    };
1443    ($name:ident, u32) => {
1444        $crate::_nt_int_from!($name, u32);
1445    };
1446    ($name:ident, i64) => {
1447        $crate::_nt_int_from!($name, i64);
1448    };
1449    ($name:ident, u64) => {
1450        $crate::_nt_int_from!($name, u64);
1451    };
1452    ($name:ident, i128) => {
1453        $crate::_nt_int_from!($name, i128);
1454    };
1455    ($name:ident, u128) => {
1456        $crate::_nt_int_from!($name, u128);
1457    };
1458    ($name:ident, isize) => {
1459        $crate::_nt_int_from!($name, isize);
1460    };
1461    ($name:ident, usize) => {
1462        $crate::_nt_int_from!($name, usize);
1463    };
1464
1465    ($name:ident, f32) => {
1466        $crate::_nt_float_from!($name, f32);
1467    };
1468    ($name:ident, f64) => {
1469        $crate::_nt_float_from!($name, f64);
1470    };
1471
1472    ($name:ident, String) => {
1473        impl From<String> for $name {
1474            #[inline(always)]
1475            fn from(value: String) -> Self {
1476                $name(value)
1477            }
1478        }
1479
1480        impl From<&str> for $name {
1481            #[inline(always)]
1482            fn from(value: &str) -> Self {
1483                $name(value.into())
1484            }
1485        }
1486
1487        impl std::str::FromStr for $name {
1488            type Err = std::convert::Infallible;
1489
1490            #[inline(always)]
1491            fn from_str(s: &str) -> Result<Self, Self::Err> {
1492                Ok($name(String::from_str(s).unwrap()))
1493            }
1494        }
1495    };
1496
1497    ($name:ident, $inner:ty) => {
1498        impl From<$inner> for $name {
1499            #[inline(always)]
1500            fn from(value: $inner) -> Self {
1501                $name(value)
1502            }
1503        }
1504    };
1505}
1506
1507/// The macro `newtype_from_only!` implements only the `From` trait for a
1508/// newtype, leaving `FromStr` to the caller. Use it when a type should be
1509/// constructible from its inner value but should not parse from text.
1510///
1511/// It has to be used in combination with one of the other ones
1512/// (`newtype!`, `newtype_ord!`, `newtype_struct!`, or `newtype_unit!`).
1513///
1514/// Example:
1515/// ```rust
1516/// use newtypes::*;
1517///
1518/// newtype!(VertexIndex, u32);
1519/// newtype_from_only!(VertexIndex, u32);
1520/// ```
1521///
1522/// > **NOTE:** It works for integers, floating point numbers, `String`, and
1523/// > arbitrary inner types.
1524#[macro_export]
1525macro_rules! newtype_from_only {
1526    ($name:ident, i8) => {
1527        $crate::_nt_from_traits!($name, i8);
1528    };
1529    ($name:ident, u8) => {
1530        $crate::_nt_from_traits!($name, u8);
1531    };
1532    ($name:ident, i16) => {
1533        $crate::_nt_from_traits!($name, i16);
1534    };
1535    ($name:ident, u16) => {
1536        $crate::_nt_from_traits!($name, u16);
1537    };
1538    ($name:ident, i32) => {
1539        $crate::_nt_from_traits!($name, i32);
1540    };
1541    ($name:ident, u32) => {
1542        $crate::_nt_from_traits!($name, u32);
1543    };
1544    ($name:ident, i64) => {
1545        $crate::_nt_from_traits!($name, i64);
1546    };
1547    ($name:ident, u64) => {
1548        $crate::_nt_from_traits!($name, u64);
1549    };
1550    ($name:ident, i128) => {
1551        $crate::_nt_from_traits!($name, i128);
1552    };
1553    ($name:ident, u128) => {
1554        $crate::_nt_from_traits!($name, u128);
1555    };
1556    ($name:ident, isize) => {
1557        $crate::_nt_from_traits!($name, isize);
1558    };
1559    ($name:ident, usize) => {
1560        $crate::_nt_from_traits!($name, usize);
1561    };
1562
1563    ($name:ident, f32) => {
1564        $crate::_nt_from_traits!($name, f32);
1565    };
1566    ($name:ident, f64) => {
1567        $crate::_nt_from_traits!($name, f64);
1568    };
1569
1570    ($name:ident, String) => {
1571        impl From<String> for $name {
1572            #[inline(always)]
1573            fn from(value: String) -> Self {
1574                $name(value)
1575            }
1576        }
1577
1578        impl From<&str> for $name {
1579            #[inline(always)]
1580            fn from(value: &str) -> Self {
1581                $name(value.into())
1582            }
1583        }
1584    };
1585
1586    ($name:ident, $inner:ty) => {
1587        $crate::_nt_from_traits!($name, $inner);
1588    };
1589}
1590
1591/// The macro `newtype_fromstr!` implements only the `FromStr` trait for a
1592/// newtype, leaving `From<inner>` to the caller. Use it when a type should
1593/// parse from text but should not be implicitly constructible from its inner
1594/// value.
1595///
1596/// It has to be used in combination with one of the other ones
1597/// (`newtype!`, `newtype_ord!`, or `newtype_unit!`).
1598///
1599/// Example:
1600/// ```rust
1601/// use newtypes::*;
1602/// use std::str::FromStr;
1603///
1604/// newtype!(Age, u8);
1605/// newtype_fromstr!(Age, u8);
1606///
1607/// let a = Age::from_str("42").unwrap();
1608/// ```
1609///
1610/// > **NOTE:** It only works for integers, floating point numbers, and
1611/// > `String`. For arbitrary inner types implement `FromStr` manually.
1612#[macro_export]
1613macro_rules! newtype_fromstr {
1614    ($name:ident, i8) => {
1615        $crate::_nt_fromstr_traits!($name, i8, std::num::ParseIntError);
1616    };
1617    ($name:ident, u8) => {
1618        $crate::_nt_fromstr_traits!($name, u8, std::num::ParseIntError);
1619    };
1620    ($name:ident, i16) => {
1621        $crate::_nt_fromstr_traits!($name, i16, std::num::ParseIntError);
1622    };
1623    ($name:ident, u16) => {
1624        $crate::_nt_fromstr_traits!($name, u16, std::num::ParseIntError);
1625    };
1626    ($name:ident, i32) => {
1627        $crate::_nt_fromstr_traits!($name, i32, std::num::ParseIntError);
1628    };
1629    ($name:ident, u32) => {
1630        $crate::_nt_fromstr_traits!($name, u32, std::num::ParseIntError);
1631    };
1632    ($name:ident, i64) => {
1633        $crate::_nt_fromstr_traits!($name, i64, std::num::ParseIntError);
1634    };
1635    ($name:ident, u64) => {
1636        $crate::_nt_fromstr_traits!($name, u64, std::num::ParseIntError);
1637    };
1638    ($name:ident, i128) => {
1639        $crate::_nt_fromstr_traits!($name, i128, std::num::ParseIntError);
1640    };
1641    ($name:ident, u128) => {
1642        $crate::_nt_fromstr_traits!($name, u128, std::num::ParseIntError);
1643    };
1644    ($name:ident, isize) => {
1645        $crate::_nt_fromstr_traits!($name, isize, std::num::ParseIntError);
1646    };
1647    ($name:ident, usize) => {
1648        $crate::_nt_fromstr_traits!($name, usize, std::num::ParseIntError);
1649    };
1650
1651    ($name:ident, f32) => {
1652        $crate::_nt_fromstr_traits!($name, f32, std::num::ParseFloatError);
1653    };
1654    ($name:ident, f64) => {
1655        $crate::_nt_fromstr_traits!($name, f64, std::num::ParseFloatError);
1656    };
1657
1658    ($name:ident, String) => {
1659        impl std::str::FromStr for $name {
1660            type Err = std::convert::Infallible;
1661
1662            #[inline(always)]
1663            fn from_str(s: &str) -> Result<Self, Self::Err> {
1664                Ok($name(String::from_str(s).unwrap()))
1665            }
1666        }
1667    };
1668}
1669
1670#[cfg(test)]
1671mod tests_newtype {
1672    newtype!(UserId, u32);
1673    newtype_from!(UserId, u32);
1674
1675    newtype!(Weight, f32);
1676    newtype_from!(Weight, f32);
1677
1678    newtype!(StrId, String);
1679    newtype_from!(StrId, String);
1680
1681    #[test]
1682    fn test_integers_cmp() {
1683        let v1 = UserId::from(42);
1684        let v2 = UserId::from(1001);
1685        let v3 = UserId::from(42);
1686
1687        assert!(v1 != v2);
1688        assert!(v2 != v3);
1689        assert!(v1 == v1);
1690        assert!(v1 == v3);
1691    }
1692
1693    #[test]
1694    #[allow(clippy::clone_on_copy)]
1695    fn test_integers_copy() {
1696        let v1 = UserId::from(42);
1697        let v2 = UserId::from(1001);
1698
1699        #[allow(unused)]
1700        let mut v3 = UserId::from(0);
1701
1702        v3 = v1;
1703        assert_eq!(UserId(42), v3);
1704        v3 = v2;
1705        assert_eq!(UserId(1001), v3);
1706
1707        v3 = v1.clone();
1708        assert_eq!(UserId(42), v3);
1709        v3 = v2.clone();
1710        assert_eq!(UserId(1001), v3);
1711    }
1712
1713    #[test]
1714    fn test_integers_into() {
1715        let v1 = UserId::from(42);
1716        assert_eq!(42_u32, v1.into());
1717    }
1718
1719    #[test]
1720    fn test_float_cmp() {
1721        let v1 = Weight::from(42.0);
1722        let v2 = Weight::from(1001.0);
1723        let v3 = Weight::from(42.0);
1724
1725        assert!(v1 != v2);
1726        assert!(v2 != v3);
1727        assert!(v1 == v1);
1728        assert!(v1 == v3);
1729    }
1730
1731    #[test]
1732    #[allow(clippy::clone_on_copy)]
1733    fn test_float_copy() {
1734        let v1 = Weight::from(42.0);
1735        let v2 = Weight::from(1001.0);
1736
1737        #[allow(unused)]
1738        let mut v3 = Weight::from(0.0);
1739
1740        v3 = v1;
1741        assert_eq!(Weight(42.0), v3);
1742        v3 = v2;
1743        assert_eq!(Weight(1001.0), v3);
1744
1745        v3 = v1.clone();
1746        assert_eq!(Weight(42.0), v3);
1747        v3 = v2.clone();
1748        assert_eq!(Weight(1001.0), v3);
1749    }
1750
1751    #[test]
1752    fn test_float_into() {
1753        let v1 = Weight::from(42.0);
1754        assert_eq!(42_f32, v1.into());
1755    }
1756
1757    #[test]
1758    fn test_string_cmp() {
1759        let v1 = StrId::from("42");
1760        let v2 = StrId::from("1001");
1761        let v3 = StrId::from("42");
1762
1763        assert!(v1 != v2);
1764        assert!(v2 != v3);
1765        assert!(v1 == v1);
1766        assert!(v1 == v3);
1767    }
1768
1769    #[test]
1770    fn test_string_copy() {
1771        let v1 = StrId::from("42");
1772        let v2 = StrId::from("1001");
1773
1774        #[allow(unused)]
1775        let mut v3 = StrId::from("0");
1776
1777        v3 = v1.clone();
1778        assert_eq!(StrId("42".into()), v3);
1779        v3 = v2.clone();
1780        assert_eq!(StrId("1001".into()), v3);
1781    }
1782
1783    #[test]
1784    fn test_string_into() {
1785        let v1 = StrId::from("42");
1786
1787        let s: String = v1.into();
1788        assert_eq!("42", s);
1789    }
1790}
1791
1792#[cfg(test)]
1793mod tests_newtype_ord {
1794    newtype_ord!(Weight, u32);
1795    newtype_from!(Weight, u32);
1796
1797    newtype_ord!(Height, f32);
1798    newtype_from!(Height, f32);
1799
1800    newtype_ord!(Name, String);
1801    newtype_from!(Name, String);
1802
1803    #[test]
1804    fn test_integers_cmp() {
1805        let w1 = Weight::from(100);
1806        let w2 = Weight::from(150);
1807
1808        assert!(w1 <= w2);
1809        assert!(w1 < w2);
1810        assert!(w2 >= w1);
1811        assert!(w2 > w1);
1812    }
1813
1814    #[test]
1815    fn test_float_cmp() {
1816        let h1 = Height::from(100.0);
1817        let h2 = Height::from(150.0);
1818
1819        assert!(h1 <= h2);
1820        assert!(h1 < h2);
1821        assert!(h2 >= h1);
1822        assert!(h2 > h1);
1823    }
1824
1825    #[test]
1826    fn test_string_cmp() {
1827        let n1 = Name::from("Alan");
1828        let n2 = Name::from("Julia");
1829
1830        assert!(n1 <= n2);
1831        assert!(n1 < n2);
1832        assert!(n2 >= n1);
1833        assert!(n2 > n1);
1834    }
1835}
1836
1837#[cfg(test)]
1838mod tests_newtype_unit {
1839    newtype_unit!(Units, i32);
1840    newtype_from!(Units, i32);
1841
1842    #[test]
1843    fn test_integers_add() {
1844        let u1 = Units::from(100);
1845        let u2 = Units::from(50);
1846        let mut u3 = Units::from(200);
1847
1848        assert_eq!(Units(150), u1 + u2);
1849        assert_eq!(Units(150), u2 + u1);
1850
1851        u3 += u2;
1852        assert_eq!(Units(250), u3);
1853    }
1854
1855    #[test]
1856    fn test_integers_sub() {
1857        let u1 = Units::from(100);
1858        let u2 = Units::from(50);
1859        let mut u3 = Units::from(200);
1860
1861        assert_eq!(Units(50), u1 - u2);
1862        assert_eq!(Units(-50), u2 - u1);
1863
1864        u3 -= u2;
1865        assert_eq!(Units(150), u3);
1866    }
1867}
1868
1869#[cfg(test)]
1870mod tests_newtype_from {
1871    use std::str::FromStr;
1872
1873    newtype!(UserId, u32);
1874    newtype_from!(UserId, u32);
1875
1876    newtype!(Weight, f32);
1877    newtype_from!(Weight, f32);
1878
1879    newtype!(Name, String);
1880    newtype_from!(Name, String);
1881
1882    #[test]
1883    fn test_integer_fromstr() {
1884        assert_eq!(Ok(UserId(42)), UserId::from_str("42"));
1885        assert!(UserId::from_str("hello").is_err());
1886    }
1887
1888    #[test]
1889    fn test_float_fromstr() {
1890        assert_eq!(Ok(Weight(42.0)), Weight::from_str("42.0"));
1891        assert!(Weight::from_str("hello").is_err());
1892    }
1893
1894    #[test]
1895    fn test_string_fromstr() {
1896        assert_eq!(Ok(Name("John".into())), Name::from_str("John"));
1897    }
1898}
1899
1900#[cfg(test)]
1901mod tests_newtype_from_split {
1902    use std::str::FromStr;
1903
1904    newtype!(IntFromOnly, u32);
1905    newtype_from_only!(IntFromOnly, u32);
1906
1907    newtype!(FloatFromOnly, f32);
1908    newtype_from_only!(FloatFromOnly, f32);
1909
1910    newtype!(StrFromOnly, String);
1911    newtype_from_only!(StrFromOnly, String);
1912
1913    #[derive(Debug)]
1914    pub struct Inner(u32);
1915    newtype!(StructFromOnly, Inner);
1916    newtype_from_only!(StructFromOnly, Inner);
1917
1918    newtype!(IntFromStr, u32);
1919    newtype_fromstr!(IntFromStr, u32);
1920
1921    newtype!(FloatFromStr, f32);
1922    newtype_fromstr!(FloatFromStr, f32);
1923
1924    newtype!(StrFromStr, String);
1925    newtype_fromstr!(StrFromStr, String);
1926
1927    newtype!(BothInt, u32);
1928    newtype_from_only!(BothInt, u32);
1929    newtype_fromstr!(BothInt, u32);
1930
1931    #[test]
1932    fn test_from_only_integer() {
1933        let v: IntFromOnly = 42_u32.into();
1934        let n: u32 = v.into();
1935        assert_eq!(42, n);
1936    }
1937
1938    #[test]
1939    fn test_from_only_float() {
1940        let v: FloatFromOnly = 1.5_f32.into();
1941        let n: f32 = v.into();
1942        assert!((n - 1.5).abs() < f32::EPSILON);
1943    }
1944
1945    #[test]
1946    fn test_from_only_string_owned() {
1947        let v: StrFromOnly = String::from("hello").into();
1948        let s: String = v.into();
1949        assert_eq!("hello", s);
1950    }
1951
1952    #[test]
1953    fn test_from_only_string_slice() {
1954        let v: StrFromOnly = "world".into();
1955        let s: String = v.into();
1956        assert_eq!("world", s);
1957    }
1958
1959    #[test]
1960    fn test_from_only_struct() {
1961        let v: StructFromOnly = Inner(7).into();
1962        let inner: Inner = v.into();
1963        assert_eq!(7, inner.0);
1964    }
1965
1966    #[test]
1967    fn test_fromstr_integer() {
1968        let v = IntFromStr::from_str("99").unwrap();
1969        assert_eq!(99_u32, v.into());
1970        assert!(IntFromStr::from_str("nope").is_err());
1971    }
1972
1973    #[test]
1974    fn test_fromstr_float() {
1975        let v = FloatFromStr::from_str("3.25").unwrap();
1976        let n: f32 = v.into();
1977        assert!((n - 3.25).abs() < f32::EPSILON);
1978        assert!(FloatFromStr::from_str("nope").is_err());
1979    }
1980
1981    #[test]
1982    fn test_fromstr_string() {
1983        let v = StrFromStr::from_str("greetings").unwrap();
1984        let s: String = v.into();
1985        assert_eq!("greetings", s);
1986    }
1987
1988    #[test]
1989    fn test_combined_equivalent_to_newtype_from() {
1990        let from_int: BothInt = 7_u32.into();
1991        let parsed = BothInt::from_str("7").unwrap();
1992        assert_eq!(7_u32, from_int.into());
1993        assert_eq!(7_u32, parsed.into());
1994    }
1995}
1996
1997#[cfg(test)]
1998mod tests_newtype_struct {
1999    #[derive(Debug, Clone, PartialEq)]
2000    pub struct Point2D {
2001        pub x: f32,
2002        pub y: f32,
2003    }
2004
2005    newtype_struct!(Vertex, Point2D);
2006
2007    newtype_struct!(Numbers, Vec<u32>);
2008
2009    #[derive(Debug, Clone, PartialEq)]
2010    struct Container {
2011        head: Vertex,
2012        tail: Vertex,
2013    }
2014
2015    #[test]
2016    fn test_struct_clone_and_eq() {
2017        let a = Vertex(Point2D { x: 1.0, y: 2.0 });
2018        let b = a.clone();
2019        assert_eq!(a, b);
2020        let c = Vertex(Point2D { x: 1.0, y: 3.0 });
2021        assert!(a != c);
2022    }
2023
2024    #[test]
2025    fn test_struct_into() {
2026        let v = Vertex(Point2D { x: 4.0, y: 5.0 });
2027        let inner: Point2D = v.into();
2028        assert_eq!(Point2D { x: 4.0, y: 5.0 }, inner);
2029    }
2030
2031    #[test]
2032    fn test_struct_debug() {
2033        let v = Vertex(Point2D { x: 0.0, y: 0.0 });
2034        let dbg = format!("{:?}", v);
2035        assert!(dbg.contains("Vertex"));
2036        assert!(dbg.contains("Point2D"));
2037    }
2038
2039    #[test]
2040    fn test_struct_wrapping_vec() {
2041        let n = Numbers(vec![1, 2, 3]);
2042        let m = n.clone();
2043        assert_eq!(n, m);
2044        let inner: Vec<u32> = n.into();
2045        assert_eq!(vec![1, 2, 3], inner);
2046    }
2047
2048    #[test]
2049    fn test_struct_composes_in_outer_struct() {
2050        let c1 = Container {
2051            head: Vertex(Point2D { x: 0.0, y: 0.0 }),
2052            tail: Vertex(Point2D { x: 1.0, y: 1.0 }),
2053        };
2054        let c2 = c1.clone();
2055        assert_eq!(c1, c2);
2056    }
2057}
2058
2059#[cfg(test)]
2060mod tests_newtype_validated {
2061    use std::error::Error;
2062
2063    newtype_validated!(Probability, ProbabilityError, f32, |x: &f32| (0.0..=1.0)
2064        .contains(x));
2065
2066    fn is_even(x: &u32) -> bool {
2067        x.is_multiple_of(2)
2068    }
2069    newtype_validated!(EvenU32, EvenU32Error, u32, is_even);
2070
2071    newtype_validated!(NonEmpty, NonEmptyError, String, |s: &String| !s.is_empty());
2072
2073    #[derive(Debug, Clone, PartialEq)]
2074    pub struct Range {
2075        pub lo: i32,
2076        pub hi: i32,
2077    }
2078    newtype_validated!(SortedRange, SortedRangeError, Range, |r: &Range| r.lo
2079        <= r.hi);
2080
2081    #[test]
2082    fn test_closure_validator_valid() {
2083        let p = Probability::new(0.5).unwrap();
2084        let inner: f32 = p.into();
2085        assert!((inner - 0.5).abs() < f32::EPSILON);
2086    }
2087
2088    #[test]
2089    fn test_closure_validator_invalid() {
2090        assert_eq!(Err(ProbabilityError), Probability::new(2.0));
2091        assert_eq!(Err(ProbabilityError), Probability::new(-0.1));
2092    }
2093
2094    #[test]
2095    fn test_closure_validator_boundaries() {
2096        assert!(Probability::new(0.0).is_ok());
2097        assert!(Probability::new(1.0).is_ok());
2098    }
2099
2100    #[test]
2101    fn test_function_path_validator() {
2102        assert!(EvenU32::new(4).is_ok());
2103        assert_eq!(Err(EvenU32Error), EvenU32::new(5));
2104    }
2105
2106    #[test]
2107    fn test_string_validator() {
2108        assert!(NonEmpty::new("hello".to_string()).is_ok());
2109        assert_eq!(Err(NonEmptyError), NonEmpty::new(String::new()));
2110    }
2111
2112    #[test]
2113    fn test_struct_validator() {
2114        assert!(SortedRange::new(Range { lo: 1, hi: 5 }).is_ok());
2115        assert_eq!(
2116            Err(SortedRangeError),
2117            SortedRange::new(Range { lo: 5, hi: 1 })
2118        );
2119    }
2120
2121    #[test]
2122    fn test_tryfrom_valid() {
2123        let p: Probability = (0.5_f32).try_into().unwrap();
2124        let inner: f32 = p.into();
2125        assert!((inner - 0.5).abs() < f32::EPSILON);
2126    }
2127
2128    #[test]
2129    fn test_tryfrom_invalid() {
2130        let r: Result<Probability, _> = (2.0_f32).try_into();
2131        assert_eq!(Err(ProbabilityError), r);
2132    }
2133
2134    #[test]
2135    fn test_error_traits() {
2136        let e = ProbabilityError;
2137        let dbg = format!("{:?}", e);
2138        assert!(dbg.contains("ProbabilityError"));
2139        let disp = format!("{}", e);
2140        assert_eq!("invalid Probability value", disp);
2141        let copy = e;
2142        assert_eq!(e, copy);
2143        let _src: Option<&(dyn Error + 'static)> = e.source();
2144    }
2145
2146    #[test]
2147    fn test_clone_and_eq_on_validated_value() {
2148        let a = Probability::new(0.25).unwrap();
2149        let b = a.clone();
2150        assert_eq!(a, b);
2151    }
2152}
2153
2154#[cfg(test)]
2155mod tests_pointer_sized_ints {
2156    use std::str::FromStr;
2157
2158    newtype!(UsizeId, usize);
2159    newtype_from!(UsizeId, usize);
2160
2161    newtype_ord!(UsizeOrd, usize);
2162    newtype_from!(UsizeOrd, usize);
2163
2164    newtype_unit!(UsizeUnit, usize);
2165    newtype_from!(UsizeUnit, usize);
2166
2167    newtype!(UsizeOnly, usize);
2168    newtype_from_only!(UsizeOnly, usize);
2169
2170    newtype!(UsizeStr, usize);
2171    newtype_fromstr!(UsizeStr, usize);
2172
2173    newtype!(IsizeId, isize);
2174    newtype_from!(IsizeId, isize);
2175
2176    newtype_ord!(IsizeOrd, isize);
2177    newtype_from!(IsizeOrd, isize);
2178
2179    newtype_unit!(IsizeUnit, isize);
2180    newtype_from!(IsizeUnit, isize);
2181
2182    newtype!(IsizeOnly, isize);
2183    newtype_from_only!(IsizeOnly, isize);
2184
2185    newtype!(IsizeStr, isize);
2186    newtype_fromstr!(IsizeStr, isize);
2187
2188    #[test]
2189    fn test_usize_basics() {
2190        let a = UsizeId::from(42);
2191        let b = UsizeId::from(42);
2192        let c = UsizeId::from(7);
2193        assert_eq!(a, b);
2194        assert!(a != c);
2195        let n: usize = a.into();
2196        assert_eq!(42, n);
2197    }
2198
2199    #[test]
2200    fn test_usize_ord() {
2201        let a = UsizeOrd::from(1);
2202        let b = UsizeOrd::from(2);
2203        assert!(a < b);
2204    }
2205
2206    #[test]
2207    fn test_usize_unit_arithmetic() {
2208        let a = UsizeUnit::from(10);
2209        let b = UsizeUnit::from(3);
2210        let c = a + b;
2211        let n: usize = c.into();
2212        assert_eq!(13, n);
2213    }
2214
2215    #[test]
2216    fn test_usize_fromstr_via_newtype_from() {
2217        assert_eq!(Ok(UsizeId(99)), UsizeId::from_str("99"));
2218        assert!(UsizeId::from_str("nope").is_err());
2219    }
2220
2221    #[test]
2222    fn test_usize_from_only() {
2223        let a = UsizeOnly::from(5);
2224        let n: usize = a.into();
2225        assert_eq!(5, n);
2226    }
2227
2228    #[test]
2229    fn test_usize_fromstr_only() {
2230        let a = UsizeStr::from_str("123").unwrap();
2231        let n: usize = a.into();
2232        assert_eq!(123, n);
2233    }
2234
2235    #[test]
2236    fn test_isize_basics() {
2237        let a = IsizeId::from(-42);
2238        let b = IsizeId::from(-42);
2239        let c = IsizeId::from(7);
2240        assert_eq!(a, b);
2241        assert!(a != c);
2242        let n: isize = a.into();
2243        assert_eq!(-42, n);
2244    }
2245
2246    #[test]
2247    fn test_isize_ord() {
2248        let a = IsizeOrd::from(-1);
2249        let b = IsizeOrd::from(2);
2250        assert!(a < b);
2251    }
2252
2253    #[test]
2254    fn test_isize_unit_arithmetic() {
2255        let a = IsizeUnit::from(10);
2256        let b = IsizeUnit::from(-3);
2257        let c = a + b;
2258        let n: isize = c.into();
2259        assert_eq!(7, n);
2260    }
2261
2262    #[test]
2263    fn test_isize_fromstr_via_newtype_from() {
2264        assert_eq!(Ok(IsizeId(-99)), IsizeId::from_str("-99"));
2265        assert!(IsizeId::from_str("nope").is_err());
2266    }
2267
2268    #[test]
2269    fn test_isize_from_only() {
2270        let a = IsizeOnly::from(-5);
2271        let n: isize = a.into();
2272        assert_eq!(-5, n);
2273    }
2274
2275    #[test]
2276    fn test_isize_fromstr_only() {
2277        let a = IsizeStr::from_str("-123").unwrap();
2278        let n: isize = a.into();
2279        assert_eq!(-123, n);
2280    }
2281}
2282
2283#[cfg(test)]
2284mod tests_layout {
2285    use std::mem::{align_of, size_of};
2286
2287    newtype!(LayoutI8, i8);
2288    newtype!(LayoutU64, u64);
2289    newtype!(LayoutI128, i128);
2290    newtype!(LayoutF32, f32);
2291    newtype!(LayoutF64, f64);
2292    newtype!(LayoutString, String);
2293
2294    #[derive(Debug)]
2295    #[allow(dead_code)]
2296    struct Wide {
2297        a: u64,
2298        b: u32,
2299    }
2300    newtype!(LayoutStruct, Wide);
2301
2302    #[test]
2303    fn test_size_matches_inner() {
2304        assert_eq!(size_of::<i8>(), size_of::<LayoutI8>());
2305        assert_eq!(size_of::<u64>(), size_of::<LayoutU64>());
2306        assert_eq!(size_of::<i128>(), size_of::<LayoutI128>());
2307        assert_eq!(size_of::<f32>(), size_of::<LayoutF32>());
2308        assert_eq!(size_of::<f64>(), size_of::<LayoutF64>());
2309        assert_eq!(size_of::<String>(), size_of::<LayoutString>());
2310        assert_eq!(size_of::<Wide>(), size_of::<LayoutStruct>());
2311    }
2312
2313    #[test]
2314    fn test_align_matches_inner() {
2315        assert_eq!(align_of::<i8>(), align_of::<LayoutI8>());
2316        assert_eq!(align_of::<u64>(), align_of::<LayoutU64>());
2317        assert_eq!(align_of::<i128>(), align_of::<LayoutI128>());
2318        assert_eq!(align_of::<f32>(), align_of::<LayoutF32>());
2319        assert_eq!(align_of::<f64>(), align_of::<LayoutF64>());
2320        assert_eq!(align_of::<String>(), align_of::<LayoutString>());
2321        assert_eq!(align_of::<Wide>(), align_of::<LayoutStruct>());
2322    }
2323}
2324
2325#[cfg(test)]
2326mod tests_newtype_array {
2327    newtype_array!(Mac, u8, 6);
2328    newtype_array!(Floats, f32, 4);
2329    newtype_array!(Names, String, 2);
2330    newtype_array!(Empty, u8, 0);
2331
2332    #[derive(Debug, Clone, PartialEq)]
2333    pub struct Tag(pub u32);
2334    newtype_array!(Tags, Tag, 3);
2335
2336    #[test]
2337    fn test_index_usize() {
2338        let m = Mac([1, 2, 3, 4, 5, 6]);
2339        assert_eq!(1, m[0]);
2340        assert_eq!(6, m[5]);
2341    }
2342
2343    #[test]
2344    fn test_index_mut_usize() {
2345        let mut m = Mac([0; 6]);
2346        m[0] = 42;
2347        m[5] = 7;
2348        assert_eq!(42, m[0]);
2349        assert_eq!(7, m[5]);
2350    }
2351
2352    #[test]
2353    fn test_range_index() {
2354        let m = Mac([1, 2, 3, 4, 5, 6]);
2355        let s: &[u8] = &m[1..3];
2356        assert_eq!(&[2u8, 3], s);
2357        let s: &[u8] = &m[..];
2358        assert_eq!(&[1u8, 2, 3, 4, 5, 6], s);
2359        let s: &[u8] = &m[2..];
2360        assert_eq!(&[3u8, 4, 5, 6], s);
2361        let s: &[u8] = &m[..=1];
2362        assert_eq!(&[1u8, 2], s);
2363    }
2364
2365    #[test]
2366    fn test_range_index_mut() {
2367        let mut m = Mac([1, 2, 3, 4, 5, 6]);
2368        m[1..3].copy_from_slice(&[20, 30]);
2369        assert_eq!(20, m[1]);
2370        assert_eq!(30, m[2]);
2371    }
2372
2373    #[test]
2374    fn test_iter_inherent() {
2375        let m = Mac([1, 2, 3, 4, 5, 6]);
2376        let sum: u32 = m.iter().map(|&x| x as u32).sum();
2377        assert_eq!(21, sum);
2378    }
2379
2380    #[test]
2381    fn test_iter_mut_inherent() {
2382        let mut m = Mac([1, 2, 3, 4, 5, 6]);
2383        for x in m.iter_mut() {
2384            *x *= 2;
2385        }
2386        assert_eq!(2, m[0]);
2387        assert_eq!(12, m[5]);
2388    }
2389
2390    #[test]
2391    fn test_into_iter_ref() {
2392        let m = Mac([1, 2, 3, 4, 5, 6]);
2393        let sum: u32 = (&m).into_iter().map(|&x| x as u32).sum();
2394        assert_eq!(21, sum);
2395    }
2396
2397    #[test]
2398    fn test_into_iter_owned() {
2399        let m = Mac([1, 2, 3, 4, 5, 6]);
2400        let v: Vec<u8> = m.into_iter().collect();
2401        assert_eq!(vec![1u8, 2, 3, 4, 5, 6], v);
2402    }
2403
2404    #[test]
2405    fn test_for_loop_ref() {
2406        let m = Mac([1, 2, 3, 4, 5, 6]);
2407        let mut total: u32 = 0;
2408        for x in &m {
2409            total += *x as u32;
2410        }
2411        assert_eq!(21, total);
2412    }
2413
2414    #[test]
2415    fn test_for_loop_mut() {
2416        let mut m = Mac([1, 2, 3, 4, 5, 6]);
2417        for x in &mut m {
2418            *x += 1;
2419        }
2420        assert_eq!(2, m[0]);
2421        assert_eq!(7, m[5]);
2422    }
2423
2424    #[test]
2425    fn test_len_and_is_empty() {
2426        let m = Mac([0; 6]);
2427        assert_eq!(6, m.len());
2428        assert!(!m.is_empty());
2429
2430        let e = Empty([]);
2431        assert_eq!(0, e.len());
2432        assert!(e.is_empty());
2433    }
2434
2435    #[test]
2436    fn test_as_array() {
2437        let m = Mac([1, 2, 3, 4, 5, 6]);
2438        let a: &[u8; 6] = m.as_array();
2439        assert_eq!(&[1u8, 2, 3, 4, 5, 6], a);
2440    }
2441
2442    #[test]
2443    fn test_as_array_mut() {
2444        let mut m = Mac([0; 6]);
2445        m.as_array_mut()[0] = 9;
2446        assert_eq!(9, m[0]);
2447    }
2448
2449    #[test]
2450    fn test_into_array() {
2451        let m = Mac([1, 2, 3, 4, 5, 6]);
2452        let a: [u8; 6] = m.into();
2453        assert_eq!([1u8, 2, 3, 4, 5, 6], a);
2454    }
2455
2456    #[test]
2457    fn test_as_ref_slice() {
2458        let m = Mac([1, 2, 3, 4, 5, 6]);
2459        let s: &[u8] = m.as_ref();
2460        assert_eq!(&[1u8, 2, 3, 4, 5, 6], s);
2461    }
2462
2463    #[test]
2464    fn test_as_mut_slice() {
2465        let mut m = Mac([1, 2, 3, 4, 5, 6]);
2466        let s: &mut [u8] = m.as_mut();
2467        s[0] = 99;
2468        assert_eq!(99, m[0]);
2469    }
2470
2471    #[test]
2472    fn test_eq_and_hash_for_int_array() {
2473        use std::collections::HashSet;
2474        let a = Mac([1, 2, 3, 4, 5, 6]);
2475        let b = Mac([1, 2, 3, 4, 5, 6]);
2476        let c = Mac([6, 5, 4, 3, 2, 1]);
2477        assert_eq!(a, b);
2478        assert!(a != c);
2479        let mut set: HashSet<Mac> = HashSet::new();
2480        set.insert(a);
2481        assert!(set.contains(&b));
2482        assert!(!set.contains(&c));
2483    }
2484
2485    #[test]
2486    fn test_copy_for_int_array() {
2487        let a = Mac([1, 2, 3, 4, 5, 6]);
2488        let b = a;
2489        let c = a;
2490        assert_eq!(a, b);
2491        assert_eq!(a, c);
2492    }
2493
2494    #[test]
2495    fn test_float_array_partialeq() {
2496        let a = Floats([1.0, 2.0, 3.0, 4.0]);
2497        let b = Floats([1.0, 2.0, 3.0, 4.0]);
2498        let c = Floats([1.0, 2.0, 3.0, 5.0]);
2499        assert!(a == b);
2500        assert!(a != c);
2501    }
2502
2503    #[test]
2504    fn test_string_array() {
2505        let n = Names(["alice".into(), "bob".into()]);
2506        let m = n.clone();
2507        assert_eq!(n, m);
2508        assert_eq!("alice", n[0]);
2509        assert_eq!("bob", n[1]);
2510    }
2511
2512    #[test]
2513    fn test_generic_struct_array() {
2514        let t = Tags([Tag(1), Tag(2), Tag(3)]);
2515        let u = t.clone();
2516        assert_eq!(t, u);
2517        assert_eq!(Tag(2), t[1]);
2518    }
2519
2520    #[test]
2521    fn test_empty_array_iter() {
2522        let e = Empty([]);
2523        let count = e.iter().count();
2524        assert_eq!(0, count);
2525        let count = e.into_iter().count();
2526        assert_eq!(0, count);
2527    }
2528}
2529
2530#[cfg(test)]
2531mod tests_newtype_array_deref {
2532    newtype_array_deref!(Buf, u8, 4);
2533
2534    #[test]
2535    fn test_deref_slice_methods() {
2536        let b = Buf([1, 2, 3, 4]);
2537        assert_eq!(Some(&1u8), b.first());
2538        assert_eq!(Some(&4u8), b.last());
2539        assert!(b.contains(&3));
2540        assert!(!b.contains(&99));
2541    }
2542
2543    #[test]
2544    fn test_deref_mut_slice_method() {
2545        let mut b = Buf([1, 2, 3, 4]);
2546        b.fill(0);
2547        assert_eq!([0u8, 0, 0, 0], *b.as_array());
2548    }
2549
2550    #[test]
2551    fn test_deref_target_is_slice() {
2552        let b = Buf([10, 20, 30, 40]);
2553        let s: &[u8] = &b;
2554        assert_eq!(&[10u8, 20, 30, 40], s);
2555    }
2556
2557    #[test]
2558    fn test_deref_does_not_break_inherent_iter() {
2559        let b = Buf([1, 2, 3, 4]);
2560        let sum: u32 = b.iter().map(|&x| x as u32).sum();
2561        assert_eq!(10, sum);
2562    }
2563}
2564
2565#[cfg(test)]
2566mod tests_newtype_array_layout {
2567    use std::mem::{align_of, size_of};
2568
2569    newtype_array!(LU8x6, u8, 6);
2570    newtype_array!(LU64x4, u64, 4);
2571    newtype_array!(LF32x3, f32, 3);
2572    newtype_array_deref!(LDU8x4, u8, 4);
2573
2574    #[test]
2575    fn test_size_matches_inner() {
2576        assert_eq!(size_of::<[u8; 6]>(), size_of::<LU8x6>());
2577        assert_eq!(size_of::<[u64; 4]>(), size_of::<LU64x4>());
2578        assert_eq!(size_of::<[f32; 3]>(), size_of::<LF32x3>());
2579        assert_eq!(size_of::<[u8; 4]>(), size_of::<LDU8x4>());
2580    }
2581
2582    #[test]
2583    fn test_align_matches_inner() {
2584        assert_eq!(align_of::<[u8; 6]>(), align_of::<LU8x6>());
2585        assert_eq!(align_of::<[u64; 4]>(), align_of::<LU64x4>());
2586        assert_eq!(align_of::<[f32; 3]>(), align_of::<LF32x3>());
2587        assert_eq!(align_of::<[u8; 4]>(), align_of::<LDU8x4>());
2588    }
2589}