Skip to content

Commit e076173

Browse files
authored
Merge pull request #16 from jkcclemens/maybe
Add MaybeUninit support
2 parents a0e85ea + 7372159 commit e076173

File tree

4 files changed

+105
-19
lines changed

4 files changed

+105
-19
lines changed

build.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,12 @@ fn main() {
2828
if minor >= 27 {
2929
println!("cargo:rustc-cfg=must_use_return");
3030
}
31+
32+
// MaybeUninit<T> stabilized in Rust 1.36:
33+
// https://blog.rust-lang.org/2019/07/04/Rust-1.36.0.html
34+
if minor >= 36 {
35+
println!("cargo:rustc-cfg=maybe_uninit");
36+
}
3137
}
3238

3339
fn rustc_minor_version() -> Option<u32> {

src/buffer/mod.rs

Lines changed: 40 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
use core::{mem, slice, str};
22

3+
#[cfg(maybe_uninit)]
4+
use core::mem::MaybeUninit;
5+
36
use raw;
47

58
#[cfg(feature = "no-panic")]
@@ -20,6 +23,9 @@ const NEG_INFINITY: &'static str = "-inf";
2023
/// ```
2124
#[derive(Copy, Clone)]
2225
pub struct Buffer {
26+
#[cfg(maybe_uninit)]
27+
bytes: [MaybeUninit<u8>; 24],
28+
#[cfg(not(maybe_uninit))]
2329
bytes: [u8; 24],
2430
}
2531

@@ -29,8 +35,15 @@ impl Buffer {
2935
#[inline]
3036
#[cfg_attr(feature = "no-panic", no_panic)]
3137
pub fn new() -> Self {
38+
// assume_init is safe here, since this is an array of MaybeUninit, which does not need
39+
// to be initialized.
40+
#[cfg(maybe_uninit)]
41+
let bytes = unsafe { MaybeUninit::uninit().assume_init() };
42+
#[cfg(not(maybe_uninit))]
43+
let bytes = unsafe { mem::uninitialized() };
44+
3245
Buffer {
33-
bytes: unsafe { mem::uninitialized() },
46+
bytes: bytes,
3447
}
3548
}
3649

@@ -74,12 +87,36 @@ impl Buffer {
7487
#[cfg_attr(feature = "no-panic", no_panic)]
7588
pub fn format_finite<F: Float>(&mut self, f: F) -> &str {
7689
unsafe {
77-
let n = f.write_to_ryu_buffer(&mut self.bytes[0]);
90+
let n = f.write_to_ryu_buffer(self.first_byte_pointer_mut());
7891
debug_assert!(n <= self.bytes.len());
79-
let slice = slice::from_raw_parts(&self.bytes[0], n);
92+
let slice = slice::from_raw_parts(self.first_byte_pointer(), n);
8093
str::from_utf8_unchecked(slice)
8194
}
8295
}
96+
97+
#[inline]
98+
#[cfg(maybe_uninit)]
99+
fn first_byte_pointer(&self) -> *const u8 {
100+
self.bytes[0].as_ptr()
101+
}
102+
103+
#[inline]
104+
#[cfg(not(maybe_uninit))]
105+
fn first_byte_pointer(&self) -> *const u8 {
106+
&self.bytes[0] as *const u8
107+
}
108+
109+
#[inline]
110+
#[cfg(maybe_uninit)]
111+
fn first_byte_pointer_mut(&mut self) -> *mut u8 {
112+
self.bytes[0].as_mut_ptr()
113+
}
114+
115+
#[inline]
116+
#[cfg(not(maybe_uninit))]
117+
fn first_byte_pointer_mut(&mut self) -> *mut u8 {
118+
&mut self.bytes[0] as *mut u8
119+
}
83120
}
84121

85122
impl Default for Buffer {

src/d2s.rs

Lines changed: 49 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,12 @@
1818
// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
1919
// KIND, either express or implied.
2020

21+
use core::ptr;
22+
23+
#[cfg(maybe_uninit)]
24+
use core::mem::MaybeUninit;
25+
26+
#[cfg(not(maybe_uninit))]
2127
use core::mem;
2228

2329
use common::*;
@@ -48,12 +54,14 @@ fn mul_shift_all(
4854
m: u64,
4955
mul: &(u64, u64),
5056
j: u32,
51-
vp: &mut u64,
52-
vm: &mut u64,
57+
vp: *mut u64,
58+
vm: *mut u64,
5359
mm_shift: u32,
5460
) -> u64 {
55-
*vp = mul_shift(4 * m + 2, mul, j);
56-
*vm = mul_shift(4 * m - 1 - mm_shift as u64, mul, j);
61+
unsafe {
62+
ptr::write(vp, mul_shift(4 * m + 2, mul, j));
63+
ptr::write(vm, mul_shift(4 * m - 1 - mm_shift as u64, mul, j));
64+
}
5765
mul_shift(4 * m, mul, j)
5866
}
5967

@@ -177,8 +185,17 @@ pub fn d2d(ieee_mantissa: u64, ieee_exponent: u32) -> FloatingDecimal64 {
177185

178186
// Step 3: Convert to a decimal power base using 128-bit arithmetic.
179187
let mut vr: u64;
180-
let mut vp: u64 = unsafe { mem::uninitialized() };
181-
let mut vm: u64 = unsafe { mem::uninitialized() };
188+
let mut vp: u64;
189+
let mut vm: u64;
190+
#[cfg(not(maybe_uninit))]
191+
{
192+
vp = unsafe { mem::uninitialized() };
193+
vm = unsafe { mem::uninitialized() };
194+
}
195+
#[cfg(maybe_uninit)]
196+
let mut vp_uninit: MaybeUninit<u64> = MaybeUninit::uninit();
197+
#[cfg(maybe_uninit)]
198+
let mut vm_uninit: MaybeUninit<u64> = MaybeUninit::uninit();
182199
let e10: i32;
183200
let mut vm_is_trailing_zeros = false;
184201
let mut vr_is_trailing_zeros = false;
@@ -201,10 +218,21 @@ pub fn d2d(ieee_mantissa: u64, ieee_exponent: u32) -> FloatingDecimal64 {
201218
DOUBLE_POW5_INV_SPLIT.get_unchecked(q as usize)
202219
},
203220
i as u32,
204-
&mut vp,
205-
&mut vm,
221+
#[cfg(maybe_uninit)]
222+
{ vp_uninit.as_mut_ptr() },
223+
#[cfg(not(maybe_uninit))]
224+
{ &mut vp },
225+
#[cfg(maybe_uninit)]
226+
{ vm_uninit.as_mut_ptr() },
227+
#[cfg(not(maybe_uninit))]
228+
{ &mut vm },
206229
mm_shift,
207230
);
231+
#[cfg(maybe_uninit)]
232+
{
233+
vp = unsafe { vp_uninit.assume_init() };
234+
vm = unsafe { vm_uninit.assume_init() };
235+
}
208236
if q <= 21 {
209237
// This should use q <= 22, but I think 21 is also safe. Smaller values
210238
// may still be safe, but it's more difficult to reason about them.
@@ -241,10 +269,21 @@ pub fn d2d(ieee_mantissa: u64, ieee_exponent: u32) -> FloatingDecimal64 {
241269
DOUBLE_POW5_SPLIT.get_unchecked(i as usize)
242270
},
243271
j as u32,
244-
&mut vp,
245-
&mut vm,
272+
#[cfg(maybe_uninit)]
273+
{ vp_uninit.as_mut_ptr() },
274+
#[cfg(not(maybe_uninit))]
275+
{ &mut vp },
276+
#[cfg(maybe_uninit)]
277+
{ vm_uninit.as_mut_ptr() },
278+
#[cfg(not(maybe_uninit))]
279+
{ &mut vm },
246280
mm_shift,
247281
);
282+
#[cfg(maybe_uninit)]
283+
{
284+
vp = unsafe { vp_uninit.assume_init() };
285+
vm = unsafe { vm_uninit.assume_init() };
286+
}
248287
if q <= 1 {
249288
// {vr,vp,vm} is trailing zeros if {mv,mp,mm} has at least q trailing 0 bits.
250289
// mv = 4 * m2, so it always has at least two trailing 0 bits.

src/pretty/mod.rs

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -38,12 +38,14 @@ use no_panic::no_panic;
3838
/// ## Example
3939
///
4040
/// ```edition2018
41+
/// use std::mem::MaybeUninit;
42+
///
4143
/// let f = 1.234f64;
4244
///
4345
/// unsafe {
44-
/// let mut buffer: [u8; 24] = std::mem::uninitialized();
45-
/// let len = ryu::raw::format64(f, buffer.as_mut_ptr());
46-
/// let slice = std::slice::from_raw_parts(buffer.as_ptr(), len);
46+
/// let mut buffer: [MaybeUninit<u8>; 24] = MaybeUninit::uninit().assume_init();
47+
/// let len = ryu::raw::format64(f, buffer.as_mut_ptr() as *mut u8);
48+
/// let slice = std::slice::from_raw_parts(buffer.as_ptr() as *const u8, len);
4749
/// let print = std::str::from_utf8_unchecked(slice);
4850
/// assert_eq!(print, "1.234");
4951
/// }
@@ -143,12 +145,14 @@ pub unsafe fn format64(f: f64, result: *mut u8) -> usize {
143145
/// ## Example
144146
///
145147
/// ```edition2018
148+
/// use std::mem::MaybeUninit;
149+
///
146150
/// let f = 1.234f32;
147151
///
148152
/// unsafe {
149-
/// let mut buffer: [u8; 16] = std::mem::uninitialized();
150-
/// let len = ryu::raw::format32(f, buffer.as_mut_ptr());
151-
/// let slice = std::slice::from_raw_parts(buffer.as_ptr(), len);
153+
/// let mut buffer: [MaybeUninit<u8>; 16] = MaybeUninit::uninit().assume_init();
154+
/// let len = ryu::raw::format32(f, buffer.as_mut_ptr() as *mut u8);
155+
/// let slice = std::slice::from_raw_parts(buffer.as_ptr() as *const u8, len);
152156
/// let print = std::str::from_utf8_unchecked(slice);
153157
/// assert_eq!(print, "1.234");
154158
/// }

0 commit comments

Comments
 (0)