Documentation
/*
==--==--==--==--==--==--==--==--==--==--==--==--==--==--==--==--

SJ

Copyright (C) 2019-2025  Anonymous

There are several releases over multiple years,
they are listed as ranges, such as: "2019-2025".

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public License
along with this program.  If not, see <https://www.gnu.org/licenses/>.

::--::--::--::--::--::--::--::--::--::--::--::--::--::--::--::--
*/

//! # Number writer

#![cfg(feature="std")]
#![cfg(test)]

use {
    core::fmt::{self, Display, Formatter},
    alloc::string::ToString,
    std::{
        io::{self, Write},
        time::Instant,
    },
    crate::{IoResult, Number, NumberWriter},
    super::super::Kind,
};

enum Sample {
    Format,
    ToString,
    NumberWriter,
}

impl Display for Sample {

    fn fmt(&self, f: &mut Formatter) -> Result<(), fmt::Error> {
        f.write_str(match self {
            Sample::Format => "Format",
            Sample::ToString => "ToString",
            Sample::NumberWriter => "NumberWriter",
        })
    }

}

impl Sample {

    fn write<W>(&self, n: &Number, nw: &mut NumberWriter, stream: &mut W) -> IoResult<()> where W: Write {
        match self {
            Sample::Format => match n.kind {
                Kind::I64 => write!(stream, "{}", n.as_i64()),
                Kind::I128 => write!(stream, "{}", n.as_i128()),

                Kind::U64 => write!(stream, "{}", n.as_u64()),
                Kind::U128 => write!(stream, "{}", n.as_u128()),

                Kind::F32 => write!(stream, "{}", n.as_f32()),
                Kind::F64 => write!(stream, "{}", n.as_f64()),
            },
            Sample::ToString => match n.kind {
                Kind::I64 => stream.write_all(n.as_i64().to_string().as_bytes()),
                Kind::I128 => stream.write_all(n.as_i128().to_string().as_bytes()),

                Kind::U64 => stream.write_all(n.as_u64().to_string().as_bytes()),
                Kind::U128 => stream.write_all(n.as_u128().to_string().as_bytes()),

                Kind::F32 => stream.write_all(n.as_f32().to_string().as_bytes()),
                Kind::F64 => stream.write_all(n.as_f64().to_string().as_bytes()),
            },
            Sample::NumberWriter => nw.write(n, stream),
        }
    }

}

/// # Measures formatting integers
///
/// This test requires you to watch for results from stdout.
#[test]
#[ignore]
fn measure_formatting_integers() -> IoResult<()> {
    const COUNT: u32 = 1_500_000;

    fn test(s: Sample) -> IoResult<()> {
        let mut sink = io::sink();
        let mut nw = NumberWriter::new();

        let start = Instant::now();
        for i in 0..COUNT {
            s.write(&Number::from(u32::max_value() - i), &mut nw, &mut sink)?;
            s.write(&Number::from(i32::min_value() + i32::try_from(i).unwrap()), &mut nw, &mut sink)?;
            s.write(&Number::from(u64::max_value() - u64::from(i)), &mut nw, &mut sink)?;
            s.write(&Number::from(i64::min_value() + i64::from(i)), &mut nw, &mut sink)?;
        }

        std::println!("{s:>20}: {time:>15}", s=s.to_string(), time=alloc::format!("{:?}", Instant::now().duration_since(start)));
        Ok(())
    }

    test(Sample::Format)?;
    test(Sample::ToString)?;
    test(Sample::NumberWriter)?;

    Ok(())
}