1//! Conditional aliases to numeric types.
2//!
3//! # Examples
4//!
5//! ```
6//! use std::fs::File;
7//! use condtype::num::Usize64;
8//!
9//! fn handle_throughput(bytes: Usize64) {
10//! // ...
11//! }
12//!
13//! // usize
14//! let s: &str = // ...
15//! # "";
16//! handle_throughput(s.len() as Usize64);
17//!
18//! // u64
19//! # fn file() -> std::io::Result<()> {
20//! let f: File = // ...
21//! # panic!();
22//! handle_throughput(f.metadata()?.len() as Usize64);
23//! # Ok(()) }
24//! ```
25//!
26//! # Pitfalls
27//!
28//! Because these are type aliases, some operations may happen to work for the
29//! current target but not for other targets.
30//!
31//! The following example handles [`Usize32`] explicitly as [`usize`] or [`u32`]
32//! depending on whether the platform is 64-bit or 32-bit:
33//!
34//! ```
35//! # use condtype::num::Usize32;
36//! #[cfg(target_pointer_width = "64")]
37//! let x: Usize32 = usize::MAX;
38//!
39//! #[cfg(target_pointer_width = "32")]
40//! let x: Usize32 = u32::MAX;
41//! ```
42//!
43//! Instead, the code should be made portable by using an `as` cast:
44//!
45//! ```
46//! # use condtype::num::Usize32;
47//! let x: Usize32 = usize::MAX as Usize32;
48//! ```
49
50use core::mem::size_of;
51
52use crate::CondType;
53
54/// Conditional alias to the larger of two types.
55macro_rules! max_ty {
56 ($a:ty, $b:ty) => {
57 CondType<{ size_of::<$a>() > size_of::<$b>() }, $a, $b>
58 };
59}
60
61/// A signed integer that is convertible from [`isize`] and [`i8`][`i16`].
62///
63/// The integer is guaranteed to be at least [`isize`] large and [`i16`] small.
64pub type Isize16 = max_ty!(isize, i16);
65
66/// A signed integer that is convertible from [`isize`] and [`i8`][`i32`].
67///
68/// The integer is guaranteed to be at least [`isize`] large and [`i32`] small.
69pub type Isize32 = max_ty!(isize, i32);
70
71/// A signed integer that is convertible from [`isize`] and [`i8`][`i64`].
72///
73/// The integer is guaranteed to be at least [`isize`] large and [`i64`] small.
74pub type Isize64 = max_ty!(isize, i64);
75
76/// A signed integer that is convertible from [`isize`] and [`i8`][`i128`].
77///
78/// The integer is guaranteed to be at least [`isize`] large and [`i128`] small.
79pub type Isize128 = max_ty!(isize, i128);
80
81/// An unsigned integer that is convertible from [`usize`] and [`u8`][`u16`].
82///
83/// The integer is guaranteed to be at least [`usize`] large and [`u16`] small.
84pub type Usize16 = max_ty!(usize, u16);
85
86/// An unsigned integer that is convertible from [`usize`] and [`u8`][`u32`].
87///
88/// The integer is guaranteed to be at least [`usize`] large and [`u32`] small.
89pub type Usize32 = max_ty!(usize, u32);
90
91/// An unsigned integer that is convertible from [`usize`] and [`u8`][`u64`].
92///
93/// The integer is guaranteed to be at least [`usize`] large and [`u64`] small.
94pub type Usize64 = max_ty!(usize, u64);
95
96/// An unsigned integer that is convertible from [`usize`] and [`u8`][`u128`].
97///
98/// The integer is guaranteed to be at least [`usize`] large and [`u128`] small.
99pub type Usize128 = max_ty!(usize, u128);
100
101#[cfg(test)]
102mod tests {
103 use core::any::{type_name, TypeId};
104
105 use super::*;
106
107 #[test]
108 fn expected_type() {
109 macro_rules! assert_eq_ty {
110 ($a:ty, $b:ty) => {
111 assert_eq!(
112 TypeId::of::<$a>(),
113 TypeId::of::<$b>(),
114 "{} != {}",
115 type_name::<$a>(),
116 type_name::<$b>()
117 );
118 };
119 }
120
121 #[cfg(target_pointer_width = "32")]
122 assert_eq_ty!(Usize32, u32);
123
124 #[cfg(target_pointer_width = "64")]
125 assert_eq_ty!(Usize32, usize);
126
127 #[cfg(any(target_pointer_width = "32", target_pointer_width = "64"))]
128 assert_eq_ty!(Usize64, u64);
129
130 #[cfg(any(target_pointer_width = "32", target_pointer_width = "64"))]
131 assert_eq_ty!(Usize128, u128);
132 }
133}
134