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}