smallest_uint/
lib.rs

1/*
2 * Copyright 2021-2022 taylor.fish <contact@taylor.fish>
3 *
4 * This file is part of smallest-uint.
5 *
6 * smallest-uint is licensed under the Apache License, Version 2.0
7 * (the "License"); you may not use smallest-uint except in compliance
8 * with the License. You may obtain a copy of the License at
9 *
10 *     http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 */
18
19#![no_std]
20#![cfg_attr(test, recursion_limit = "256")]
21#![forbid(unsafe_code)]
22#![warn(clippy::pedantic)]
23#![allow(clippy::default_trait_access)]
24#![allow(clippy::module_name_repetitions)]
25#![allow(clippy::must_use_candidate)]
26
27//! Given an unsigned [type-level integer][typenum], provides access to
28//! the smallest primitive unsigned integer type ([`u8`], [`u16`], etc.) that
29//! can represent the integer’s value (or all values less than that value).
30//!
31//! This is mainly useful for minimizing memory usage when building data
32//! structures.
33//!
34//! This crate depends only on [`core`], so it can be used in `no_std`
35//! environments.
36//!
37//! [`core`]: https://doc.rust-lang.org/core/
38//!
39//! Example
40//! -------
41//!
42//! ```rust
43//! use smallest_uint::{SmallestUIntFor, SmallestUIntUpTo};
44//! use std::any::TypeId;
45//! use typenum::U65536;
46//!
47//! assert_eq!(TypeId::of::<SmallestUIntUpTo<U65536>>(), TypeId::of::<u16>());
48//! assert_eq!(TypeId::of::<SmallestUIntFor<U65536>>(), TypeId::of::<u32>());
49//! ```
50//!
51//! Crate features
52//! --------------
53//!
54//! If the feature `u128` is enabled, this crate will use the [`u128`] type.
55//! This feature is enabled by default.
56//!
57//! [typenum]: typenum
58
59use num_traits::{NumAssign, PrimInt};
60use typenum::Unsigned;
61
62#[cfg(test)]
63mod tests;
64
65mod detail {
66    use super::SmallestUIntFor;
67    use core::ops::Sub;
68    use num_traits::{NumAssign, PrimInt};
69    use typenum::{Len, Max, Unsigned};
70    use typenum::{Length, Maximum, Sub1};
71    use typenum::{B1, U1};
72
73    type Max1<N> = Maximum<N, U1>;
74
75    pub trait GetSmallestUIntFor: Unsigned {
76        type Type: Default + PrimInt + NumAssign;
77    }
78
79    impl<N> GetSmallestUIntFor for N
80    where
81        N: Unsigned + Max<U1>,
82        Max1<N>: Len,
83        Length<Max1<N>>: Sub<B1>,
84        Sub1<Length<Max1<N>>>: Len,
85        Length<Sub1<Length<Max1<N>>>>: Get,
86    {
87        type Type = <Length<Sub1<Length<Max1<N>>>> as Get>::Type;
88    }
89
90    pub trait GetSmallestUIntUpTo: Unsigned {
91        type Type: Default + PrimInt + NumAssign;
92    }
93
94    impl<N> GetSmallestUIntUpTo for N
95    where
96        N: Unsigned + Max<U1>,
97        Max1<N>: Sub<B1>,
98        Sub1<Max1<N>>: super::GetSmallestUIntFor,
99    {
100        type Type = SmallestUIntFor<Sub1<Max1<N>>>;
101    }
102
103    /// Gets the smallest unsigned integer type with at least 2**`Self` bits.
104    pub trait Get {
105        type Type: Default + PrimInt + NumAssign;
106    }
107
108    impl Get for typenum::U0 {
109        type Type = u8;
110    }
111
112    impl Get for typenum::U1 {
113        type Type = u8;
114    }
115
116    impl Get for typenum::U2 {
117        type Type = u8;
118    }
119
120    impl Get for typenum::U3 {
121        type Type = u8;
122    }
123
124    impl Get for typenum::U4 {
125        type Type = u16;
126    }
127
128    impl Get for typenum::U5 {
129        type Type = u32;
130    }
131
132    impl Get for typenum::U6 {
133        type Type = u64;
134    }
135
136    #[cfg(feature = "u128")]
137    impl Get for typenum::U7 {
138        type Type = u128;
139    }
140}
141
142/// Gets the smallest unsigned integer type capable of representing the value
143/// of `Self`.
144///
145/// `Self` is an unsigned [type-level integer](typenum).
146///
147/// The type is provided as the associated type [`Self::Type`]. If you just
148/// want the type and aren’t specifying trait bounds, use the type alias
149/// [`SmallestUIntFor`].
150pub trait GetSmallestUIntFor: Unsigned + detail::GetSmallestUIntFor {
151    /// The unsigned integer type.
152    type Type: Default + PrimInt + NumAssign;
153}
154
155/// Alias of [`GetSmallestUIntFor::Type`].
156pub type SmallestUIntFor<N> = <N as GetSmallestUIntFor>::Type;
157
158impl<N> GetSmallestUIntFor for N
159where
160    N: detail::GetSmallestUIntFor,
161{
162    type Type = <N as detail::GetSmallestUIntFor>::Type;
163}
164
165/// Gets the smallest unsigned integer type capable of representing all values
166/// up to, but not including, the value of `Self`.
167///
168/// `Self` is an unsigned [type-level integer](typenum).
169///
170/// The type is provided as the associated type [`Self::Type`]. If you just
171/// want the type and aren’t specifying trait bounds, use the type alias
172/// [`SmallestUIntUpTo`].
173pub trait GetSmallestUIntUpTo: Unsigned + detail::GetSmallestUIntUpTo {
174    /// The unsigned integer type.
175    type Type: Default + PrimInt + NumAssign;
176}
177
178/// Alias of [`GetSmallestUIntUpTo::Type`].
179pub type SmallestUIntUpTo<N> = <N as GetSmallestUIntUpTo>::Type;
180
181impl<N> GetSmallestUIntUpTo for N
182where
183    N: detail::GetSmallestUIntUpTo,
184{
185    type Type = <N as detail::GetSmallestUIntUpTo>::Type;
186}