# Implementation overview
It is easy to get the floating point printing correct but slow (Russ Cox has
-[demonstrated](http://research.swtch.com/ftoa) how it's easy), or incorrect but
+[demonstrated](https://research.swtch.com/ftoa) how it's easy), or incorrect but
fast (naïve division and modulo). But it is surprisingly hard to print
floating point numbers correctly *and* efficiently.
pub use self::decoder::{decode, DecodableFloat, Decoded, FullDecoded};
+use super::fmt::{Formatted, Part};
use crate::mem::MaybeUninit;
pub mod decoder;
}
}
-/// 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)
- }
-}
-
/// Formats given decimal digits `0.<...buf...> * 10^exp` into the decimal form
/// with at least given number of fractional digits. The result is stored to
/// the supplied parts array and a slice of written parts is returned.