-
Notifications
You must be signed in to change notification settings - Fork 13.1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Auto merge of #86048 - nbdd0121:no_floating_point, r=Amanieu
core: add unstable no_fp_fmt_parse to disable float formatting code In some projects (e.g. kernel), floating point is forbidden. They can disable hardware floating point support and use `+soft-float` to avoid fp instructions from being generated, but as libcore contains the formatting code for `f32` and `f64`, some fp intrinsics are depended. One could define stubs for these intrinsics that just panic [1], but it means that if any formatting functions are accidentally used, mistake can only be caught during the runtime rather than during compile-time or link-time, and they consume a lot of space without LTO. This patch provides an unstable cfg `no_fp_fmt_parse` to disable these. A panicking stub is still provided for the `Debug` implementation (unfortunately) because there are some SIMD types that use `#[derive(Debug)]`. [1]: https://lkml.org/lkml/2021/4/14/1028
- Loading branch information
Showing
10 changed files
with
160 additions
and
121 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
use crate::fmt::{Debug, Formatter, Result}; | ||
|
||
macro_rules! floating { | ||
($ty:ident) => { | ||
#[stable(feature = "rust1", since = "1.0.0")] | ||
impl Debug for $ty { | ||
fn fmt(&self, _fmt: &mut Formatter<'_>) -> Result { | ||
panic!("floating point support is turned off"); | ||
} | ||
} | ||
}; | ||
} | ||
|
||
floating! { f32 } | ||
floating! { f64 } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,108 @@ | ||
//! Shared utilties used by both float and integer formatting. | ||
#![doc(hidden)] | ||
#![unstable( | ||
feature = "numfmt", | ||
reason = "internal routines only exposed for testing", | ||
issue = "none" | ||
)] | ||
|
||
/// Formatted parts. | ||
#[derive(Copy, Clone, PartialEq, Eq, Debug)] | ||
pub enum Part<'a> { | ||
/// Given number of zero digits. | ||
Zero(usize), | ||
/// A literal number up to 5 digits. | ||
Num(u16), | ||
/// A verbatim copy of given bytes. | ||
Copy(&'a [u8]), | ||
} | ||
|
||
impl<'a> Part<'a> { | ||
/// Returns the exact byte length of given part. | ||
pub fn len(&self) -> usize { | ||
match *self { | ||
Part::Zero(nzeroes) => nzeroes, | ||
Part::Num(v) => { | ||
if v < 1_000 { | ||
if v < 10 { | ||
1 | ||
} else if v < 100 { | ||
2 | ||
} else { | ||
3 | ||
} | ||
} else { | ||
if v < 10_000 { 4 } else { 5 } | ||
} | ||
} | ||
Part::Copy(buf) => buf.len(), | ||
} | ||
} | ||
|
||
/// Writes a part into the supplied buffer. | ||
/// Returns the number of written bytes, or `None` if the buffer is not enough. | ||
/// (It may still leave partially written bytes in the buffer; do not rely on that.) | ||
pub fn write(&self, out: &mut [u8]) -> Option<usize> { | ||
let len = self.len(); | ||
if out.len() >= len { | ||
match *self { | ||
Part::Zero(nzeroes) => { | ||
for c in &mut out[..nzeroes] { | ||
*c = b'0'; | ||
} | ||
} | ||
Part::Num(mut v) => { | ||
for c in out[..len].iter_mut().rev() { | ||
*c = b'0' + (v % 10) as u8; | ||
v /= 10; | ||
} | ||
} | ||
Part::Copy(buf) => { | ||
out[..buf.len()].copy_from_slice(buf); | ||
} | ||
} | ||
Some(len) | ||
} else { | ||
None | ||
} | ||
} | ||
} | ||
|
||
/// Formatted result containing one or more parts. | ||
/// This can be written to the byte buffer or converted to the allocated string. | ||
#[allow(missing_debug_implementations)] | ||
#[derive(Clone)] | ||
pub struct Formatted<'a> { | ||
/// A byte slice representing a sign, either `""`, `"-"` or `"+"`. | ||
pub sign: &'static str, | ||
/// Formatted parts to be rendered after a sign and optional zero padding. | ||
pub parts: &'a [Part<'a>], | ||
} | ||
|
||
impl<'a> Formatted<'a> { | ||
/// Returns the exact byte length of combined formatted result. | ||
pub fn len(&self) -> usize { | ||
let mut len = self.sign.len(); | ||
for part in self.parts { | ||
len += part.len(); | ||
} | ||
len | ||
} | ||
|
||
/// Writes all formatted parts into the supplied buffer. | ||
/// Returns the number of written bytes, or `None` if the buffer is not enough. | ||
/// (It may still leave partially written bytes in the buffer; do not rely on that.) | ||
pub fn write(&self, out: &mut [u8]) -> Option<usize> { | ||
if out.len() < self.sign.len() { | ||
return None; | ||
} | ||
out[..self.sign.len()].copy_from_slice(self.sign.as_bytes()); | ||
|
||
let mut written = self.sign.len(); | ||
for part in self.parts { | ||
let len = part.write(&mut out[written..])?; | ||
written += len; | ||
} | ||
Some(written) | ||
} | ||
} |
Oops, something went wrong.