jsonx 0.1.0

A serde-enabled implementation of the JSONX extended-JSON format: typed value constructors, unquoted keys, and trailing commas.
Documentation
//! Fast decimal formatting of integers.
//!
//! These `itoa`-style helpers write a `u64`/`i64` straight into a stack buffer,
//! avoiding the `core::fmt` machinery of `write!`. They back the JSONX integer
//! constructors (`int8(…)`, `int64(…)`, the bare `int(…)`/`uint(…)` payloads,
//! and integer object keys).
//!
//! Floating-point numbers are *not* handled here: the serializer writes them in
//! their shortest round-trippable form directly via [`ryu`] (see
//! [`crate::ser::Serializer`]'s `serialize_f64`).

/// Largest decimal width of a `u64`/`i64` (`18446744073709551615` and
/// `-9223372036854775808` are both 20 bytes).
pub(crate) const INT_BUF: usize = 20;

/// Writes a `u64`'s decimal digits into `out`, returning the count.
pub(crate) fn fmt_u64(mut v: u64, out: &mut [u8; INT_BUF]) -> usize {
    let mut i = INT_BUF;
    loop {
        i -= 1;
        out[i] = b'0' + (v % 10) as u8;
        v /= 10;
        if v == 0 {
            break;
        }
    }
    let n = INT_BUF - i;
    out.copy_within(i.., 0);
    n
}

/// Writes an `i64`'s decimal form (with a leading `-` when negative) into `out`,
/// returning the count.
pub(crate) fn fmt_i64(v: i64, out: &mut [u8; INT_BUF]) -> usize {
    let mut m = v.unsigned_abs(); // handles i64::MIN without overflow
    let mut i = INT_BUF;
    loop {
        i -= 1;
        out[i] = b'0' + (m % 10) as u8;
        m /= 10;
        if m == 0 {
            break;
        }
    }
    if v < 0 {
        i -= 1;
        out[i] = b'-';
    }
    let n = INT_BUF - i;
    out.copy_within(i.., 0);
    n
}

#[cfg(test)]
mod tests {
    use super::*;

    fn u64s(v: u64) -> String {
        let mut out = [0u8; INT_BUF];
        let n = fmt_u64(v, &mut out);
        String::from_utf8(out[..n].to_vec()).unwrap()
    }
    fn i64s(v: i64) -> String {
        let mut out = [0u8; INT_BUF];
        let n = fmt_i64(v, &mut out);
        String::from_utf8(out[..n].to_vec()).unwrap()
    }

    #[test]
    fn integer_formatting() {
        assert_eq!(u64s(0), "0");
        assert_eq!(u64s(5432), "5432");
        assert_eq!(u64s(u64::MAX), "18446744073709551615");
        assert_eq!(i64s(0), "0");
        assert_eq!(i64s(-1), "-1");
        assert_eq!(i64s(i64::MAX), "9223372036854775807");
        assert_eq!(i64s(i64::MIN), "-9223372036854775808");
    }
}