1#![allow(trivial_numeric_casts)]
2
3use core::marker::PhantomData;
4use core::num::{NonZeroU128, NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU8, NonZeroUsize};
5use core::ptr;
6
7use crate::buffer::Buffer;
8use crate::constants::*;
9use crate::format::Format;
10use crate::grouping::Grouping;
11use crate::sealed::Sealed;
12use crate::to_formatted_str::ToFormattedStr;
13
14impl ToFormattedStr for u8 {
17 #[doc(hidden)]
18 #[inline(always)]
19 fn read_to_buffer<'a, F>(&self, buf: &'a mut Buffer, _: &F) -> usize
20 where
21 F: Format,
22 {
23 buf.write_with_itoa(*self)
24 }
25}
26
27macro_rules! impl_unsigned {
28 ($type:ty, $max_len:expr) => {
29 impl ToFormattedStr for $type {
30 #[doc(hidden)]
31 #[inline(always)]
32 fn read_to_buffer<'a, F>(&self, buf: &'a mut Buffer, format: &F) -> usize
33 where
34 F: Format,
35 {
36 let n = *self as u128;
37 run_core_algorithm(n, buf, format)
38 }
39 }
40 };
41}
42
43impl_unsigned!(u16, U16_MAX_LEN);
44impl_unsigned!(u32, U32_MAX_LEN);
45impl_unsigned!(usize, USIZE_MAX_LEN);
46impl_unsigned!(u64, U64_MAX_LEN);
47impl_unsigned!(u128, U128_MAX_LEN);
48
49impl Sealed for u8 {}
50impl Sealed for u16 {}
51impl Sealed for u32 {}
52impl Sealed for usize {}
53impl Sealed for u64 {}
54impl Sealed for u128 {}
55
56macro_rules! impl_signed {
59 ($type:ty, $max_len:expr) => {
60 impl ToFormattedStr for $type {
61 #[doc(hidden)]
62 #[inline(always)]
63 fn read_to_buffer<'a, F>(&self, buf: &'a mut Buffer, format: &F) -> usize
64 where
65 F: Format,
66 {
67 if self.is_negative() {
68 let n = (!(*self as u128)).wrapping_add(1); let c = run_core_algorithm(n, buf, format);
70 let minus_sign = format.minus_sign().into_str();
71 let min_len = minus_sign.len();
72 buf.pos -= min_len;
73 for (i, byte) in minus_sign.as_bytes().iter().enumerate() {
74 buf.inner[buf.pos + i] = *byte;
75 }
76 c + min_len
77 } else {
78 let n = *self as u128;
79 let c = run_core_algorithm(n, buf, format);
80 c
81 }
82 }
83 }
84 };
85}
86
87impl_signed!(i8, I8_MAX_LEN);
88impl_signed!(i16, I16_MAX_LEN);
89impl_signed!(i32, I32_MAX_LEN);
90impl_signed!(isize, ISIZE_MAX_LEN);
91impl_signed!(i64, I64_MAX_LEN);
92impl_signed!(i128, I128_MAX_LEN);
93
94impl Sealed for i8 {}
95impl Sealed for i16 {}
96impl Sealed for i32 {}
97impl Sealed for isize {}
98impl Sealed for i64 {}
99impl Sealed for i128 {}
100
101impl ToFormattedStr for NonZeroU8 {
104 #[doc(hidden)]
105 #[inline(always)]
106 fn read_to_buffer<'a, F>(&self, buf: &'a mut Buffer, _: &F) -> usize
107 where
108 F: Format,
109 {
110 buf.write_with_itoa(self.get())
111 }
112}
113
114macro_rules! impl_non_zero {
115 ($type:ty, $related_type:ty, $max_len:expr) => {
116 impl ToFormattedStr for $type {
117 #[doc(hidden)]
118 #[inline(always)]
119 fn read_to_buffer<'a, F>(&self, buf: &'a mut Buffer, format: &F) -> usize
120 where
121 F: Format,
122 {
123 let n = self.get() as u128;
124 run_core_algorithm(n, buf, format)
125 }
126 }
127 };
128}
129
130impl_non_zero!(NonZeroU16, u16, U16_MAX_LEN);
131impl_non_zero!(NonZeroU32, u32, U32_MAX_LEN);
132impl_non_zero!(NonZeroUsize, usize, USIZE_MAX_LEN);
133impl_non_zero!(NonZeroU64, u64, U64_MAX_LEN);
134impl_non_zero!(NonZeroU128, u128, U128_MAX_LEN);
135
136impl Sealed for NonZeroU8 {}
137impl Sealed for NonZeroU16 {}
138impl Sealed for NonZeroU32 {}
139impl Sealed for NonZeroUsize {}
140impl Sealed for NonZeroU64 {}
141impl Sealed for NonZeroU128 {}
142
143#[inline(always)]
146fn run_core_algorithm<F>(mut n: u128, buf: &mut Buffer, format: &F) -> usize
147where
148 F: Format,
149{
150 let separator = format.separator().into_str();
153 let grouping = format.grouping();
154 if separator.is_empty() || grouping == Grouping::Posix {
155 return buf.write_with_itoa(n);
156 }
157
158 buf.pos = MAX_BUF_LEN;
160 buf.end = MAX_BUF_LEN;
161
162 let mut sep = Sep {
164 ptr: separator.as_bytes().as_ptr(),
165 len: separator.len(),
166 pos: MAX_BUF_LEN as isize - 4,
167 step: match grouping {
168 Grouping::Standard => 4isize,
169 Grouping::Indian => 3isize,
170 Grouping::Posix => unreachable!(),
171 },
172 phantom: PhantomData,
173 };
174
175 while n >= 10_000 {
177 let remainder = n % 10_000;
178 let table_index = ((remainder % 100) << 1) as isize;
179 write_two_bytes(buf, &mut sep, table_index);
180 let table_index = ((remainder / 100) << 1) as isize;
181 write_two_bytes(buf, &mut sep, table_index);
182 n /= 10_000;
183 }
184 let mut n = n as isize;
185 while n >= 100 {
186 let table_index = (n % 100) << 1;
187 write_two_bytes(buf, &mut sep, table_index);
188 n /= 100;
189 }
190 if n >= 10 {
191 let table_index = n << 1;
192 write_two_bytes(buf, &mut sep, table_index);
193 } else {
194 let table_index = n << 1;
195 write_one_byte(buf, &mut sep, table_index + 1);
196 }
197
198 buf.end - buf.pos
199}
200
201struct Sep<'a> {
202 ptr: *const u8,
203 len: usize,
204 pos: isize,
205 step: isize,
206 phantom: PhantomData<&'a ()>,
207}
208
209#[inline(always)]
210fn write_one_byte(buf: &mut Buffer, sep: &mut Sep<'_>, table_index: isize) {
211 buf.pos -= 1;
212 if sep.pos == (buf.pos as isize) {
213 buf.pos -= sep.len - 1;
214 unsafe { ptr::copy_nonoverlapping(sep.ptr, buf.as_mut_ptr().add(buf.pos), sep.len) }
215 sep.pos -= sep.step + (sep.len as isize - 1);
216 buf.pos -= 1;
217 }
218 unsafe {
219 ptr::copy_nonoverlapping(
220 TABLE.as_ptr().offset(table_index),
221 buf.as_mut_ptr().add(buf.pos),
222 1,
223 )
224 };
225}
226
227#[inline(always)]
228fn write_two_bytes(buf: &mut Buffer, sep: &mut Sep<'_>, table_index: isize) {
229 write_one_byte(buf, sep, table_index + 1);
230 write_one_byte(buf, sep, table_index);
231}