lexical_write_float/
write.rs1#![doc(hidden)]
4
5#[cfg(not(feature = "compact"))]
6use crate::algorithm::write_float as write_float_decimal;
7#[cfg(feature = "power-of-two")]
8use crate::binary;
9#[cfg(feature = "compact")]
11use crate::compact::write_float as write_float_decimal;
12#[cfg(feature = "power-of-two")]
13use crate::hex;
14#[cfg(feature = "radix")]
15use crate::radix;
16
17use crate::float::RawFloat;
18use crate::options::Options;
19#[cfg(feature = "f16")]
20use lexical_util::bf16::bf16;
21use lexical_util::constants::FormattedSize;
22#[cfg(feature = "f16")]
23use lexical_util::f16::f16;
24use lexical_util::format::NumberFormat;
25use lexical_write_integer::write::WriteInteger;
26
27pub trait WriteFloat: RawFloat {
29 #[inline]
53 unsafe fn write_float<const FORMAT: u128>(self, bytes: &mut [u8], options: &Options) -> usize
54 where
55 Self::Unsigned: FormattedSize + WriteInteger,
56 {
57 let format = NumberFormat::<FORMAT> {};
59 assert!(format.is_valid());
60 assert!(Self::BITS <= 64);
62
63 #[cfg(feature = "power-of-two")]
64 {
65 if format.radix() != format.exponent_base() {
66 assert!(matches!(
67 (format.radix(), format.exponent_base()),
68 (4, 2) | (8, 2) | (16, 2) | (32, 2) | (16, 4)
69 ));
70 }
71 }
72
73 let (float, count, bytes) = if self < Self::ZERO {
74 unsafe { index_unchecked_mut!(bytes[0]) = b'-' };
76 (-self, 1, unsafe { &mut index_unchecked_mut!(bytes[1..]) })
77 } else if cfg!(feature = "format") && format.required_mantissa_sign() {
78 unsafe { index_unchecked_mut!(bytes[0]) = b'+' };
80 (self, 1, unsafe { &mut index_unchecked_mut!(bytes[1..]) })
81 } else {
82 (self, 0, bytes)
83 };
84
85 if !self.is_special() {
87 #[cfg(all(feature = "power-of-two", not(feature = "radix")))]
88 {
89 let radix = format.radix();
91 let exponent_base = format.exponent_base();
92 count
93 + if radix == 10 {
94 unsafe { write_float_decimal::<_, FORMAT>(float, bytes, options) }
95 } else if radix != exponent_base {
96 unsafe { hex::write_float::<_, FORMAT>(float, bytes, options) }
97 } else {
98 unsafe { binary::write_float::<_, FORMAT>(float, bytes, options) }
99 }
100 }
101
102 #[cfg(feature = "radix")]
103 {
104 let radix = format.radix();
106 let exponent_base = format.exponent_base();
107 count
108 + if radix == 10 {
109 unsafe { write_float_decimal::<_, FORMAT>(float, bytes, options) }
110 } else if radix != exponent_base {
111 unsafe { hex::write_float::<_, FORMAT>(float, bytes, options) }
112 } else if matches!(radix, 2 | 4 | 8 | 16 | 32) {
113 unsafe { binary::write_float::<_, FORMAT>(float, bytes, options) }
114 } else {
115 unsafe { radix::write_float::<_, FORMAT>(float, bytes, options) }
116 }
117 }
118
119 #[cfg(not(feature = "power-of-two"))]
120 {
121 count + unsafe { write_float_decimal::<_, FORMAT>(float, bytes, options) }
123 }
124 } else if self.is_nan() {
125 if let Some(nan_string) = options.nan_string() {
129 let length = nan_string.len();
130 unsafe {
131 let src = nan_string.as_ptr();
132 let dst = &mut index_unchecked_mut!(bytes[..length]);
133 copy_nonoverlapping_unchecked!(dst, src, length);
134 }
135 count + length
136 } else {
137 panic!("NaN explicitly disabled but asked to write NaN as string.");
139 }
140 } else {
141 if let Some(inf_string) = options.inf_string() {
146 let length = inf_string.len();
147 unsafe {
148 let src = inf_string.as_ptr();
149 let dst = &mut index_unchecked_mut!(bytes[..length]);
150 copy_nonoverlapping_unchecked!(dst, src, length);
151 }
152 count + length
153 } else {
154 panic!("Inf explicitly disabled but asked to write Inf as string.");
156 }
157 }
158 }
159}
160
161macro_rules! write_float_impl {
162 ($($t:ty)*) => ($(
163 impl WriteFloat for $t {}
164 )*)
165}
166
167write_float_impl! { f32 f64 }
168
169#[cfg(feature = "f16")]
170macro_rules! write_float_as_f32 {
171 ($($t:ty)*) => ($(
172 impl WriteFloat for $t {
173 #[inline]
174 unsafe fn write_float<const FORMAT: u128>(self, bytes: &mut [u8], options: &Options) -> usize
175 {
176 unsafe { self.as_f32().write_float::<FORMAT>(bytes, options) }
178 }
179 }
180 )*)
181}
182
183#[cfg(feature = "f16")]
184write_float_as_f32! { bf16 f16 }