lexical_write_integer/write.rs
1//! Shared trait and methods for writing integers.
2
3#![doc(hidden)]
4
5/// Select the back-end.
6#[cfg(feature = "compact")]
7use crate::compact::Compact;
8#[cfg(not(feature = "compact"))]
9use crate::decimal::Decimal;
10#[cfg(all(not(feature = "compact"), feature = "power-of-two"))]
11use crate::radix::Radix;
12use lexical_util::format;
13
14/// Define the implementation to write significant digits.
15macro_rules! write_mantissa {
16 ($($t:tt)+) => (
17 /// Internal implementation to write significant digits for float writers.
18 ///
19 /// # Safety
20 ///
21 /// Safe as long as the buffer can hold `FORMATTED_SIZE` elements.
22 #[doc(hidden)]
23 #[inline(always)]
24 unsafe fn write_mantissa<U, const FORMAT: u128>(self, buffer: &mut [u8]) -> usize
25 where
26 U: $($t)+,
27 {
28 // SAFETY: safe as long as the buffer can hold `FORMATTED_SIZE` elements.
29 unsafe { self.write_integer::<U, FORMAT, { format::RADIX }, { format::RADIX_SHIFT }>(buffer) }
30 }
31 )
32}
33
34/// Define the implementation to write exponent digits.
35macro_rules! write_exponent {
36 ($($t:tt)+) => (
37 /// Internal implementation to write exponent digits for float writers.
38 ///
39 /// # Safety
40 ///
41 /// Safe as long as the buffer can hold `FORMATTED_SIZE` elements.
42 #[doc(hidden)]
43 #[inline(always)]
44 unsafe fn write_exponent<U, const FORMAT: u128>(self, buffer: &mut [u8]) -> usize
45 where
46 U: $($t)+,
47 {
48 // SAFETY: safe as long as the buffer can hold `FORMATTED_SIZE` elements.
49 unsafe { self.write_integer::<U, FORMAT, { format::EXPONENT_RADIX }, { format::EXPONENT_RADIX_SHIFT }>(buffer) }
50 }
51 )
52}
53
54/// Write integer trait, implemented in terms of the compact back-end.
55#[cfg(feature = "compact")]
56pub trait WriteInteger: Compact {
57 /// Forward write integer parameters to an unoptimized backend.
58 ///
59 /// # Preconditions
60 ///
61 /// `self` must be non-negative and unsigned.
62 ///
63 /// # Safety
64 ///
65 /// Safe as long as the buffer can hold [`FORMATTED_SIZE`] elements
66 /// (or [`FORMATTED_SIZE_DECIMAL`] for decimal).
67 ///
68 /// [`FORMATTED_SIZE`]: lexical_util::constants::FormattedSize::FORMATTED_SIZE
69 /// [`FORMATTED_SIZE_DECIMAL`]: lexical_util::constants::FormattedSize::FORMATTED_SIZE_DECIMAL
70 unsafe fn write_integer<U, const FORMAT: u128, const MASK: u128, const SHIFT: i32>(
71 self,
72 buffer: &mut [u8],
73 ) -> usize
74 where
75 U: Compact,
76 {
77 let value = U::as_cast(self);
78 let radix = format::radix_from_flags(FORMAT, MASK, SHIFT);
79 unsafe { value.compact(radix, buffer) }
80 }
81
82 write_mantissa!(Compact);
83 write_exponent!(Compact);
84}
85
86/// Write integer trait, implemented in terms of the optimized, decimal back-end.
87#[cfg(all(not(feature = "compact"), not(feature = "power-of-two")))]
88pub trait WriteInteger: Decimal {
89 /// Forward write integer parameters to an optimized backend.
90 ///
91 /// # Preconditions
92 ///
93 /// `self` must be non-negative and unsigned.
94 ///
95 /// # Safety
96 ///
97 /// Safe as long as the buffer can hold [`FORMATTED_SIZE_DECIMAL`] elements.
98 ///
99 /// [`FORMATTED_SIZE_DECIMAL`]: lexical_util::constants::FormattedSize::FORMATTED_SIZE_DECIMAL
100 #[inline]
101 unsafe fn write_integer<U, const __: u128, const ___: u128, const ____: i32>(
102 self,
103 buffer: &mut [u8],
104 ) -> usize
105 where
106 U: Decimal,
107 {
108 let value = U::as_cast(self);
109 unsafe { value.decimal(buffer) }
110 }
111
112 write_mantissa!(Decimal);
113 write_exponent!(Decimal);
114}
115
116/// Write integer trait, implemented in terms of the optimized, decimal or radix back-end.
117#[cfg(all(not(feature = "compact"), feature = "power-of-two"))]
118pub trait WriteInteger: Decimal + Radix {
119 /// Forward write integer parameters to an optimized backend.
120 ///
121 /// # Preconditions
122 ///
123 /// `self` must be non-negative and unsigned.
124 ///
125 /// # Safety
126 ///
127 /// Safe as long as the buffer can hold [`FORMATTED_SIZE`] elements
128 /// (or [`FORMATTED_SIZE_DECIMAL`] for decimal).
129 ///
130 /// [`FORMATTED_SIZE`]: lexical_util::constants::FormattedSize::FORMATTED_SIZE
131 /// [`FORMATTED_SIZE_DECIMAL`]: lexical_util::constants::FormattedSize::FORMATTED_SIZE_DECIMAL
132 #[inline]
133 unsafe fn write_integer<U, const FORMAT: u128, const MASK: u128, const SHIFT: i32>(
134 self,
135 buffer: &mut [u8],
136 ) -> usize
137 where
138 U: Decimal + Radix,
139 {
140 let value = U::as_cast(self);
141 if format::radix_from_flags(FORMAT, MASK, SHIFT) == 10 {
142 unsafe { value.decimal(buffer) }
143 } else {
144 unsafe { value.radix::<FORMAT, MASK, SHIFT>(buffer) }
145 }
146 }
147
148 write_mantissa!(Decimal + Radix);
149 write_exponent!(Decimal + Radix);
150}
151
152macro_rules! write_integer_impl {
153 ($($t:ty)*) => ($(
154 impl WriteInteger for $t {}
155 )*)
156}
157
158write_integer_impl! { u8 u16 u32 u64 u128 usize }