lexical_write_float/
index.rs

1//! Wrapper around indexing for opt-in, additional safety.
2//!
3//! By default, writers tend to be safe, due to Miri, Valgrind,
4//! and other tests and careful validation against a wide range
5//! of randomized input. Parsers are much trickier to validate.
6
7#![cfg_attr(not(feature = "power-of-two"), allow(unused_macros))]
8#![doc(hidden)]
9
10/// Enable an assertion only when the `safe` feature is enabled.
11macro_rules! safe_assert {
12    ($cond:expr $(,)?) => {
13        #[cfg(feature = "safe")]
14        assert!($cond);
15    };
16}
17
18/// Index a buffer, without bounds checking.
19#[cfg(not(feature = "safe"))]
20macro_rules! index_unchecked {
21    ($x:ident[$i:expr]) => {
22        *$x.get_unchecked($i)
23    };
24}
25
26/// Index a buffer and get a mutable reference, without bounds checking.
27#[cfg(not(feature = "safe"))]
28macro_rules! index_unchecked_mut {
29    ($x:ident[$i:expr]) => {
30        *$x.get_unchecked_mut($i)
31    };
32
33    ($x:ident[$i:expr] = $y:ident[$j:expr]) => {
34        *$x.get_unchecked_mut($i) = *$y.get_unchecked($j)
35    };
36}
37
38/// Fill a slice with a value, without bounds checking.
39#[cfg(not(feature = "safe"))]
40macro_rules! slice_fill_unchecked {
41    ($slc:expr, $value:expr) => {
42        // Get the length first to avoid stacked borrows, since we might
43        // have a complex expression for the slice calculation.
44        let len = $slc.len();
45        core::ptr::write_bytes($slc.as_mut_ptr(), $value, len)
46    };
47}
48
49/// Copy to a slice without overlaps, without bounds checking.
50#[cfg(not(feature = "safe"))]
51macro_rules! copy_nonoverlapping_unchecked {
52    ($dst:expr, $src:expr, $srclen:expr) => {
53        core::ptr::copy_nonoverlapping($src, $dst.as_mut_ptr(), $srclen)
54    };
55}
56
57/// Index a buffer, with bounds checking.
58#[cfg(feature = "safe")]
59macro_rules! index_unchecked {
60    ($x:ident[$i:expr]) => {
61        $x[$i]
62    };
63}
64
65/// Index a buffer and get a mutable reference, with bounds checking.
66#[cfg(feature = "safe")]
67macro_rules! index_unchecked_mut {
68    ($x:ident[$i:expr]) => {
69        $x[$i]
70    };
71
72    ($x:ident[$i:expr] = $y:ident[$j:expr]) => {
73        $x[$i] = $y[$j]
74    };
75}
76
77/// Fill a slice with a value, with bounds checking.
78#[cfg(feature = "safe")]
79macro_rules! slice_fill_unchecked {
80    ($slc:expr, $value:expr) => {
81        $slc.fill($value)
82    };
83}
84
85/// Copy to a slice, with bounds checking.
86#[cfg(feature = "safe")]
87macro_rules! copy_nonoverlapping_unchecked {
88    ($dst:expr, $src:expr, $srclen:expr) => {
89        let slc = unsafe { core::slice::from_raw_parts($src, $srclen) };
90        $dst.copy_from_slice(slc)
91    };
92}