1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
//! Shared trait and methods for writing integers.

#![doc(hidden)]

/// Select the back-end.
#[cfg(feature = "compact")]
use crate::compact::Compact;
#[cfg(not(feature = "compact"))]
use crate::decimal::Decimal;
#[cfg(all(not(feature = "compact"), feature = "power-of-two"))]
use crate::radix::Radix;
use lexical_util::format;

/// Define the implementation to write significant digits.
macro_rules! write_mantissa {
    ($($t:tt)+) => (
        /// Internal implementation to write significant digits for float writers.
        ///
        /// # Safety
        ///
        /// Safe as long as the buffer can hold `FORMATTED_SIZE` elements.
        #[doc(hidden)]
        #[inline(always)]
        unsafe fn write_mantissa<U, const FORMAT: u128>(self, buffer: &mut [u8]) -> usize
        where
            U: $($t)+,
        {
            // SAFETY: safe as long as the buffer can hold `FORMATTED_SIZE` elements.
            unsafe { self.write_integer::<U, FORMAT, { format::RADIX }, { format::RADIX_SHIFT }>(buffer) }
        }
    )
}

/// Define the implementation to write exponent digits.
macro_rules! write_exponent {
    ($($t:tt)+) => (
        /// Internal implementation to write exponent digits for float writers.
        ///
        /// # Safety
        ///
        /// Safe as long as the buffer can hold `FORMATTED_SIZE` elements.
        #[doc(hidden)]
        #[inline(always)]
        unsafe fn write_exponent<U, const FORMAT: u128>(self, buffer: &mut [u8]) -> usize
        where
            U: $($t)+,
        {
            // SAFETY: safe as long as the buffer can hold `FORMATTED_SIZE` elements.
            unsafe { self.write_integer::<U, FORMAT, { format::EXPONENT_RADIX }, { format::EXPONENT_RADIX_SHIFT }>(buffer) }
        }
    )
}

/// Write integer trait, implemented in terms of the compact back-end.
#[cfg(feature = "compact")]
pub trait WriteInteger: Compact {
    /// Forward write integer parameters to an unoptimized backend.
    ///
    /// # Preconditions
    ///
    /// `self` must be non-negative and unsigned.
    ///
    /// # Safety
    ///
    /// Safe as long as the buffer can hold [`FORMATTED_SIZE`] elements
    /// (or [`FORMATTED_SIZE_DECIMAL`] for decimal).
    ///
    /// [`FORMATTED_SIZE`]: lexical_util::constants::FormattedSize::FORMATTED_SIZE
    /// [`FORMATTED_SIZE_DECIMAL`]: lexical_util::constants::FormattedSize::FORMATTED_SIZE_DECIMAL
    unsafe fn write_integer<U, const FORMAT: u128, const MASK: u128, const SHIFT: i32>(
        self,
        buffer: &mut [u8],
    ) -> usize
    where
        U: Compact,
    {
        let value = U::as_cast(self);
        let radix = format::radix_from_flags(FORMAT, MASK, SHIFT);
        unsafe { value.compact(radix, buffer) }
    }

    write_mantissa!(Compact);
    write_exponent!(Compact);
}

/// Write integer trait, implemented in terms of the optimized, decimal back-end.
#[cfg(all(not(feature = "compact"), not(feature = "power-of-two")))]
pub trait WriteInteger: Decimal {
    /// Forward write integer parameters to an optimized backend.
    ///
    /// # Preconditions
    ///
    /// `self` must be non-negative and unsigned.
    ///
    /// # Safety
    ///
    /// Safe as long as the buffer can hold [`FORMATTED_SIZE_DECIMAL`] elements.
    ///
    /// [`FORMATTED_SIZE_DECIMAL`]: lexical_util::constants::FormattedSize::FORMATTED_SIZE_DECIMAL
    #[inline]
    unsafe fn write_integer<U, const __: u128, const ___: u128, const ____: i32>(
        self,
        buffer: &mut [u8],
    ) -> usize
    where
        U: Decimal,
    {
        let value = U::as_cast(self);
        unsafe { value.decimal(buffer) }
    }

    write_mantissa!(Decimal);
    write_exponent!(Decimal);
}

/// Write integer trait, implemented in terms of the optimized, decimal or radix back-end.
#[cfg(all(not(feature = "compact"), feature = "power-of-two"))]
pub trait WriteInteger: Decimal + Radix {
    /// Forward write integer parameters to an optimized backend.
    ///
    /// # Preconditions
    ///
    /// `self` must be non-negative and unsigned.
    ///
    /// # Safety
    ///
    /// Safe as long as the buffer can hold [`FORMATTED_SIZE`] elements
    /// (or [`FORMATTED_SIZE_DECIMAL`] for decimal).
    ///
    /// [`FORMATTED_SIZE`]: lexical_util::constants::FormattedSize::FORMATTED_SIZE
    /// [`FORMATTED_SIZE_DECIMAL`]: lexical_util::constants::FormattedSize::FORMATTED_SIZE_DECIMAL
    #[inline]
    unsafe fn write_integer<U, const FORMAT: u128, const MASK: u128, const SHIFT: i32>(
        self,
        buffer: &mut [u8],
    ) -> usize
    where
        U: Decimal + Radix,
    {
        let value = U::as_cast(self);
        if format::radix_from_flags(FORMAT, MASK, SHIFT) == 10 {
            unsafe { value.decimal(buffer) }
        } else {
            unsafe { value.radix::<FORMAT, MASK, SHIFT>(buffer) }
        }
    }

    write_mantissa!(Decimal + Radix);
    write_exponent!(Decimal + Radix);
}

macro_rules! write_integer_impl {
    ($($t:ty)*) => ($(
        impl WriteInteger for $t {}
    )*)
}

write_integer_impl! { u8 u16 u32 u64 u128 usize }