1#[cfg(test)]
57mod tests;
58
59use core::num::{NonZeroI128, NonZeroU128};
60use core::num::{NonZeroI16, NonZeroU16};
61use core::num::{NonZeroI32, NonZeroU32};
62use core::num::{NonZeroI64, NonZeroU64};
63use core::num::{NonZeroI8, NonZeroU8};
64use core::num::{NonZeroIsize, NonZeroUsize};
65use std::fmt::{Display, Formatter, Result};
66use std::iter::successors;
67
68#[derive(Debug, Clone, Copy)]
83pub struct Radix<T> {
84 n: T,
85 base: u8,
86}
87
88impl<T> Radix<T>
89where
90 Radix<T>: Display,
91{
92 pub fn new(n: T, base: u8) -> Self {
95 assert!(base >= 2 && base <= 36);
96
97 Radix { n, base }
98 }
99}
100
101#[inline(always)]
102fn digit(u: u8, alternate: bool) -> u8 {
103 let a = if alternate { b'A' } else { b'a' };
104
105 match u {
106 0...9 => u + b'0',
107 10...35 => u - 10 + a,
108 _ => unreachable!("Digit is not in range [0..36]"),
109 }
110}
111
112const BUF_SIZE: usize = 81; macro_rules! impl_display_for {
115 ($i: ty => $via: ty as $u: ty) => {
116 impl Display for Radix<$i> {
117 fn fmt(&self, f: &mut Formatter) -> Result {
118 fn do_format(n: $u, base: $u, f: &mut Formatter) -> Result {
119 let mut buffer = [0_u8; BUF_SIZE];
120 let divided = successors(Some(n), |n| match n / base {
121 0 => None,
122 n => Some(n),
123 });
124 let written = buffer
125 .iter_mut()
126 .rev()
127 .zip(divided)
128 .map(|(c, n)| *c = digit((n % base) as u8, f.alternate()))
129 .count();
130 let index = BUF_SIZE - written;
131
132 let s = unsafe { std::str::from_utf8_unchecked(&buffer[index..]) };
135
136 f.write_str(s)
137 }
138
139 match (self.base, f.alternate()) {
140 (2, _) => write!(f, "{:b}", self.n),
141 (8, _) => write!(f, "{:o}", self.n),
142 (10, _) => write!(f, "{}", self.n),
143 (16, false) => write!(f, "{:x}", self.n),
144 (16, true) => write!(f, "{:X}", self.n),
145 (base, _) => do_format(<$via>::from(self.n) as $u, base.into(), f),
146 }
147 }
148 }
149 };
150}
151
152impl_display_for!(i8 => i8 as u8);
153impl_display_for!(u8 => u8 as u8);
154
155impl_display_for!(i16 => i16 as u16);
156impl_display_for!(u16 => u16 as u16);
157
158impl_display_for!(i32 => i32 as u32);
159impl_display_for!(u32 => u32 as u32);
160
161impl_display_for!(i64 => i64 as u64);
162impl_display_for!(u64 => u64 as u64);
163
164impl_display_for!(i128 => i128 as u128);
165impl_display_for!(u128 => u128 as u128);
166
167impl_display_for!(isize => isize as usize);
168impl_display_for!(usize => usize as usize);
169
170impl_display_for!(NonZeroI8 => i8 as u8);
171impl_display_for!(NonZeroU8 => u8 as u8);
172
173impl_display_for!(NonZeroI16 => i16 as u16);
174impl_display_for!(NonZeroU16 => u16 as u16);
175
176impl_display_for!(NonZeroI32 => i32 as u32);
177impl_display_for!(NonZeroU32 => u32 as u32);
178
179impl_display_for!(NonZeroI64 => i64 as u64);
180impl_display_for!(NonZeroU64 => u64 as u64);
181
182impl_display_for!(NonZeroI128 => i128 as u128);
183impl_display_for!(NonZeroU128 => u128 as u128);
184
185impl_display_for!(NonZeroIsize => isize as usize);
186impl_display_for!(NonZeroUsize => usize as usize);
187
188pub fn radix<T>(n: T, base: u8) -> Radix<T>
201where
202 Radix<T>: Display,
203{
204 Radix::new(n, base)
205}
206pub fn radix_3<T>(n: T) -> Radix<T>
208where
209 Radix<T>: Display,
210{
211 Radix::new(n, 3)
212}
213pub fn radix_4<T>(n: T) -> Radix<T>
215where
216 Radix<T>: Display,
217{
218 Radix::new(n, 4)
219}
220pub fn radix_5<T>(n: T) -> Radix<T>
222where
223 Radix<T>: Display,
224{
225 Radix::new(n, 5)
226}
227pub fn radix_6<T>(n: T) -> Radix<T>
229where
230 Radix<T>: Display,
231{
232 Radix::new(n, 6)
233}
234pub fn radix_7<T>(n: T) -> Radix<T>
236where
237 Radix<T>: Display,
238{
239 Radix::new(n, 7)
240}
241pub fn radix_9<T>(n: T) -> Radix<T>
243where
244 Radix<T>: Display,
245{
246 Radix::new(n, 9)
247}
248pub fn radix_11<T>(n: T) -> Radix<T>
250where
251 Radix<T>: Display,
252{
253 Radix::new(n, 11)
254}
255pub fn radix_12<T>(n: T) -> Radix<T>
257where
258 Radix<T>: Display,
259{
260 Radix::new(n, 12)
261}
262pub fn radix_13<T>(n: T) -> Radix<T>
264where
265 Radix<T>: Display,
266{
267 Radix::new(n, 13)
268}
269pub fn radix_14<T>(n: T) -> Radix<T>
271where
272 Radix<T>: Display,
273{
274 Radix::new(n, 14)
275}
276pub fn radix_15<T>(n: T) -> Radix<T>
278where
279 Radix<T>: Display,
280{
281 Radix::new(n, 15)
282}
283pub fn radix_17<T>(n: T) -> Radix<T>
285where
286 Radix<T>: Display,
287{
288 Radix::new(n, 17)
289}
290pub fn radix_18<T>(n: T) -> Radix<T>
292where
293 Radix<T>: Display,
294{
295 Radix::new(n, 18)
296}
297pub fn radix_19<T>(n: T) -> Radix<T>
299where
300 Radix<T>: Display,
301{
302 Radix::new(n, 19)
303}
304pub fn radix_20<T>(n: T) -> Radix<T>
306where
307 Radix<T>: Display,
308{
309 Radix::new(n, 20)
310}
311pub fn radix_21<T>(n: T) -> Radix<T>
313where
314 Radix<T>: Display,
315{
316 Radix::new(n, 21)
317}
318pub fn radix_22<T>(n: T) -> Radix<T>
320where
321 Radix<T>: Display,
322{
323 Radix::new(n, 22)
324}
325pub fn radix_23<T>(n: T) -> Radix<T>
327where
328 Radix<T>: Display,
329{
330 Radix::new(n, 23)
331}
332pub fn radix_24<T>(n: T) -> Radix<T>
334where
335 Radix<T>: Display,
336{
337 Radix::new(n, 24)
338}
339pub fn radix_25<T>(n: T) -> Radix<T>
341where
342 Radix<T>: Display,
343{
344 Radix::new(n, 25)
345}
346pub fn radix_26<T>(n: T) -> Radix<T>
348where
349 Radix<T>: Display,
350{
351 Radix::new(n, 26)
352}
353pub fn radix_27<T>(n: T) -> Radix<T>
355where
356 Radix<T>: Display,
357{
358 Radix::new(n, 27)
359}
360pub fn radix_28<T>(n: T) -> Radix<T>
362where
363 Radix<T>: Display,
364{
365 Radix::new(n, 28)
366}
367pub fn radix_29<T>(n: T) -> Radix<T>
369where
370 Radix<T>: Display,
371{
372 Radix::new(n, 29)
373}
374pub fn radix_30<T>(n: T) -> Radix<T>
376where
377 Radix<T>: Display,
378{
379 Radix::new(n, 30)
380}
381pub fn radix_31<T>(n: T) -> Radix<T>
383where
384 Radix<T>: Display,
385{
386 Radix::new(n, 31)
387}
388pub fn radix_32<T>(n: T) -> Radix<T>
390where
391 Radix<T>: Display,
392{
393 Radix::new(n, 32)
394}
395pub fn radix_33<T>(n: T) -> Radix<T>
397where
398 Radix<T>: Display,
399{
400 Radix::new(n, 33)
401}
402pub fn radix_34<T>(n: T) -> Radix<T>
404where
405 Radix<T>: Display,
406{
407 Radix::new(n, 34)
408}
409pub fn radix_35<T>(n: T) -> Radix<T>
411where
412 Radix<T>: Display,
413{
414 Radix::new(n, 35)
415}
416pub fn radix_36<T>(n: T) -> Radix<T>
418where
419 Radix<T>: Display,
420{
421 Radix::new(n, 36)
422}