Stdx
The missing batteries of Rust
Install / Use
/learn @brson/StdxREADME
This project is unmaintained. For a similar project see rustmax.
<a id="list"></a>
stdx - The missing batteries of Rust
New to Rust and don't yet know what crates to use? stdx has the best crates.
Current revision: stdx 0.119.0-rc, for Rust 1.19, July 20, 2017.
| Feature | Crate | |
|--------------------------------|----------------------------|--------------------|
| Bitfields | [bitflags = "0.9.1"] | [📖][d-bitflags] |
| Byte order conversion | [byteorder = "1.1.0"] | [📖][d-byteorder] |
| Date and time | [chrono = "0.4.0"] | [📖][d-chrono] |
| Command-line argument parsing | [clap = "2.25.0"] | [📖][d-clap] |
| Encoding/decoding | [encoding_rs = "0.6.11"] | [📖][d-encoding_rs] |
| Error handling | [error-chain = "0.10.0"] | [📖][d-error-chain] |
| Fast hashing | [fnv = "1.0.5"] | [📖][d-fnv] |
| Compression - deflate (gzip) | [flate2 = "0.2.19"] | [📖][d-flate2] |
| Iterator functions, macros | [itertools = "0.6.0"] | [📖][d-itertools] |
| Global initialization | [lazy_static = "0.2.8"] | [📖][d-lazy_static] |
| C interop | [libc = "0.2.25"] | [📖][d-libc] |
| Logging | [log = "0.3.8"] | [📖][d-log] |
| Memory-mapped file I/O | [memmap = "0.5.2"] | [📖][d-memmap] |
| Multidimensional arrays | [ndarray = "0.9.1"] | [📖][d-ndarray] |
| Big, rational, complex numbers | [num = "0.1.40"] | [📖][d-num] |
| Number of CPUs | [num_cpus = "1.6.2"] | [📖][d-num_cpus] |
| Random numbers | [rand = "0.3.15"] | [📖][d-rand] |
| Parallel iteration | [rayon = "0.8.2"] | [📖][d-rayon] |
| Regular expressions | [regex = "0.2.2"] | [📖][d-regex] |
| HTTP client | [reqwest = "0.7.1"] | [📖][d-reqwest] |
| Software versioning | [semver = "0.7.0"] | [📖][d-semver] |
| Serialization | [serde = "1.0.10"] | [📖][d-serde] |
| JSON | [serde_json = "1.0.2"] | [📖][d-serde_json] |
| Tar archives | [tar = "0.4.23"] | [📖][d-tar] |
| Temporary directories | [tempdir = "0.3.5"] | [📖][d-tempdir] |
| Thread pool | [threadpool = "1.4.0"] | [📖][d-threadpool] |
| Configuration files | [toml = "0.4.2"] | [📖][d-toml] |
| URLs | [url = "1.5.1"] | [📖][d-url] |
| Directory traversal | [walkdir = "1.0.7"] | [📖][d-walkdir] |
<a id="bitflags"></a>
bitflags = "0.9.1" [📖][d-bitflags]
The only thing this crate does is export the [bitflags!] macro, but
it's a heckuva-useful macro. bitflags! produces typesafe bitmasks,
types with named values that are efficiently packed together as bits
to express sets of options.
Example: [examples/bitflags.rs]
#[macro_use]
extern crate bitflags;
bitflags! {
struct Flags: u32 {
const FLAG_A = 0b00000001;
const FLAG_B = 0b00000010;
const FLAG_C = 0b00000100;
const FLAG_ABC = FLAG_A.bits
| FLAG_B.bits
| FLAG_C.bits;
}
}
fn main() {
let e1 = FLAG_A | FLAG_C;
let e2 = FLAG_B | FLAG_C;
assert_eq!((e1 | e2), FLAG_ABC); // union
assert_eq!((e1 & e2), FLAG_C); // intersection
assert_eq!((e1 - e2), FLAG_A); // set difference
assert_eq!(!e2, FLAG_A); // set complement
}
<a id="byteorder"></a>
byteorder = "1.1.0" [📖][d-byteorder]
When serializing integers it's important to consider that not all computers store in memory the individual bytes of the number in the same order. The choice of byte order is called ["endianness"], and this simple crate provides the crucial functions for converting between numbers and bytes, in little-endian, or big-endian orders.
Example: [examples/byteorder.rs]
extern crate byteorder;
use std::io::Cursor;
use byteorder::{BigEndian, ReadBytesExt};
use byteorder::{LittleEndian, WriteBytesExt};
fn main() {
// Read unsigned 16 bit big-endian integers from a Read type:
let mut rdr = Cursor::new(vec![2, 5, 3, 0]);
// Note that we use type parameters to indicate which kind of byte
// order we want!
assert_eq!(517, rdr.read_u16::<BigEndian>().unwrap());
assert_eq!(768, rdr.read_u16::<BigEndian>().unwrap());
// Write unsigned 16 bit little-endian integers to a Write type:
let mut wtr = vec![];
wtr.write_u16::<LittleEndian>(517).unwrap();
wtr.write_u16::<LittleEndian>(768).unwrap();
assert_eq!(wtr, vec![5, 2, 0, 3]);
}
<a id="chrono"></a>
chrono = "0.4.0" [📖][d-chrono]
Date and time types.
Example: [examples/chrono.rs]
extern crate chrono;
use chrono::*;
fn main() {
let local: DateTime<Local> = Local::now();
let utc: DateTime<Utc> = Utc::now();
let dt = Utc.ymd(2014, 11, 28).and_hms(12, 0, 9);
assert_eq!((dt.year(), dt.month(), dt.day()), (2014, 11, 28));
assert_eq!((dt.hour(), dt.minute(), dt.second()), (12, 0, 9));
assert_eq!(dt.format("%Y-%m-%d %H:%M:%S").to_string(), "2014-11-28 12:00:09");
assert_eq!(dt.format("%a %b %e %T %Y").to_string(), "Fri Nov 28 12:00:09 2014");
assert_eq!(format!("{}", dt), "2014-11-28 12:00:09 UTC");
}
<a id="clap"></a>
clap = "2.25.0" [📖][d-clap]
Clap is a command line argument parser that is easy to use and is highly configurable.
Example: [examples/clap.rs]
extern crate clap;
use clap::{Arg, App, SubCommand};
fn main() {
let app = App::new("My Super Program")
.version("1.0")
.author("Kevin K. <kbknapp@gmail.com>")
.about("Does awesome things")
.arg(Arg::with_name("config")
.short("c")
.long("config")
.value_name("FILE")
.help("Sets a custom config file")
.takes_value(true))
.arg(Arg::with_name("INPUT")
.help("Sets the input file to use")
.required(true)
.index(1))
.subcommand(SubCommand::with_name("test")
.about("controls testing features")
.arg(Arg::with_name("debug")
.short("d")
.help("print debug information verbosely")));
// Parse the command line arguments
let matches = app.get_matches();
let config = matches.value_of("config").unwrap_or("default.conf");
let input = matches.value_of("INPUT").unwrap();
// Handle subcommands
match matches.subcommand() {
("clone", Some(sub_matches)) => {
if matches.is_present("d") {
// ...
}
},
("push", Some(sub_matches)) => {},
("commit", Some(sub_matches)) => {},
_ => {},
}
}
Alternatives: [docopt]
<a id="encoding_rs"></a>
encoding_rs = "0.6.11" [📖][d-encoding_rs]
encoding_rs is a Gecko-oriented Free Software / Open Source implementation of the Encoding Standard in Rust. Gecko-oriented means that converting to and from UTF-16 is supported in addition to converting to and from UTF-8, that the performance and streamability goals are browser-oriented, and that FFI-friendliness is a goal.
Example: [examples/encoding_rs.rs]
extern crate encoding_rs;
use encoding_rs::*;
fn main() {
let expected = "\u{30CF}\u{30ED}\u{30FC}\u{30FB}\u{30EF}\u{30FC}\u{30EB}\u{30C9}";
let encoded = b"\x83n\x83\x8D\x81[\x81E\x83\x8F\x81[\x83\x8B\x83h";
let (decoded, encoding_used, had_errors) = SHIFT_JIS.decode(encoded);
assert_eq!(&decoded[..], expected);
assert_eq!(encoding_used, SHIFT_JIS);
assert!(!had_errors);
println!("Decoded result: {}", decoded);
}
<a id="error-chain"></a>
error-chain = "0.10.0" [📖][d-error-chain]
Rust programs that handle errors consistently are reliable programs.
Even after one understands [error handling] in Rust, it can be
difficult to grasp and implement its best practices. error-chain
helps you define your own error type that works with the ? operator
to make error handling in Rust simple and elegant.
Example: [examples/error-chain.rs]
// `error_chain!` can recurse deeply
#![recursion_limit = "1024"]
#[macro_use]
extern crate error_chain;
// We'll put our errors in an `errors` module, and other modules in
// this crate will `use errors::*;` to get access to everything
// `error_chain!` creates.
mod errors {
// Create the Error, ErrorKind, ResultExt, and Result types
error_chain! { }
}
use errors::*;
fn main() {
if let Err(ref e) = run() {
use ::std::io::Write;
let stderr = &mut ::std::io::stderr();
let errmsg = "Error writing to stderr";
writeln!(stderr, "error: {}", e).expect(errmsg);
for e in e.iter().skip(1) {
writeln!(stderr, "caused by: {}", e).expect(errmsg);
}
// The backtrace is not always generated. Try to run this example
// with `RUST_BACKTRACE=1`.
if let Some(backtrace) = e.backtrace() {
write
