const_panic/
int_formatting.rs
1use crate::{
2 fmt::{FmtArg, NumberFmt},
3 utils::{Sign, TailShortString},
4};
5
6pub(crate) const fn fmt_decimal<const N: usize>(sign: Sign, mut n: u128) -> TailShortString<N> {
7 let mut start = N;
8 let mut buffer = [0u8; N];
9
10 loop {
11 start -= 1;
12 let digit = (n % 10) as u8;
13 buffer[start] = b'0' + digit;
14 n /= 10;
15 if n == 0 {
16 break;
17 }
18 }
19
20 if let Sign::Negative = sign {
21 start -= 1;
22 buffer[start] = b'-';
23 }
24
25 unsafe { TailShortString::new(start as u8, buffer) }
27}
28
29pub(crate) const fn fmt_binary<const N: usize>(
30 mut n: u128,
31 is_alternate: bool,
32) -> TailShortString<N> {
33 let mut start = N;
34 let mut buffer = [0u8; N];
35
36 loop {
37 start -= 1;
38 let digit = (n & 1) as u8;
39 buffer[start] = b'0' + digit;
40 n >>= 1;
41 if n == 0 {
42 break;
43 }
44 }
45
46 if is_alternate {
47 start -= 1;
48 buffer[start] = b'b';
49 start -= 1;
50 buffer[start] = b'0';
51 }
52
53 unsafe { TailShortString::new(start as u8, buffer) }
55}
56
57pub(crate) const fn fmt_hexadecimal<const N: usize>(
58 mut n: u128,
59 is_alternate: bool,
60) -> TailShortString<N> {
61 let mut start = N;
62 let mut buffer = [0u8; N];
63
64 loop {
65 start -= 1;
66 let digit = (n & 0xF) as u8;
67 buffer[start] = match digit {
68 0..=9 => b'0' + digit,
69 _ => b'A' - 10 + digit,
70 };
71 n >>= 4;
72 if n == 0 {
73 break;
74 }
75 }
76
77 if is_alternate {
78 start -= 1;
79 buffer[start] = b'x';
80 start -= 1;
81 buffer[start] = b'0';
82 }
83
84 unsafe { TailShortString::new(start as u8, buffer) }
86}
87
88pub(crate) const fn compute_len(sign: Sign, int: u128, bits: u8, fmt: FmtArg) -> u8 {
89 match fmt.number_fmt {
90 NumberFmt::Decimal => compute_decimal_len(sign, int),
91 NumberFmt::Hexadecimal => {
92 let with_0x = (fmt.is_alternate as u8) * 2;
93 let i = match sign {
94 Sign::Negative => bits,
95 Sign::Positive => (128 - int.leading_zeros()) as u8,
96 };
97 let tmp = if i == 0 {
98 1
99 } else {
100 i / 4 + (i % 4 != 0) as u8
101 };
102 tmp + with_0x
103 }
104 NumberFmt::Binary => {
105 let with_0b = (fmt.is_alternate as u8) * 2;
106 let i = match sign {
107 Sign::Negative => bits,
108 Sign::Positive => (128 - int.leading_zeros()) as u8,
109 };
110 (if i == 0 { 1 } else { i }) + with_0b
111 }
112 }
113}
114
115const fn compute_decimal_len(sign: Sign, mut n: u128) -> u8 {
116 let mut len = matches!(sign, Sign::Negative) as u8 + 1;
117 if n >= 1_0000_0000_0000_0000 {
118 n /= 1_0000_0000_0000_0000;
119 len += 16;
120 }
121 if n >= 1_0000_0000_0000 {
122 n /= 1_0000_0000_0000;
123 len += 12;
124 }
125 if n >= 1_0000_0000 {
126 n /= 100_000_000;
127 len += 8;
128 }
129 if n >= 1_0000 {
130 n /= 1_0000;
131 len += 4;
132 }
133 if n >= 100 {
134 n /= 100;
135 len += 2;
136 }
137 if n >= 10 {
138 len += 1;
139 }
140 len
141}