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 }