A Rust crate for producing string representations of numbers, formatted according to international standards, e.g.
"1,000,000"
for US English"10,00,000"
for Indian English"1 000 000"
for French Frenchnum-format offers three principal APIs...
ToFormattedString
The [ToFormattedString
] trait is the simplist of the three APIs. Just call
[to_formatted_string
] on a type that implements it (all the integer types in the standard library
implement it) while providing a desired format (see [picking a format] below). That said, using
[ToFormattedString
] will always heap allocate; so it is the slowest of the three APIs and cannot
be used in a no_std
environment.
```rust use num_format::{Locale, ToFormattedString};
fn main() { let s = 1000000.toformattedstring(&Locale::en); assert_eq!(&s, "1,000,000"); } ```
Buffer
Using the [Buffer
] type is the fastest API, as it does not heap allocate. Instead, the
formatted representation is written into a stack-allocated buffer. As such, you can use it in a
no_std
environment.
Although this API is available for all the integer types in the standard library, it is not
available for types like [num_bigint::BigInt
] whose maximum size cannot be known in advance.
```rust use num_format::{Buffer, Locale};
fn main() { // Create a stack-allocated buffer... let mut buf = Buffer::default();
// Write "1,000,000" into the buffer...
buf.write_formatted(&1000000, &Locale::en);
// Get a view into the buffer as a &str...
let s = buf.as_str();
// Do what you want with the &str...
assert_eq!("1,000,000", s);
} ```
WriteFormatted
The [WriteFormatted
] trait is in between the other two APIs. You can write a formatted
representation into any type that implements [WriteFormatted
] (all the types in the standard
library that implement [io::Write
] or [fmt::Write
] implement [WriteFormatted
], such as
[Vec
], [String
], [File
], etc.).
If you're writing a number type that can use the [Buffer
] API, there is no heap allocation.
That said, the [io::Write
] and [fmt::Write
] machinery adds a bit of overhead; so it's faster
to use the [Buffer
] type directly.
You can also use this API with types where the [Buffer
] API will not work, like
[num_bigint::BigInt
], in which case there will be heap allocation. As such, this trait is
not available in a no_std
environment.
```rust use num_format::{Locale, WriteFormatted};
fn main() { // Create a writer... let mut writer = String::new(); // Could also be Vec::new(), File::open(...), ...
// Write "1,000,000" into the writer...
writer.write_formatted(&1000000, &Locale::en);
assert_eq!(&writer, "1,000,000");
} ```
Formatting options (e.g. which thousands separator to use, what the minus sign looks like, etc.)
are represented by the [Format
] trait. This crate offers three concrete implementations of
the [Format
] trait...
Locale
The [Locale
] type is a programatically generated enum representing formatting standards from the
[Common Locale Data Repository], which is maintained by the [Unicode Consortium] and used by
Apple in macOS and iOS, by LibreOffice, by IBM in AIX, among others.
```rust use num_format::{Grouping, Locale};
fn main() { let locale = Locale::en; asserteq!(locale.grouping(), Grouping::Standard); asserteq!(locale.minussign(), "-"); asserteq!(locale.name(), "en"); assert_eq!(locale.separator(), ",");
let locale2 = Locale::from_name("en").unwrap();
assert_eq!(locale, locale2);
let available = Locale::available_names();
println!("All of the locale names available in the Unicode database are...");
println!("{:#?}", available);
} ```
SystemLocale
The [SystemLocale
] type is another type that implements [Format
]. It allows you to access your
OS's locale information. It has a very similar API to [Locale
] and should work on all major
operating systems (i.e. macOS, linux, the BSDs, and Windows).
locale
], [newlocale
],
[uselocale
] and other POSIX functions from the C standard library.GetLocaleInfoEx
] and [EnumSystemLocalesEx
] functions from the Windows API
are used.```rust use num_format::SystemLocale;
fn main() { let locale = SystemLocale::default().unwrap(); println!("My system's default locale is..."); println!("{:#?}", &locale);
let available = SystemLocale::available_names().unwrap();
println!("My available locale names are...");
println!("{:#?}", available);
match SystemLocale::from_name("en_US") {
Ok(_) => println!("My system has the 'en_US' locale."),
Err(_) => println!("The 'en_US' locale is not included with my system."),
}
} ```
CustomFormat
[CustomFormat
] is the third and final type that implements [Format
]. You can use it to build
your own custom formats.
```rust use num_format::{Buffer, Error, CustomFormat, Grouping};
fn main() -> Result<(), Error> { let format = CustomFormat::builder() .grouping(Grouping::Indian) .minus_sign("🙌") .separator("😀") .build()?;
let mut buf = Buffer::new();
buf.write_formatted(&(-1000000), &format);
assert_eq!("🙌10😀00😀000", buf.as_str());
Ok(())
} ```
| Available features | What to put in your Cargo.toml
|
| :----------------- | :------------------------------------------------------------ |
| no_std
| num-format = { version = "0.3", default-features = false }
|
| num-bigint
| num-format = { version = "0.3", features = ["num-bigint"] }
|
| serde
| num-format = { version = "0.3", features = ["with-serde"] }
|
num-format is licensed under either of:
at your option.