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 }