An efficient method of heaplessly converting numbers into their string representations, storing the representation within a reusable byte array.

Overview

NumToA

#![no_std] Compatible with Zero Heap Allocations

The standard library provides a convenient method of converting numbers into strings, but these strings are heap-allocated. If you have an application which needs to convert large volumes of numbers into strings, but don't want to pay the price of heap allocation, this crate provides an efficient no_std-compatible method of heaplessly converting numbers into their string representations, storing the representation within a reusable byte array.

Supports Multiple Bases

In addition to supporting the standard base 10 conversion, this implementation allows you to select the base of your choice. Therefore, if you want a binary representation, set the base to 2. If you want hexadecimal, set the base to 16.

&str Example

use numtoa::NumToA;

let mut buffer = [0u8; 20];
println!("{}", 12345.numtoa_str(10, &mut buffer));
println!("{}", 256652.numtoa_str(10, &mut buffer));

&[u8] Example

use numtoa::NumToA;
use std::io::{self, Write};

let stdout = io::stdout();
let mut stdout = stdout.lock();
let mut buffer = [0u8; 20];

let number: u32 = 162392;
let _ = stdout.write(number.numtoa(10, &mut buffer));
let _ = stdout.write(b"\n");
assert_eq!(number.numtoa(10, &mut buffer), b"162392");

let number: i32 = -6235;
let _ = stdout.write(number.numtoa(10, &mut buffer));
let _ = stdout.write(b"\n");

let number: i8 = -128;
let _ = stdout.write(number.numtoa(10, &mut buffer));
let _ = stdout.write(b"\n");

let number: i8 = 53;
let _ = stdout.write(number.numtoa(10, &mut buffer));
let _ = stdout.write(b"\n");

let number: i16 = -256;
let _ = stdout.write(number.numtoa(10, &mut buffer));
let _ = stdout.write(b"\n");

let number: i16 = -32768;
let _ = stdout.write(number.numtoa(10, &mut buffer));
let _ = stdout.write(b"\n");

let number: u64 = 35320842;
let _ = stdout.write(number.numtoa(10, &mut buffer));
let _ = stdout.write(b"\n");

let number: u64 = 18446744073709551615;
let _ = stdout.write(number.numtoa(10, &mut buffer));
let _ = stdout.write(b"\n");
Comments
  • too_small tests are failing

    too_small tests are failing

    running 16 tests
    test base10_i16_array_just_right ... ok
    test base10_i32_array_just_right ... ok
    test base10_i16_array_too_small ... FAILED
    test base10_i32_array_too_small ... FAILED
    test base10_i8_array_just_right ... ok
    test base10_i64_array_just_right ... ok
    test base10_i64_array_too_small ... FAILED
    test base10_i8_array_too_small ... FAILED
    test base10_u16_array_just_right ... ok
    test base10_u16_array_too_small ... FAILED
    test base10_u32_array_just_right ... ok
    test base10_u32_array_too_small ... FAILED
    test base10_u64_array_just_right ... ok
    test base10_u64_array_too_small ... FAILED
    test base10_u8_array_just_right ... ok
    test base10_u8_array_too_small ... FAILED
    
    failures:
    
    failures:
        base10_i16_array_too_small
        base10_i32_array_too_small
        base10_i64_array_too_small
        base10_i8_array_too_small
        base10_u16_array_too_small
        base10_u32_array_too_small
        base10_u64_array_too_small
        base10_u8_array_too_small
    

    I'm packaging numtoa for Fedora and those tests are failing, not sure what information to attach honetsly.

    opened by ignatenkobrain 9
  • Share benchmark code

    Share benchmark code

    I see benchmark numbers in the readme but the code isn't in the repo. Could you share the code so I can reproduce those on my machine? Really what I am wondering is how the comparison changes if I do have an io::Write that I need to write to, as is the case in serde_json. With numtoa I would have to copy the bytes from my buffer over to the io::Write which I imagine would cut into the 8% advantage.

    opened by dtolnay 3
  • i8 bug

    i8 bug

    If we double anything greater than +63 for i8 we get an overflow I'm afraid so there's a slight chink in the armour between 64-99 for i8.

    https://github.com/mmstick/numtoa/blob/429fa9cd603f02c08cc712787ba13b330a320bfc/src/lib.rs#L310

    (Sorry my usage of the crate tests it pretty well as I'm using it to drive my own test harness!)

    opened by gilescope 2
  • Tests fail: error[E0599]: no method named `numtoa_str` found for type `{integer}`

    Tests fail: error[E0599]: no method named `numtoa_str` found for type `{integer}`

    + /usr/bin/cargo test -j6 --release --no-fail-fast
       Compiling numtoa v0.1.0 (file:///builddir/build/BUILD/numtoa-0.1.0)
         Running `/usr/bin/rustc --crate-name numtoa src/lib.rs --emit=dep-info,link -C opt-level=3 --test -C metadata=a8991c65fdb394d2 -C extra-filename=-a8991c65fdb394d2 --out-dir /builddir/build/BUILD/numtoa-0.1.0/target/release/deps -L dependency=/builddir/build/BUILD/numtoa-0.1.0/target/release/deps -Copt-level=3 -Cdebuginfo=2 -Clink-arg=-Wl,-z,relro,-z,now`
    error[E0599]: no method named `numtoa_str` found for type `{integer}` in the current scope
       --> src/lib.rs:401:33
        |
    401 |     assert_eq!("256123", 256123.numtoa_str(10, &mut buffer));
        |                                 ^^^^^^^^^^
    error: aborting due to previous error
    For more information about this error, try `rustc --explain E0599`.
    error: Could not compile `numtoa`.
    

    Built on Fedora Rawhide with Rust 1.29.1

    Also it seems the source code on this repo is outdated and the Gitlab repo is not accessible.

    opened by eclipseo 2
  • Code duplication

    Code duplication

    Here: https://github.com/mmstick/numtoa/blob/master/src/lib.rs#L241

    Wouldn't it be better to write an universal implementation and just call it from generic impls?

    opened by pravic 1
  • Generic issue?

    Generic issue?

    Hello,

    I am trying to write a function that calls numtoa shown below:

    fn render_num<T: NumToA>(num: T, buffer: &'a mut [u8; 20]) -> Font6x8<'a> {
            let n = num.numtoa(10, buffer);
    
            let text = from_utf8(&buffer[..n]).unwrap();
    
            Self { pos: (0, 0), text }
    }
    

    but I get the error wrong number of type arguments: expected 1, found 0, highlighting T: NumToA. How do I correctly implement this function?

    Thanks :)

    opened by fmckeogh 1
  • Fix conversion of smallest signed integers with non-decimal bases

    Fix conversion of smallest signed integers with non-decimal bases

    This code assumes base 10 in case of smallest signed numbers like -128 and -32768, leading to incorrect results if base is not 10. Sample test:

    let mut buffer = [0u8; 4];
    let i = (-128i8).numtoa(8, &mut buffer);
    assert_eq!(&buffer[i..], b"-200"); // Fails as the buffer is equal to b"-148"
    
    opened by crazymerlyn 1
  • Formatting negative numbers requires reserving one extra byte of space

    Formatting negative numbers requires reserving one extra byte of space

    For instance the i16 number -32768 fits in a 6 byte buffer but trying to format that number in a 6 byte buffer using numtoa results in a panic:

    extern crate numtoa;
    
    use std::str;
    
    use numtoa::NumToA;
    
    fn main() {
        let mut buffer: [u8; 6] = *b"-32768";
    
        let start = (-32768_i16).numtoa(10, &mut buffer);
    
        println!("{}", str::from_utf8(&buffer[start..]).unwrap());
    }
    
    $ cargo run
    thread 'main' panicked at 'attempt to subtract with overflow', /home/japaric/.cargo/registry/src/github.com-1ecc6299db9ec823/numtoa-0.0.7/src/lib.rs:231
    note: Run with `RUST_BACKTRACE=1` for a backtrace.
    

    But if you use a 7 byte buffer the operation succeeds. You don't see this behavior when formating positive integers: for example, formatting 65535_u16 works fine with a 5 byte buffer.

    opened by japaric 1
  • Wrong number written

    Wrong number written

    extern crate numtoa;
    use numtoa::NumToA;
    
    fn main() {
        let mut buf = vec![0; 20];
        let start = (256i16).numtoa(10, &mut buf);
        let s = ::std::str::from_utf8(&buf[start..]).unwrap();
        assert_eq!("256", s); // :(
    }
    
    opened by dtolnay 1
  • Added u128 & i128 support and corrected i64 length

    Added u128 & i128 support and corrected i64 length

    Fixes: #17 For i64 the way the numbers fall it actually requires one less byte than u64. This is certainly true for base 10. Does this hold for other bases?

    opened by gilescope 0
  • Buffer size check is too aggressive

    Buffer size check is too aggressive

    If I know for sure that I have numbers in the range 0 .. 100_000_000, I want to be able to use an 8-byte buffer rather than needing 20 bytes in debug mode. Maybe an unsafe way to skip the check? This is why https://github.com/mmstick/numtoa/issues/5#issuecomment-274347968 panics in debug mode even though the code is correct.

    opened by dtolnay 6
  • itoa used correctly is faster than numtoa used correctly

    itoa used correctly is faster than numtoa used correctly

    https://github.com/mmstick/numtoa/issues/4#issuecomment-274293855

    Based on the benchmark code in #4 but writing to Vec<u8>, itoa is about 10% faster.

    let mut null = Vec::new();
    
    for number in 0..100_000_000u64 {
        null.clear();
        /* write */
    }
    
    numtoa: 995 ms
    itoa: 866 ms
    std: 2803 ms
    

    This is an important use case because it is a good model of what serde_json::to_string is doing, for example.

    opened by dtolnay 11
Owner
Michael Murphy
System76 engineer; Linux developer; Rust programmer
Michael Murphy
Simple and efficient time representation in Rust.

timens-rs Simple and efficient timestamp representation. The main objective being interoperability with OCaml Core_kernel.Time_ns. A significant part

Laurent Mazare 7 Oct 17, 2022
An annotated string type in Rust, made up of string slices

A string type made up of multiple annotated string slices.

Togglebit 3 Dec 29, 2022
A memory efficient immutable string type that can store up to 24* bytes on the stack

compact_str A memory efficient immutable string type that can store up to 24* bytes on the stack. * 12 bytes for 32-bit architectures About A CompactS

Parker Timmerman 342 Jan 2, 2023
A flexible, simple to use, immutable, clone-efficient String replacement for Rust

A flexible, simple to use, immutable, clone-efficient String replacement for Rust. It unifies literals, inlined, and heap allocated strings into a single type.

Scott Meeuwsen 119 Dec 12, 2022
This plugin provides an interface for storing unencrypted values on the application cache folder.

Tauri Plugin Store This plugin provides an interface for storing unencrypted values on the application cache folder. Architecture This repo shape migh

Tauri 128 Jan 1, 2023
This crate implements an array_chunks method for iterators

This crate implements an array_chunks method for iterators. It behaves like [slice::array_chunks] but works with any [Iterator] type. Several nightly

kangalioo 1 Jan 24, 2022
Drop ownership from "method position"

disown Drop ownership from "method position". Motivation Normally, unowned data is automatically dropped at the end of its residing block. We can also

Colin Woodbury 2 Mar 9, 2022
Byte is a blazingly fast🚀 Discord Bot with a user-friendly design using twilight written in rust🦀.

Byte Byte is a blazingly fast?? Discord Bot with a user-friendly design using twilight written in rust??. How To Run There is a public version of the

TakoTheDev 3 Nov 15, 2023
Rust crate which provides direct access to files within a Debian archive

debarchive This Rust crate provides direct access to files within a Debian archive. This crate is used by our debrep utility to generate the Packages

Pop!_OS 11 Dec 18, 2021
A Foundry plugin that enables you to plot charts within solidity.

??️ solplot A Foundry plugin that enables you to plot charts within solidity. Installation First, make sure that you have Rust installed. Then install

boredretard.eth 132 Dec 27, 2022
A Rust framework to develop and use plugins within your project, without worrying about the low-level details.

VPlugin: A plugin framework for Rust. Website | Issues | Documentation VPlugin is a Rust framework to develop and use plugins on applications and libr

VPlugin 11 Dec 31, 2022
The system for remote workers to prevent their family members from interrupting conference calls

onair The system for remote workers to prevent their family members from interrupting conference calls. The system is designed to automatically detect

Yushi OMOTE 6 Sep 21, 2022
Ecstasy - a subjective experience of total involvement of the subject, with an object of their awareness.

Ecstasy (from Ancient Greek ἔκστασις ékstasis, meaning 'outside of oneself') is a subjective experience of total involvement of the subject, with an object of their awareness. In classical Greek literature it refers to removal of the mind or body "from its normal place of function."

null 2 Jun 11, 2022
A tool for investigating file system and folder contents and their changes.

Sniff A tool for investigating file systems and folder contents and their changes. Sniff can create snapshots of file systems and folders, storing has

Niclas Schwarzlose 6 Jan 14, 2023
Rust wrapper for the Google Places API. Access their hundreds of millions of places, reviews, and ratings.

Google Places API Working Examples cargo run --example nearby_search cargo run --example place_details cargo run --example find_place cargo run --exam

Jared Ucherek 4 Jun 12, 2023
microtemplate - A fast, microscopic helper crate for runtime string interpolation.

microtemplate A fast, microscopic helper crate for runtime string interpolation. Design Goals Very lightweight: I want microtemplate to do exactly one

_iPhoenix_ 13 Jan 31, 2022
SubStrings, Slices and Random String Access in Rust

SubStrings, Slices and Random String Access in Rust This is a simple way to do it. Description Rust string processing is kind of hard, because text in

João Nuno Carvalho 2 Oct 24, 2021
A simple string interner / symbol table for Rust projects.

Symbol Interner A small Rust crate that provides a naïve string interner. Consult the documentation to learn about the types that are exposed. Install

Ryan Chandler 1 Nov 18, 2021
A string truncator and scroller written in Rust

scissrs A string truncator and scroller written in Rust. Usage scissrs --help covers the definitions of this program's flags.

Skybbles 5 Aug 3, 2022