devela/text/ascii/wrapper.rs
1// devela::text::ascii::wrapper
2//
3//! Ascii functionality wrapper struct.
4//
5
6use crate::iif;
7
8// imports for the `digits_str` method
9#[cfg(all(feature = "_str_u8", any(feature = "safe_text", not(feature = "unsafe_str"))))]
10use crate::unwrap;
11#[cfg(all(feature = "_str_u8", feature = "_cmp_u8"))]
12use crate::Compare;
13#[cfg(feature = "_str_u8")]
14use crate::StringU8;
15
16#[doc = crate::TAG_NAMESPACE!()]
17/// Provides ASCII operations on `T`, most of them *const*.
18#[derive(Clone, Copy)]
19#[repr(transparent)]
20pub struct Ascii<T: Copy>(pub T);
21
22impl Ascii<usize> {
23 /// The maximum number of decimal digits a `usize` can represent in the current platform.
24 pub const MAX_DIGITS: usize = Ascii(usize::MAX).count_digits() as usize;
25
26 /// Returns the ASCII byte of a specific digit in a `usize` number.
27 ///
28 /// # Arguments
29 /// * `divisor`: A power of 10 used to determine which digit to extract.
30 ///
31 /// # Examples
32 /// ```
33 /// # use devela::text::Ascii;
34 /// assert_eq!(Ascii(12345_usize).calc_digit(10), b'4');
35 /// assert_eq!(Ascii(12345_usize).calc_digit(1000), b'2');
36 /// ```
37 #[must_use]
38 pub const fn calc_digit(self, divisor: usize) -> u8 {
39 (self.0 / divisor % 10) as u8 + b'0'
40 }
41
42 /// Counts the number of decimal digits.
43 ///
44 /// For more complex needs check the [`Int`][crate::Int] *base* methods.
45 /// # Examples
46 /// ```
47 /// # use devela::text::Ascii;
48 /// assert_eq![1, Ascii(0_usize).count_digits()];
49 /// assert_eq![4, Ascii(9876_usize).count_digits()];
50 /// ```
51 #[must_use]
52 pub const fn count_digits(self) -> u8 {
53 iif![self.0 == 0; 1; self.0.ilog10() as u8 + 1]
54 }
55
56 /// Converts a `usize` into a byte array of `5` ascii digits with leading zeros.
57 ///
58 /// The actual array length depends on the target platform's pointer size.
59 ///
60 /// You can trim the leading zeros with
61 /// [`trim_leading_bytes`][crate::Slice::trim_leading_bytes].
62 #[must_use] #[cfg(target_pointer_width = "16")] #[rustfmt::skip]
63 pub const fn digits(self) -> [u8; Self::MAX_DIGITS] {
64 Ascii(self.0 as u16).digits()
65 }
66
67 /// Converts a `usize` into a byte array of `10` ascii digits with leading zeros.
68 ///
69 /// The actual array length depends on the target platform's pointer size.
70 ///
71 /// You can trim the leading zeros with
72 /// [`trim_leading_bytes`][crate::Slice::trim_leading_bytes].
73 #[must_use] #[cfg(target_pointer_width = "32")] #[rustfmt::skip]
74 pub const fn digits(self) -> [u8; Self::MAX_DIGITS] {
75 Ascii(self.0 as u32).digits()
76 }
77
78 /// Converts a `usize` into a byte array of `20` ascii digits with leading zeros.
79 ///
80 /// The actual array length depends on the target platform's pointer size.
81 ///
82 /// You can trim the leading zeros with
83 /// [`trim_leading_bytes`][crate::Slice::trim_leading_bytes].
84 #[must_use] #[cfg(target_pointer_width = "64")] #[rustfmt::skip]
85 pub const fn digits(self) -> [u8; Self::MAX_DIGITS] {
86 Ascii(self.0 as u64).digits()
87 }
88
89 /// Returns a static string with zero-padded digits with minimum `width`.
90 ///
91 /// The given `width` will be clamped betweeen the actual number of digits
92 /// and the maximum number of digits.
93 ///
94 /// # Features
95 /// - Will only be *const* if the `_cmp_u8` feature is enabled.
96 /// - Makes use of the `unsafe_str` feature if enabled.
97 #[cfg(feature = "_cmp_u8")] // const
98 #[cfg(feature = "_str_u8")]
99 #[cfg_attr(feature = "nightly_doc", doc(cfg(feature = "string_u8")))]
100 pub const fn digits_str(self, width: u8) -> StringU8<{ Self::MAX_DIGITS }> {
101 let width = Compare(width).clamp(self.count_digits(), Self::MAX_DIGITS as u8);
102
103 #[cfg(any(feature = "safe_text", not(feature = "unsafe_str")))]
104 return unwrap![ok StringU8::<{Self::MAX_DIGITS}>::from_bytes_nright(self.digits(), width)];
105 #[cfg(all(not(feature = "safe_text"), feature = "unsafe_str"))]
106 // SAFETY: the bytes are valid utf-8
107 unsafe {
108 StringU8::<{ Self::MAX_DIGITS }>::from_bytes_nright_unchecked(self.digits(), width)
109 }
110 }
111 #[allow(missing_docs)]
112 #[cfg(not(feature = "_cmp_u8"))] // !const
113 #[cfg(feature = "_str_u8")]
114 pub fn digits_str(self, width: u8) -> StringU8<{ Self::MAX_DIGITS }> {
115 let width = width.max(self.count_digits()).min(Self::MAX_DIGITS as u8);
116
117 #[cfg(any(feature = "safe_text", not(feature = "unsafe_str")))]
118 return unwrap![ok StringU8::<{Self::MAX_DIGITS}>::from_bytes_nright(self.digits(), width)];
119 #[cfg(all(not(feature = "safe_text"), feature = "unsafe_str"))]
120 // SAFETY: the bytes are valid utf-8
121 unsafe {
122 StringU8::<{ Self::MAX_DIGITS }>::from_bytes_nright_unchecked(self.digits(), width)
123 }
124 }
125}
126
127impl Ascii<u8> {
128 /// The maximum number of decimal digits a `u8` can represent.
129 pub const MAX_DIGITS: usize = 3;
130
131 /// Returns the ASCII byte of a specific digit in a `u8` number.
132 ///
133 /// # Arguments
134 /// * `divisor`: A power of 10 used to determine which digit to extract.
135 ///
136 /// # Examples
137 /// ```
138 /// # use devela::text::Ascii;
139 /// assert_eq!(Ascii(123_u8).calc_digit(10), b'2');
140 /// assert_eq!(Ascii(123_u8).calc_digit(100), b'1');
141 /// ```
142 #[must_use]
143 pub const fn calc_digit(self, divisor: u8) -> u8 {
144 (self.0 / divisor % 10) + b'0'
145 }
146
147 /// Counts the number of decimal digits.
148 ///
149 /// For more complex needs check the [`Int`][crate::num::Int] *base* methods.
150 /// # Examples
151 /// ```
152 /// # use devela::text::Ascii;
153 /// assert_eq![1, Ascii(0_u8).count_digits()];
154 /// assert_eq![3, Ascii(123_u8).count_digits()];
155 /// ```
156 #[must_use]
157 pub const fn count_digits(self) -> u8 {
158 iif![self.0 == 0; 1; self.0.ilog10() as u8 + 1]
159 }
160
161 /// Converts a `u8` into a byte array of `3` ASCII digits with leading zeros.
162 ///
163 /// You can trim the leading zeros with
164 /// [`trim_leading_bytes`][crate::Slice::trim_leading_bytes].
165 #[must_use]
166 pub const fn digits(self) -> [u8; 3] {
167 [
168 // 321
169 // 255 u8::MAX
170 self.calc_digit(100),
171 self.calc_digit(10),
172 self.calc_digit(1),
173 ]
174 }
175
176 /// Returns a static string with zero-padded digits with minimum `width`.
177 ///
178 /// The given `width` will be clamped betweeen the actual number of digits
179 /// and the maximum number of digits.
180 ///
181 /// # Features
182 /// - Will only be *const* if the `_cmp_u8` feature is enabled.
183 /// - Makes use of the `unsafe_str` feature if enabled.
184 #[cfg(feature = "_cmp_u8")] // const
185 #[cfg(feature = "_str_u8")]
186 #[cfg_attr(feature = "nightly_doc", doc(cfg(feature = "string_u8")))]
187 pub const fn digits_str(self, width: u8) -> StringU8<3> {
188 let width = Compare(width).clamp(self.count_digits(), 3);
189
190 #[cfg(any(feature = "safe_text", not(feature = "unsafe_str")))]
191 return unwrap![ok StringU8::<3>::from_bytes_nright(self.digits(), width)];
192 #[cfg(all(not(feature = "safe_text"), feature = "unsafe_str"))]
193 // SAFETY: the bytes are valid utf-8
194 unsafe {
195 StringU8::<3>::from_bytes_nright_unchecked(self.digits(), width)
196 }
197 }
198 #[allow(missing_docs)]
199 #[cfg(not(feature = "_cmp_u8"))] // !const
200 #[cfg(feature = "_str_u8")]
201 pub fn digits_str(self, width: u8) -> StringU8<3> {
202 let width = width.max(self.count_digits()).min(3);
203
204 #[cfg(any(feature = "safe_text", not(feature = "unsafe_str")))]
205 return unwrap![ok StringU8::<3>::from_bytes_nright(self.digits(), width)];
206 #[cfg(all(not(feature = "safe_text"), feature = "unsafe_str"))]
207 // SAFETY: the bytes are valid utf-8
208 unsafe {
209 StringU8::<3>::from_bytes_nright_unchecked(self.digits(), width)
210 }
211 }
212
213 /// Converts a one-digit number to the corresponding `1` ASCII digit.
214 ///
215 /// # Panics
216 /// This function panics in debug if the given number is > 9.
217 #[must_use]
218 pub const fn digits_1(self) -> u8 {
219 debug_assert![self.0 <= 9];
220 self.0 + b'0'
221 }
222
223 /// Converts a two-digit number to the corresponding `2` ASCII digits.
224 ///
225 /// # Panics
226 /// This function panics in debug if the given number is > 99.
227 #[must_use]
228 pub const fn digits_2(self) -> [u8; 2] {
229 debug_assert![self.0 <= 99];
230 [self.calc_digit(10), self.calc_digit(1)]
231 }
232}
233
234impl Ascii<u16> {
235 /// The maximum number of decimal digits a `u16` can represent.
236 pub const MAX_DIGITS: usize = 5;
237
238 /// Returns the ASCII byte of a specific digit in a `u16` number.
239 ///
240 /// # Arguments
241 /// * `divisor`: A power of 10 used to determine which digit to extract.
242 ///
243 /// # Examples
244 /// ```
245 /// # use devela::text::Ascii;
246 /// assert_eq!(Ascii(12345_u16).calc_digit(10), b'4');
247 /// assert_eq!(Ascii(12345_u16).calc_digit(1000), b'2');
248 /// ```
249 #[must_use]
250 pub const fn calc_digit(self, divisor: u16) -> u8 {
251 (self.0 / divisor % 10) as u8 + b'0'
252 }
253
254 /// Counts the number of decimal digits.
255 ///
256 /// For more complex needs check the [`Int`][crate::num::Int] *base* methods.
257 /// # Examples
258 /// ```
259 /// # use devela::text::Ascii;
260 /// assert_eq![1, Ascii(0_u16).count_digits()];
261 /// assert_eq![4, Ascii(9876_u16).count_digits()];
262 /// ```
263 #[must_use]
264 pub const fn count_digits(self) -> u8 {
265 iif![self.0 == 0; 1; self.0.ilog10() as u8 + 1]
266 }
267
268 /// Converts a `u16` into a byte array of `5` ASCII digits with leading zeros.
269 ///
270 /// You can trim the leading zeros with
271 /// [`trim_leading_bytes`][crate::Slice::trim_leading_bytes].
272 #[must_use]
273 pub const fn digits(self) -> [u8; 5] {
274 [
275 // 54321
276 // 65535 ← u16::MAX
277 self.calc_digit(10000), // 5 digits
278 self.calc_digit(1000),
279 self.calc_digit(100),
280 self.calc_digit(10),
281 self.calc_digit(1),
282 ]
283 }
284
285 /// Returns a static string with zero-padded digits with minimum `width`.
286 ///
287 /// The given `width` will be clamped betweeen the actual number of digits
288 /// and the maximum number of digits.
289 ///
290 /// # Features
291 /// - Will only be *const* if the `_cmp_u8` feature is enabled.
292 /// - Makes use of the `unsafe_str` feature if enabled.
293 #[cfg(feature = "_cmp_u8")] // const
294 #[cfg(feature = "_str_u8")]
295 #[cfg_attr(feature = "nightly_doc", doc(cfg(feature = "string_u8")))]
296 pub const fn digits_str(self, width: u8) -> StringU8<5> {
297 let width = Compare(width).clamp(self.count_digits(), 5);
298
299 #[cfg(any(feature = "safe_text", not(feature = "unsafe_str")))]
300 return unwrap![ok StringU8::<5>::from_bytes_nright(self.digits(), width)];
301 #[cfg(all(not(feature = "safe_text"), feature = "unsafe_str"))]
302 // SAFETY: the bytes are valid utf-8
303 unsafe {
304 StringU8::<5>::from_bytes_nright_unchecked(self.digits(), width)
305 }
306 }
307 #[allow(missing_docs)]
308 #[cfg(not(feature = "_cmp_u8"))] // !const
309 #[cfg(feature = "_str_u8")]
310 pub fn digits_str(self, width: u8) -> StringU8<5> {
311 let width = width.max(self.count_digits()).min(5);
312
313 #[cfg(any(feature = "safe_text", not(feature = "unsafe_str")))]
314 return unwrap![ok StringU8::<5>::from_bytes_nright(self.digits(), width)];
315 #[cfg(all(not(feature = "safe_text"), feature = "unsafe_str"))]
316 // SAFETY: the bytes are valid utf-8
317 unsafe {
318 StringU8::<5>::from_bytes_nright_unchecked(self.digits(), width)
319 }
320 }
321
322 /// Converts a three-digit number to the corresponding `3` ASCII digits.
323 ///
324 /// # Panics
325 /// This function panics in debug if the given number is > 999.
326 #[must_use]
327 pub const fn digits_3(self) -> [u8; 3] {
328 debug_assert![self.0 <= 999];
329 [self.calc_digit(100), self.calc_digit(10), self.calc_digit(1)]
330 }
331
332 /// Converts a four-digit number to the corresponding `4` ASCII digits.
333 ///
334 /// # Panics
335 /// This function panics in debug if the given number is > 9999.
336 #[must_use]
337 pub const fn digits_4(self) -> [u8; 4] {
338 debug_assert![self.0 <= 9999];
339 [self.calc_digit(1000), self.calc_digit(100), self.calc_digit(10), self.calc_digit(1)]
340 }
341}
342
343impl Ascii<u32> {
344 /// The maximum number of decimal digits a `u32` can represent.
345 pub const MAX_DIGITS: usize = 10;
346
347 /// Returns the ASCII byte of a specific digit in a `u32` number.
348 ///
349 /// # Arguments
350 /// * `divisor`: A power of 10 used to determine which digit to extract.
351 ///
352 /// # Examples
353 /// ```
354 /// # use devela::text::Ascii;
355 /// assert_eq!(Ascii(12345_u32).calc_digit(10), b'4');
356 /// assert_eq!(Ascii(12345_u32).calc_digit(1000), b'2');
357 /// ```
358 #[must_use]
359 pub const fn calc_digit(self, divisor: u32) -> u8 {
360 (self.0 / divisor % 10) as u8 + b'0'
361 }
362
363 /// Counts the number of decimal digits.
364 ///
365 /// For more complex needs check the [`Int`][crate::num::Int] *base* methods.
366 /// # Examples
367 /// ```
368 /// # use devela::text::Ascii;
369 /// assert_eq![1, Ascii(0_u32).count_digits()];
370 /// assert_eq![4, Ascii(9876_u32).count_digits()];
371 /// ```
372 #[must_use]
373 pub const fn count_digits(self) -> u8 {
374 iif![self.0 == 0; 1; self.0.ilog10() as u8 + 1]
375 }
376
377 /// Converts a `u32` into a byte array of `10` ASCII digits with leading zeros.
378 ///
379 /// You can trim the leading zeros with
380 /// [`trim_leading_bytes`][crate::Slice::trim_leading_bytes].
381 #[must_use]
382 #[allow(clippy::unreadable_literal)]
383 pub const fn digits(self) -> [u8; 10] {
384 [
385 // 0987654321
386 // 4294967295 ← u32::MAX
387 self.calc_digit(1000000000), // 10 digits
388 self.calc_digit(100000000),
389 self.calc_digit(10000000),
390 self.calc_digit(1000000),
391 self.calc_digit(100000),
392 self.calc_digit(10000), // 5 digits
393 self.calc_digit(1000),
394 self.calc_digit(100),
395 self.calc_digit(10),
396 self.calc_digit(1),
397 ]
398 }
399
400 /// Returns a static string with zero-padded digits with minimum `width`.
401 ///
402 /// The given `width` will be clamped betweeen the actual number of digits
403 /// and the maximum number of digits.
404 ///
405 /// # Features
406 /// - Will only be *const* if the `_cmp_u8` feature is enabled.
407 /// - Makes use of the `unsafe_str` feature if enabled.
408 #[cfg(feature = "_cmp_u8")] // const
409 #[cfg(feature = "_str_u8")]
410 #[cfg_attr(feature = "nightly_doc", doc(cfg(feature = "string_u8")))]
411 pub const fn digits_str(self, width: u8) -> StringU8<10> {
412 let width = Compare(width).clamp(self.count_digits(), 10);
413
414 #[cfg(any(feature = "safe_text", not(feature = "unsafe_str")))]
415 return unwrap![ok StringU8::<10>::from_bytes_nright(self.digits(), width)];
416 #[cfg(all(not(feature = "safe_text"), feature = "unsafe_str"))]
417 // SAFETY: the bytes are valid utf-8
418 unsafe {
419 StringU8::<10>::from_bytes_nright_unchecked(self.digits(), width)
420 }
421 }
422 #[allow(missing_docs)]
423 #[cfg(not(feature = "_cmp_u8"))] // !const
424 #[cfg(feature = "_str_u8")]
425 pub fn digits_str(self, width: u8) -> StringU8<10> {
426 let width = width.max(self.count_digits()).min(10);
427
428 #[cfg(any(feature = "safe_text", not(feature = "unsafe_str")))]
429 return unwrap![ok StringU8::<10>::from_bytes_nright(self.digits(), width)];
430 #[cfg(all(not(feature = "safe_text"), feature = "unsafe_str"))]
431 // SAFETY: the bytes are valid utf-8
432 unsafe {
433 StringU8::<10>::from_bytes_nright_unchecked(self.digits(), width)
434 }
435 }
436}
437
438impl Ascii<u64> {
439 /// The maximum number of decimal digits a `u64` can represent.
440 pub const MAX_DIGITS: usize = 20;
441
442 /// Returns the ASCII byte of a specific digit in a `u64` number.
443 ///
444 /// # Arguments
445 /// * `divisor`: A power of 10 used to determine which digit to extract.
446 ///
447 /// # Examples
448 /// ```
449 /// # use devela::text::Ascii;
450 /// assert_eq!(Ascii(12345_u64).calc_digit(10), b'4');
451 /// assert_eq!(Ascii(12345_u64).calc_digit(1000), b'2');
452 /// ```
453 #[must_use]
454 pub const fn calc_digit(self, divisor: u64) -> u8 {
455 (self.0 / divisor % 10) as u8 + b'0'
456 }
457
458 /// Counts the number of decimal digits.
459 ///
460 /// For more complex needs check the [`Int`][crate::num::Int] *base* methods.
461 /// # Examples
462 /// ```
463 /// # use devela::text::Ascii;
464 /// assert_eq![1, Ascii(0_u64).count_digits()];
465 /// assert_eq![4, Ascii(9876_u64).count_digits()];
466 /// ```
467 #[must_use]
468 pub const fn count_digits(self) -> u8 {
469 iif![self.0 == 0; 1; self.0.ilog10() as u8 + 1]
470 }
471
472 /// Converts a `u64` into a byte array of `20` ascii digits with leading zeros.
473 ///
474 /// You can trim the leading zeros with
475 /// [`trim_leading_bytes`][crate::Slice::trim_leading_bytes].
476 #[must_use]
477 #[allow(clippy::unreadable_literal)]
478 pub const fn digits(self) -> [u8; 20] {
479 [
480 // 0987654321_987654321
481 // 18446744073709551615 ← u64::MAX
482 self.calc_digit(10000000000000000000), // 20 digits
483 self.calc_digit(1000000000000000000),
484 self.calc_digit(100000000000000000),
485 self.calc_digit(10000000000000000),
486 self.calc_digit(1000000000000000),
487 self.calc_digit(100000000000000),
488 self.calc_digit(10000000000000),
489 self.calc_digit(1000000000000),
490 self.calc_digit(100000000000),
491 self.calc_digit(10000000000),
492 self.calc_digit(1000000000), // 10 digits
493 self.calc_digit(100000000),
494 self.calc_digit(10000000),
495 self.calc_digit(1000000),
496 self.calc_digit(100000),
497 self.calc_digit(10000),
498 self.calc_digit(1000),
499 self.calc_digit(100),
500 self.calc_digit(10),
501 self.calc_digit(1),
502 ]
503 }
504
505 /// Returns a static string with zero-padded digits with minimum `width`.
506 ///
507 /// The given `width` will be clamped betweeen the actual number of digits
508 /// and the maximum number of digits.
509 ///
510 /// # Features
511 /// - Will only be *const* if the `_cmp_u8` feature is enabled.
512 /// - Makes use of the `unsafe_str` feature if enabled.
513 #[cfg(feature = "_cmp_u8")] // const
514 #[cfg(feature = "_str_u8")]
515 #[cfg_attr(feature = "nightly_doc", doc(cfg(feature = "string_u8")))]
516 pub const fn digits_str(self, width: u8) -> StringU8<20> {
517 let width = Compare(width).clamp(self.count_digits(), 20);
518
519 #[cfg(any(feature = "safe_text", not(feature = "unsafe_str")))]
520 return unwrap![ok StringU8::<20>::from_bytes_nright(self.digits(), width)];
521 #[cfg(all(not(feature = "safe_text"), feature = "unsafe_str"))]
522 // SAFETY: the bytes are valid utf-8
523 unsafe {
524 StringU8::<20>::from_bytes_nright_unchecked(self.digits(), width)
525 }
526 }
527 #[allow(missing_docs)]
528 #[cfg(not(feature = "_cmp_u8"))] // !const
529 #[cfg(feature = "_str_u8")]
530 pub fn digits_str(self, width: u8) -> StringU8<20> {
531 let width = width.max(self.count_digits()).min(20);
532
533 #[cfg(any(feature = "safe_text", not(feature = "unsafe_str")))]
534 return unwrap![ok StringU8::<20>::from_bytes_nright(self.digits(), width)];
535 #[cfg(all(not(feature = "safe_text"), feature = "unsafe_str"))]
536 // SAFETY: the bytes are valid utf-8
537 unsafe {
538 StringU8::<20>::from_bytes_nright_unchecked(self.digits(), width)
539 }
540 }
541}
542
543impl Ascii<u128> {
544 /// The maximum number of decimal digits a `u128` can represent.
545 pub const MAX_DIGITS: usize = 30;
546
547 /// Returns the ASCII byte of a specific digit in a `u128` number.
548 ///
549 /// # Arguments
550 /// * `divisor`: A power of 10 used to determine which digit to extract.
551 ///
552 /// # Examples
553 /// ```
554 /// # use devela::text::Ascii;
555 /// assert_eq!(Ascii(12345_u128).calc_digit(10), b'4');
556 /// assert_eq!(Ascii(12345_u128).calc_digit(1000), b'2');
557 /// ```
558 #[must_use]
559 pub const fn calc_digit(self, divisor: u128) -> u8 {
560 (self.0 / divisor % 10) as u8 + b'0'
561 }
562
563 /// Counts the number of decimal digits.
564 ///
565 /// For more complex needs check the [`Int`][crate::num::Int] *base* methods.
566 /// # Examples
567 /// ```
568 /// # use devela::text::Ascii;
569 /// assert_eq![1, Ascii(0_u128).count_digits()];
570 /// assert_eq![19, Ascii(9876543210987654321_u128).count_digits()];
571 /// ```
572 #[must_use]
573 pub const fn count_digits(self) -> u8 {
574 iif![self.0 == 0; 1; self.0.ilog10() as u8 + 1]
575 }
576
577 /// Converts a `u128` into a byte array of `39` ascii digits with leading zeros.
578 ///
579 /// You can trim the leading zeros with
580 /// [`trim_leading_bytes`][crate::Slice::trim_leading_bytes].
581 #[must_use]
582 #[allow(clippy::unreadable_literal)]
583 pub const fn digits(self) -> [u8; 39] {
584 [
585 // 987654321_987654321_987654321_987654321
586 // 340282366920938463463374607431768211455 ← u128::MAX
587 self.calc_digit(100000000000000000000000000000000000000), // 39 digits
588 self.calc_digit(10000000000000000000000000000000000000),
589 self.calc_digit(1000000000000000000000000000000000000),
590 self.calc_digit(100000000000000000000000000000000000),
591 self.calc_digit(10000000000000000000000000000000000),
592 self.calc_digit(1000000000000000000000000000000000),
593 self.calc_digit(100000000000000000000000000000000),
594 self.calc_digit(10000000000000000000000000000000),
595 self.calc_digit(1000000000000000000000000000000),
596 self.calc_digit(100000000000000000000000000000), // 30 digits
597 self.calc_digit(10000000000000000000000000000),
598 self.calc_digit(1000000000000000000000000000),
599 self.calc_digit(100000000000000000000000000),
600 self.calc_digit(10000000000000000000000000),
601 self.calc_digit(1000000000000000000000000),
602 self.calc_digit(100000000000000000000000),
603 self.calc_digit(10000000000000000000000),
604 self.calc_digit(1000000000000000000000),
605 self.calc_digit(100000000000000000000),
606 self.calc_digit(10000000000000000000), // 20 digits
607 self.calc_digit(1000000000000000000),
608 self.calc_digit(100000000000000000),
609 self.calc_digit(10000000000000000),
610 self.calc_digit(1000000000000000),
611 self.calc_digit(100000000000000),
612 self.calc_digit(10000000000000),
613 self.calc_digit(1000000000000),
614 self.calc_digit(100000000000),
615 self.calc_digit(10000000000),
616 self.calc_digit(1000000000), // 10 digits
617 self.calc_digit(100000000),
618 self.calc_digit(10000000),
619 self.calc_digit(1000000),
620 self.calc_digit(100000),
621 self.calc_digit(10000),
622 self.calc_digit(1000),
623 self.calc_digit(100),
624 self.calc_digit(10),
625 self.calc_digit(1),
626 ]
627 }
628
629 /// Returns a static string with zero-padded digits with minimum `width`.
630 ///
631 /// The given `width` will be clamped betweeen the actual number of digits
632 /// and the maximum number of digits.
633 ///
634 /// # Features
635 /// - Will only be *const* if the `_cmp_u8` feature is enabled.
636 /// - Makes use of the `unsafe_str` feature if enabled.
637 #[cfg(feature = "_cmp_u8")] // const
638 #[cfg(feature = "_str_u8")]
639 #[cfg_attr(feature = "nightly_doc", doc(cfg(feature = "string_u8")))]
640 pub const fn digits_str(self, width: u8) -> StringU8<39> {
641 let width = Compare(width).clamp(self.count_digits(), 39);
642
643 #[cfg(any(feature = "safe_text", not(feature = "unsafe_str")))]
644 return unwrap![ok StringU8::<39>::from_bytes_nright(self.digits(), width)];
645 #[cfg(all(not(feature = "safe_text"), feature = "unsafe_str"))]
646 // SAFETY: the bytes are valid utf-8
647 unsafe {
648 StringU8::<39>::from_bytes_nright_unchecked(self.digits(), width)
649 }
650 }
651 #[cfg(not(feature = "_cmp_u8"))] // !const
652 #[cfg(feature = "_str_u8")]
653 #[allow(missing_docs)]
654 pub fn digits_str(self, width: u8) -> StringU8<39> {
655 let width = width.max(self.count_digits()).min(39);
656
657 #[cfg(any(feature = "safe_text", not(feature = "unsafe_str")))]
658 return unwrap![ok StringU8::<39>::from_bytes_nright(self.digits(), width)];
659 #[cfg(all(not(feature = "safe_text"), feature = "unsafe_str"))]
660 // SAFETY: the bytes are valid utf-8
661 unsafe {
662 StringU8::<39>::from_bytes_nright_unchecked(self.digits(), width)
663 }
664 }
665}