{"id":13478474,"url":"https://github.com/brson/stdx","last_synced_at":"2025-05-14T08:05:38.386Z","repository":{"id":34597283,"uuid":"38544981","full_name":"brson/stdx","owner":"brson","description":"The missing batteries of Rust","archived":false,"fork":false,"pushed_at":"2025-02-10T06:48:56.000Z","size":159,"stargazers_count":2047,"open_issues_count":16,"forks_count":47,"subscribers_count":42,"default_branch":"master","last_synced_at":"2025-04-13T13:12:36.253Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/brson.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2015-07-04T19:19:22.000Z","updated_at":"2025-04-11T16:33:08.000Z","dependencies_parsed_at":"2025-03-01T20:00:28.510Z","dependency_job_id":"4f2b0068-51ef-4509-8e35-9a166525583c","html_url":"https://github.com/brson/stdx","commit_stats":null,"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/brson%2Fstdx","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/brson%2Fstdx/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/brson%2Fstdx/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/brson%2Fstdx/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/brson","download_url":"https://codeload.github.com/brson/stdx/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254101589,"owners_count":22014908,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-07-31T16:01:57.593Z","updated_at":"2025-05-14T08:05:33.377Z","avatar_url":"https://github.com/brson.png","language":"Rust","readme":"**This project is unmaintained. For a similar project see [rustmax](https://github.com/brson/rustmax).**\n\n\u003ca id=\"list\"\u003e\u003c/a\u003e\n# `stdx` - The missing batteries of Rust\n\nNew to Rust and don't yet know what crates to use?\n[**stdx has the best crates**](#about-stdx).\n\nCurrent revision: `stdx` 0.119.0-rc, for Rust 1.19, July 20, 2017.\n\n| Feature                        | Crate                      |                    |\n|--------------------------------|----------------------------|--------------------|\n| Bitfields                      | [`bitflags = \"0.9.1\"`]     | [📖][d-bitflags]    |\n| Byte order conversion          | [`byteorder = \"1.1.0\"`]    | [📖][d-byteorder]   |\n| Date and time                  | [`chrono = \"0.4.0\"`]       | [📖][d-chrono]      |\n| Command-line argument parsing  | [`clap = \"2.25.0\"`]        | [📖][d-clap]        |\n| Encoding/decoding              | [`encoding_rs = \"0.6.11\"`] | [📖][d-encoding_rs] |\n| Error handling                 | [`error-chain = \"0.10.0\"`] | [📖][d-error-chain] |\n| Fast hashing                   | [`fnv = \"1.0.5\"`]          | [📖][d-fnv]         |\n| Compression - deflate (gzip)   | [`flate2 = \"0.2.19\"`]      | [📖][d-flate2]      |\n| Iterator functions, macros     | [`itertools = \"0.6.0\"`]    | [📖][d-itertools]   |\n| Global initialization          | [`lazy_static = \"0.2.8\"`]  | [📖][d-lazy_static] |\n| C interop                      | [`libc = \"0.2.25\"`]        | [📖][d-libc]        |\n| Logging                        | [`log = \"0.3.8\"`]          | [📖][d-log]         |\n| Memory-mapped file I/O         | [`memmap = \"0.5.2\"`]       | [📖][d-memmap]      |\n| Multidimensional arrays        | [`ndarray = \"0.9.1\"`]      | [📖][d-ndarray]     |\n| Big, rational, complex numbers | [`num = \"0.1.40\"`]         | [📖][d-num]         |\n| Number of CPUs                 | [`num_cpus = \"1.6.2\"`]     | [📖][d-num_cpus]    |\n| Random numbers                 | [`rand = \"0.3.15\"`]        | [📖][d-rand]        |\n| Parallel iteration             | [`rayon = \"0.8.2\"`]        | [📖][d-rayon]       |\n| Regular expressions            | [`regex = \"0.2.2\"`]        | [📖][d-regex]       |\n| HTTP client                    | [`reqwest = \"0.7.1\"`]      | [📖][d-reqwest]     |\n| Software versioning            | [`semver = \"0.7.0\"`]       | [📖][d-semver]      |\n| Serialization                  | [`serde = \"1.0.10\"`]       | [📖][d-serde]       |\n| JSON                           | [`serde_json = \"1.0.2\"`]   | [📖][d-serde_json]  |\n| Tar archives                   | [`tar = \"0.4.23\"`]         | [📖][d-tar]         |\n| Temporary directories          | [`tempdir = \"0.3.5\"`]      | [📖][d-tempdir]     |\n| Thread pool                    | [`threadpool = \"1.4.0\"`]   | [📖][d-threadpool]  |\n| Configuration files            | [`toml = \"0.4.2\"`]         | [📖][d-toml]        |\n| URLs                           | [`url = \"1.5.1\"`]          | [📖][d-url]         |\n| Directory traversal            | [`walkdir = \"1.0.7\"`]      | [📖][d-walkdir]     |\n\n\u0026nbsp;\u0026NewLine;\u0026nbsp;\u0026NewLine;\u0026nbsp;\u0026NewLine;\n\n\n\u003ca id=\"bitflags\"\u003e\u003c/a\u003e\n### `bitflags = \"0.9.1\"` \u0026emsp; [📖][d-bitflags]\n\nThe only thing this crate does is export the [`bitflags!`] macro, but\nit's a heckuva-useful macro. `bitflags!` produces typesafe bitmasks,\ntypes with named values that are efficiently packed together as bits\nto express sets of options.\n\n**Example**: [`examples/bitflags.rs`]\n\n```rust\n#[macro_use]\nextern crate bitflags;\n\nbitflags! {\n    struct Flags: u32 {\n        const FLAG_A       = 0b00000001;\n        const FLAG_B       = 0b00000010;\n        const FLAG_C       = 0b00000100;\n        const FLAG_ABC     = FLAG_A.bits\n                           | FLAG_B.bits\n                           | FLAG_C.bits;\n    }\n}\n\nfn main() {\n    let e1 = FLAG_A | FLAG_C;\n    let e2 = FLAG_B | FLAG_C;\n    assert_eq!((e1 | e2), FLAG_ABC);   // union\n    assert_eq!((e1 \u0026 e2), FLAG_C);     // intersection\n    assert_eq!((e1 - e2), FLAG_A);     // set difference\n    assert_eq!(!e2, FLAG_A);           // set complement\n}\n```\n\n\u0026nbsp;\u0026NewLine;\u0026nbsp;\u0026NewLine;\u0026nbsp;\u0026NewLine;\n\n\n\u003ca id=\"byteorder\"\u003e\u003c/a\u003e\n### `byteorder = \"1.1.0\"` \u0026emsp; [📖][d-byteorder]\n\nWhen serializing integers it's important to consider that not all\ncomputers store in memory the individual bytes of the number in the\nsame order. The choice of byte order is called [\"endianness\"], and\nthis simple crate provides the crucial functions for converting\nbetween numbers and bytes, in little-endian, or big-endian orders.\n\n**Example**: [`examples/byteorder.rs`]\n\n```rust\nextern crate byteorder;\n\nuse std::io::Cursor;\nuse byteorder::{BigEndian, ReadBytesExt};\nuse byteorder::{LittleEndian, WriteBytesExt};\n\nfn main() {\n    // Read unsigned 16 bit big-endian integers from a Read type:\n    let mut rdr = Cursor::new(vec![2, 5, 3, 0]);\n    // Note that we use type parameters to indicate which kind of byte\n    // order we want!\n    assert_eq!(517, rdr.read_u16::\u003cBigEndian\u003e().unwrap());\n    assert_eq!(768, rdr.read_u16::\u003cBigEndian\u003e().unwrap());\n\n    // Write unsigned 16 bit little-endian integers to a Write type:\n    let mut wtr = vec![];\n    wtr.write_u16::\u003cLittleEndian\u003e(517).unwrap();\n    wtr.write_u16::\u003cLittleEndian\u003e(768).unwrap();\n    assert_eq!(wtr, vec![5, 2, 0, 3]);\n}\n```\n\n\u0026nbsp;\u0026NewLine;\u0026nbsp;\u0026NewLine;\u0026nbsp;\u0026NewLine;\n\n\n\u003ca id=\"chrono\"\u003e\u003c/a\u003e\n### `chrono = \"0.4.0\"` \u0026emsp; [📖][d-chrono]\n\nDate and time types.\n\n**Example**: [`examples/chrono.rs`]\n\n```rust\nextern crate chrono;\nuse chrono::*;\n\nfn main() {\n    let local: DateTime\u003cLocal\u003e = Local::now();\n    let utc: DateTime\u003cUtc\u003e = Utc::now();\n\n    let dt = Utc.ymd(2014, 11, 28).and_hms(12, 0, 9);\n\n    assert_eq!((dt.year(), dt.month(), dt.day()), (2014, 11, 28));\n    assert_eq!((dt.hour(), dt.minute(), dt.second()), (12, 0, 9));\n\n    assert_eq!(dt.format(\"%Y-%m-%d %H:%M:%S\").to_string(), \"2014-11-28 12:00:09\");\n    assert_eq!(dt.format(\"%a %b %e %T %Y\").to_string(), \"Fri Nov 28 12:00:09 2014\");\n\n    assert_eq!(format!(\"{}\", dt), \"2014-11-28 12:00:09 UTC\");\n}\n```\n\n\u0026nbsp;\u0026NewLine;\u0026nbsp;\u0026NewLine;\u0026nbsp;\u0026NewLine;\n\n\n\u003ca id=\"clap\"\u003e\u003c/a\u003e\n### `clap = \"2.25.0\"` \u0026emsp; [📖][d-clap]\n\nClap is a command line argument parser that is easy to\nuse and is highly configurable.\n\n**Example**: [`examples/clap.rs`]\n\n```rust,no_run\nextern crate clap;\nuse clap::{Arg, App, SubCommand};\n\nfn main() {\n    let app = App::new(\"My Super Program\")\n        .version(\"1.0\")\n        .author(\"Kevin K. \u003ckbknapp@gmail.com\u003e\")\n        .about(\"Does awesome things\")\n        .arg(Arg::with_name(\"config\")\n             .short(\"c\")\n             .long(\"config\")\n             .value_name(\"FILE\")\n             .help(\"Sets a custom config file\")\n             .takes_value(true))\n        .arg(Arg::with_name(\"INPUT\")\n             .help(\"Sets the input file to use\")\n             .required(true)\n             .index(1))\n        .subcommand(SubCommand::with_name(\"test\")\n                    .about(\"controls testing features\")\n                    .arg(Arg::with_name(\"debug\")\n                         .short(\"d\")\n                         .help(\"print debug information verbosely\")));\n\n    // Parse the command line arguments\n    let matches = app.get_matches();\n\n    let config = matches.value_of(\"config\").unwrap_or(\"default.conf\");\n    let input = matches.value_of(\"INPUT\").unwrap();\n\n    // Handle subcommands\n    match matches.subcommand() {\n        (\"clone\",  Some(sub_matches)) =\u003e {\n            if matches.is_present(\"d\") {\n                // ...\n            }\n        },\n        (\"push\",   Some(sub_matches)) =\u003e {},\n        (\"commit\", Some(sub_matches)) =\u003e {},\n        _ =\u003e {},\n    }\n}\n```\n\n**Alternatives**: [`docopt`]\n\n\u0026nbsp;\u0026NewLine;\u0026nbsp;\u0026NewLine;\u0026nbsp;\u0026NewLine;\n\n\n\u003ca id=\"encoding_rs\"\u003e\u003c/a\u003e\n ### `encoding_rs = \"0.6.11\"` \u0026emsp; [📖][d-encoding_rs]\n\nencoding_rs is a Gecko-oriented Free Software / Open Source\nimplementation of the Encoding Standard in Rust. Gecko-oriented means\nthat converting to and from UTF-16 is supported in addition to\nconverting to and from UTF-8, that the performance and streamability\ngoals are browser-oriented, and that FFI-friendliness is a goal.\n\n **Example**: [`examples/encoding_rs.rs`]\n\n ```rust\n extern crate encoding_rs;\n use encoding_rs::*;\n\n fn main() {\n     let expected = \"\\u{30CF}\\u{30ED}\\u{30FC}\\u{30FB}\\u{30EF}\\u{30FC}\\u{30EB}\\u{30C9}\";\n     let encoded = b\"\\x83n\\x83\\x8D\\x81[\\x81E\\x83\\x8F\\x81[\\x83\\x8B\\x83h\";\n\n     let (decoded, encoding_used, had_errors) = SHIFT_JIS.decode(encoded);\n\n     assert_eq!(\u0026decoded[..], expected);\n     assert_eq!(encoding_used, SHIFT_JIS);\n     assert!(!had_errors);\n\n     println!(\"Decoded result: {}\", decoded);\n }\n ```\n\n \u0026nbsp;\u0026NewLine;\u0026nbsp;\u0026NewLine;\u0026nbsp;\u0026NewLine;\n\n\n\u003ca id=\"error-chain\"\u003e\u003c/a\u003e\n### `error-chain = \"0.10.0\"` \u0026emsp; [📖][d-error-chain]\n\nRust programs that handle errors consistently are reliable programs.\nEven after one understands [error handling] in Rust, it can be\ndifficult to grasp and implement its best practices. `error-chain`\nhelps you define your own error type that works with the `?` operator\nto make error handling in Rust simple and elegant.\n\n**Example**: [`examples/error-chain.rs`]\n\n```rust,no_run,ignore\n// `error_chain!` can recurse deeply\n#![recursion_limit = \"1024\"]\n\n#[macro_use]\nextern crate error_chain;\n\n// We'll put our errors in an `errors` module, and other modules in\n// this crate will `use errors::*;` to get access to everything\n// `error_chain!` creates.\nmod errors {\n    // Create the Error, ErrorKind, ResultExt, and Result types\n    error_chain! { }\n}\n\nuse errors::*;\n\nfn main() {\n    if let Err(ref e) = run() {\n        use ::std::io::Write;\n        let stderr = \u0026mut ::std::io::stderr();\n        let errmsg = \"Error writing to stderr\";\n\n        writeln!(stderr, \"error: {}\", e).expect(errmsg);\n\n        for e in e.iter().skip(1) {\n            writeln!(stderr, \"caused by: {}\", e).expect(errmsg);\n        }\n\n        // The backtrace is not always generated. Try to run this example\n        // with `RUST_BACKTRACE=1`.\n        if let Some(backtrace) = e.backtrace() {\n            writeln!(stderr, \"backtrace: {:?}\", backtrace).expect(errmsg);\n        }\n\n        ::std::process::exit(1);\n    }\n}\n\n// Most functions will return the `Result` type, imported from the\n// `errors` module. It is a typedef of the standard `Result` type\n// for which the error type is always our own `Error`.\nfn run() -\u003e Result\u003c()\u003e {\n    use std::fs::File;\n\n    // Use chain_err to attach your own context to errors\n    File::open(\"my secret file\")\n        .chain_err(|| \"unable to open my secret file\")?;\n\n    // Use the `bail!` macro to return an error Result, ala `println!`\n    bail!(\"giving up\");\n}\n```\n\n**Alternatives**: [`quick-error`]\n\n\u0026nbsp;\u0026NewLine;\u0026nbsp;\u0026NewLine;\u0026nbsp;\u0026NewLine;\n\n\n\u003ca id=\"flate2\"\u003e\u003c/a\u003e\n### `flate2 = \"0.2.19\"` \u0026emsp; [📖][d-flate2]\n\nCompression and decompression using the [DEFLATE] algorithm.\n\n**Example**: [`examples/flate2.rs`]\n\n```rust,no_run\nextern crate flate2;\nextern crate tar;\n\nuse flate2::read::GzDecoder;\nuse std::env;\nuse std::fs::File;\nuse std::io::{self, BufReader};\nuse tar::Archive;\n\nfn run() -\u003e Result\u003c(), io::Error\u003e {\n    let mut args = env::args().skip(1);\n    let tarball = args.next().expect(\"incorrect argument\");\n    let outdir = args.next().expect(\"incorrect argument\");\n\n    let archive = File::open(tarball)?;\n    let archive = BufReader::new(archive);\n    let archive = GzDecoder::new(archive)?;\n    let mut archive = Archive::new(archive);\n\n    archive.unpack(outdir)?;\n\n    Ok(())\n}\n\nfn main() { run().unwrap() }\n```\n\n\u0026nbsp;\u0026NewLine;\u0026nbsp;\u0026NewLine;\u0026nbsp;\u0026NewLine;\n\n\u003ca id=\"fnv\"\u003e\u003c/a\u003e\n### `fnv = \"1.0.5\"` \u0026emsp; [📖][d-fnv]\n\nThe standard library's hash maps are notoriously slow for small keys (like\nintegers). That's because they provide strong protection against a class of\ndenial-of-service attacks called [\"hash flooding\"]. And that's a reasonable\ndefault. But when your `HashMap`s are a bottleneck consider reaching for this\ncrate. It provides the Fowler-Noll-Vo hash function, and conveniences for\ncreating FNV hash maps that are considerably faster than those in std.\n\n**Example**: [`examples/fnv.rs`]\n\n```rust\nextern crate fnv;\n\nuse fnv::FnvHashMap;\n\nfn main() {\n    let mut map = FnvHashMap::default();\n    map.insert(1, \"one\");\n    map.insert(2, \"two\");\n    map.insert(3, \"three\");\n\n    for (number, word) in map.iter() {\n        println!(\"Number {}: {}\", number, word);\n    }\n\n    map.remove(\u0026(2));\n    println!(\"The length of HashMap is {}.\", map.len());\n    println!(\"The first element is {}.\", map.get(\u0026(1)).unwrap());\n}\n```\n\n\u0026nbsp;\u0026NewLine;\u0026nbsp;\u0026NewLine;\u0026nbsp;\u0026NewLine;\n\n\n\u003ca id=\"itertools\"\u003e\u003c/a\u003e\n### `itertools = \"0.6.0\"` \u0026emsp; [📖][d-itertools]\n\nThe Rust standard [`Iterator`] type provides a powerful abstraction for\noperating over sequences of values, and is used pervasively throughout\nRust. There are though a number of common operations one might want to perform\non sequences that are not provided by the standard library, and that's where\nitertools comes in. This crate has everything *including* the kitchen sink (in\nthe form of the [`batching`] adaptor). Highlights include [`dedup`], [`group_by`],\n[`mend_slices`], [`merge`], [`sorted`], [`join`] and more.\n\n**Example**: [`examples/itertools.rs`]\n\n```rust\nextern crate itertools;\n\nuse itertools::{join, max, sorted};\n\nfn main(){\n    let a = [3, 2, 5, 8, 7];\n\n    // Combine all iterator elements into one String,\n    // seperated by *.\n    println!(\"{:?}\", join(\u0026a, \"*\"));\n    // Return the maximum value of the iterable.\n    println!(\"{:?}\", max(a.iter()).unwrap());\n    // Collect all the iterable's elements into a\n    // sorted vector in ascending order.\n    println!(\"{:?}\", sorted(a.iter()));\n}\n```\n\n\u0026nbsp;\u0026NewLine;\u0026nbsp;\u0026NewLine;\u0026nbsp;\u0026NewLine;\n\n\n\u003ca id=\"lazy_static\"\u003e\u003c/a\u003e\n### `lazy_static = \"0.2.8\"` \u0026emsp; [📖][d-lazy_static]\n\nRust has strict rules about accessing global state. In particular\nthere is no ['life before main'] in Rust, so it's not possible to\nwrite a programmatic constructor for a global value that will be run\nat startup. Instead, Rust prefers lazy execution for global\ninitialization, and the `lazy_static!` macro does just that.\n\n**Example**: [`examples/lazy_static.rs`]\n\n```rust\n#[macro_use]\nextern crate lazy_static;\n\nuse std::collections::HashMap;\n\nlazy_static! {\n    static ref HASHMAP: HashMap\u003cu32, \u0026'static str\u003e = {\n        let mut m = HashMap::new();\n        m.insert(0, \"foo\");\n        m.insert(1, \"bar\");\n        m.insert(2, \"baz\");\n        m\n    };\n    static ref COUNT: usize = HASHMAP.len();\n    static ref NUMBER: u32 = times_two(21);\n}\n\nfn times_two(n: u32) -\u003e u32 { n * 2 }\n\nfn main() {\n    println!(\"The map has {} entries.\", *COUNT);\n    println!(\"The entry for `0` is \\\"{}\\\".\", HASHMAP.get(\u00260).unwrap());\n    println!(\"A expensive calculation on a static results in: {}.\", *NUMBER);\n}\n```\n\n\u0026nbsp;\u0026NewLine;\u0026nbsp;\u0026NewLine;\u0026nbsp;\u0026NewLine;\n\n\n\u003ca id=\"libc\"\u003e\u003c/a\u003e\n### `libc = \"0.2.25\"` \u0026emsp; [📖][d-libc]\n\nIf you need to talk to foreign code, you need this crate. It exports C\ntype and function definitions appropriate to each target platform Rust\nsupports. It defines the standardized C features that are common\nacross all platforms as well as non-standard features specific to the\nplatform C libraries. For more platform-specific FFI definitions\nsee [`nix`] and [`winapi`].\n\n**Example**: [`examples/libc.rs`]\n\n```rust\nextern crate libc;\n\nfn main() {\n    unsafe {\n        libc::exit(0);\n    }\n}\n```\n\n\u0026nbsp;\u0026NewLine;\u0026nbsp;\u0026NewLine;\u0026nbsp;\u0026NewLine;\n\n\n\u003ca id=\"log\"\u003e\u003c/a\u003e\n### `log = \"0.3.8\"` \u0026emsp; [📖][d-log]\n\nThe most common way to perform basic logging in Rust, with the\n[`error!`], [`warn!`], [`info!`], and [`debug!`] macros. It is often\ncombined with the [`env_logger`] crate to get logging to the console,\ncontrolled by the [`RUST_LOG`] environment variable.  This is the\ntraditional logging crate used by `rustc`, and its functionality was\nonce built in to the language.\n\n**Supplemental crates**: [`env_logger = \"0.4.3\"`]\n\n**Example**: [`examples/log.rs`]\n\n```rust\n#[macro_use]\nextern crate log;\nextern crate env_logger;\n\nuse log::LogLevel;\n\nfn main() {\n    env_logger::init().unwrap();\n\n    debug!(\"this is a debug {}\", \"message\");\n    error!(\"this is printed by default\");\n\n    if log_enabled!(LogLevel::Info) {\n        let x = 3 * 4; // expensive computation\n        info!(\"the answer was: {}\", x);\n    }\n}\n```\n\n**Alternatives**: [`slog`], [`log4rs`]\n\n\u0026nbsp;\u0026NewLine;\u0026nbsp;\u0026NewLine;\u0026nbsp;\u0026NewLine;\n\n\n\u003ca id=\"memmap\"\u003e\u003c/a\u003e\n### `memmap = \"0.5.2\"` \u0026emsp; [📖][d-memmap]\n\nCross-platform access to [memory-mapped I/O], a technique for sharing\nmemory between processes, and for accessing the content of files as a\nsimple array of bytes. It is implemented by binding the [`mmap`]\nsyscall on Unix, and the [`CreateFileMapping`] / [`MapViewOfFile`]\nfunctions on Windows. This is a low-level feature used to build other\nabstractions. Note that it's not generally possible to create safe\nabstractions for memory mapping, since memory mapping entails shared\naccess to resources outside of Rust's control. As such, the APIs\nin this crate are unsafe.\n\n**Example**: [`examples/memmap.rs`]\n\n[`examples/memmap.rs`]: examples/memmap.rs\n\n```rust,no_run\nextern crate memmap;\n\nuse memmap::{Mmap, Protection};\nuse std::env;\nuse std::io;\nuse std::str;\n\nfn run() -\u003e Result\u003c(), io::Error\u003e {\n    let mut args = env::args().skip(1);\n    let input = args.next().expect(\"incorrect argument\");\n\n    let map = Mmap::open_path(input, Protection::Read)?;\n    unsafe {\n        let all_bytes = map.as_slice();\n        if let Ok(file_str) = str::from_utf8(all_bytes) {\n            println!(\"{}\", file_str);\n        } else {\n            println!(\"not utf8\");\n        }\n    }\n    Ok(())\n}\n\nfn main() { run().unwrap() }\n```\n\n\u0026nbsp;\u0026NewLine;\u0026nbsp;\u0026NewLine;\u0026nbsp;\u0026NewLine;\n\n\n\u003ca id=\"ndarray\"\u003e\u003c/a\u003e\n### `ndarray = \"0.9.1\"` \u0026emsp; [📖][d-ndarray]\n\nThe ndarray crate provides an N-dimensional container for general\nelements and for numerics. The multidimensional array, otherwise known\nas a \"matrix\", is a core data structure for numerical applications,\nand Rust does not have one in the language or standard library.\n\n**Example**: [`examples/ndarray.rs`]\n\n```rust\n#[macro_use(s)]\nextern crate ndarray;\n\nuse ndarray::{Array3, arr3};\n\nfn main() {\n    // Create a three-dimensional f64 array, initialized with zeros\n    let mut temperature = Array3::\u003cf64\u003e::zeros((3, 4, 5));\n\n    // Increase the temperature in this location, notice the\n    // double-brackets indexing `temperature`\n    temperature[[2, 2, 2]] += 0.5;\n\n    // Create a 3-dimensional matrix,\n    // 2 submatrices of 2 rows with 3 elements per row, means a shape\n    // of `[2, 2, 3]`.\n    let a = arr3(\u0026[[[ 1,  2,  3],     // -- 2 rows  \\_\n                    [ 4,  5,  6]],    // --         /\n                   [[ 7,  8,  9],     //            \\_ 2 submatrices\n                    [10, 11, 12]]]);  //            /\n    //  3 columns ..../.../.../\n\n    // This is a 2 x 2 x 3 array\n    assert_eq!(a.shape(), \u0026[2, 2, 3]);\n\n    // Let’s create a slice of `a` with\n    //\n    // - Both of the submatrices of the greatest dimension: `..`\n    // - Only the first row in each submatrix: `0..1`\n    // - Every element in each row: `..`\n    let b = a.slice(s![.., 0..1, ..]);\n\n    // This is the result of the above slice into `a`\n    let c = arr3(\u0026[[[ 1,  2,  3]],\n                   [[ 7,  8,  9]]]);\n    assert_eq!(b, c);\n    assert_eq!(b.shape(), \u0026[2, 1, 3]);\n}\n```\n\n\u0026nbsp;\u0026NewLine;\u0026nbsp;\u0026NewLine;\u0026nbsp;\u0026NewLine;\n\n\n\u003ca id=\"num\"\u003e\u003c/a\u003e\n### `num = \"0.1.40\"` \u0026emsp; [📖][d-num]\n\nBig integers, rational numbers, complex numbers, and numeric\ntraits. This crate has a long history, beginning life in the standard\nlibrary, being moved into the rust-lang organization, and finally\nbeing adopted by community maintainers. It remains a common way to\naccess the kinds of features it provides.\n\n**Example**: [`examples/num.rs`]\n\n```rust\nextern crate num;\n\nuse num::FromPrimitive;\nuse num::bigint::BigInt;\nuse num::rational::{Ratio, BigRational};\n\nfn approx_sqrt(number: u64, iterations: usize) -\u003e BigRational {\n    let start: Ratio\u003cBigInt\u003e\n        = Ratio::from_integer(FromPrimitive::from_u64(number).unwrap());\n\n    let mut approx = start.clone();\n\n    for _ in 0..iterations {\n        approx = (\u0026approx + (\u0026start / \u0026approx)) /\n            Ratio::from_integer(FromPrimitive::from_u64(2).unwrap());\n    }\n\n    approx\n}\n\nfn main() {\n    println!(\"{}\", approx_sqrt(10, 4)); // prints 4057691201/1283082416\n}\n```\n\n\u0026nbsp;\u0026NewLine;\u0026nbsp;\u0026NewLine;\u0026nbsp;\u0026NewLine;\n\n\u003ca id=\"num_cpus\"\u003e\u003c/a\u003e\n### `num_cpus = \"1.6.2\"` \u0026emsp; [📖][d-num_cpus]\n\nWhen you need to make things parallel, you need to know how many CPUs\nto use! This is the simple way to get that information.\n\n**Example**: [`examples/num_cpus.rs`]\n\n```rust\nextern crate threadpool;\nextern crate num_cpus;\n\nuse threadpool::ThreadPool;\nuse std::sync::mpsc::channel;\n\nfn main() {\n    // Get the number of cpus on current machine\n    let n_workers = num_cpus::get();\n    let n_jobs = 8;\n\n    // Create the thread pool with amount of workers equal to cores\n    let pool = ThreadPool::new(n_workers);\n\n    // Create transmitter and receiver channel\n    let (tx, rx) = channel();\n\n    // For each job grab a free worker from the pool and execute\n    for _ in 0..n_jobs {\n        let tx = tx.clone();\n        pool.execute(move || {\n            tx.send(1).unwrap();\n        });\n    }\n\n    assert_eq!(rx.iter().take(n_jobs).fold(0, |a, b| a + b), 8);\n}\n```\n\n\u0026nbsp;\u0026NewLine;\u0026nbsp;\u0026NewLine;\u0026nbsp;\u0026NewLine;\n\n\n\u003ca id=\"rand\"\u003e\u003c/a\u003e\n### `rand = \"0.3.15\"` \u0026emsp; [📖][d-rand]\n\nRandom number generators. The defaults are cryptographically\nstrong. This is another crate with a long history, beginning life in\nthe standard library.\n\n**Example**: [`examples/rand.rs`]\n\n```rust\nextern crate rand;\n\nuse rand::Rng;\n\nfn main() {\n    let mut rng = rand::thread_rng();\n    if rng.gen() { // random bool\n        println!(\"i32: {}, u32: {}\", rng.gen::\u003ci32\u003e(), rng.gen::\u003cu32\u003e())\n    }\n\n    let tuple = rand::random::\u003c(f64, char)\u003e();\n    println!(\"{:?}\", tuple)\n}\n```\n\n\u0026nbsp;\u0026NewLine;\u0026nbsp;\u0026NewLine;\u0026nbsp;\u0026NewLine;\n\n\n\u003ca id=\"rayon\"\u003e\u003c/a\u003e\n### `rayon = \"0.8.2\"` \u0026emsp; [📖][d-rayon]\n\nWhen people say that Rust makes parallelism easy, this is why. Rayon\nprovides parallel iterators that make expressing efficient parallel\noperations simple and foolproof.\n\n**Example**: [`examples/rayon.rs`]\n\n```rust\nextern crate rayon;\n\nuse rayon::prelude::*;\n\nfn main() {\n    let mut input = (0..1000).collect::\u003cVec\u003c_\u003e\u003e();\n\n    // Calculate the sum of squares\n    let sq_sum: i32 = input.par_iter()\n                      .map(|\u0026i| i * i)\n                      .sum();\n\n    // Increment each element in parallel\n    input.par_iter_mut()\n        .for_each(|p| *p += 1);\n\n    // Parallel quicksort\n    let mut input = (0..1000).rev().collect::\u003cVec\u003c_\u003e\u003e();\n    quick_sort(\u0026mut input);\n}\n\nfn quick_sort\u003cT: PartialOrd + Send\u003e(v: \u0026mut [T]) {\n    if v.len() \u003c= 1 {\n        return;\n    }\n\n    let mid = partition(v);\n    let (lo, hi) = v.split_at_mut(mid);\n    rayon::join(|| quick_sort(lo), || quick_sort(hi));\n}\n\nfn partition\u003cT: PartialOrd + Send\u003e(v: \u0026mut [T]) -\u003e usize {\n    let pivot = v.len() - 1;\n    let mut i = 0;\n    for j in 0..pivot {\n        if v[j] \u003c= v[pivot] {\n            v.swap(i, j);\n            i += 1;\n        }\n    }\n    v.swap(i, pivot);\n    i\n}\n```\n\n\u0026nbsp;\u0026NewLine;\u0026nbsp;\u0026NewLine;\u0026nbsp;\u0026NewLine;\n\n\n\u003ca id=\"regex\"\u003e\u003c/a\u003e\n### `regex = \"0.2.2\"` \u0026emsp; [📖][d-regex]\n\nRust's regular expressions are [fast], like Rust is fast. Part of\ntheir power comes from a careful design that disallows back-references\nand arbitrary lookahead, creating predictable worst-case performance.\n\n**Example**: [`examples/regex.rs`]\n\n```rust\nextern crate regex;\n\nuse regex::Regex;\n\nfn main() {\n    // Find a date\n    let re = Regex::new(r\"^\\d{4}-\\d{2}-\\d{2}$\").unwrap();\n    assert!(re.is_match(\"2014-01-01\"));\n\n    // Iterating over capture groups\n    let re = Regex::new(r\"(\\d{4})-(\\d{2})-(\\d{2})\").unwrap();\n    let text = \"2012-03-14, 2013-01-01 and 2014-07-05\";\n    for cap in re.captures_iter(text) {\n        println!(\"Month: {} Day: {} Year: {}\", \u0026cap[2], \u0026cap[3], \u0026cap[1]);\n    }\n}\n```\n\n\u0026nbsp;\u0026NewLine;\u0026nbsp;\u0026NewLine;\u0026nbsp;\u0026NewLine;\n\n\n\u003ca id=\"reqwest\"\u003e\u003c/a\u003e\n### `reqwest = \"0.7.1\"` \u0026emsp; [📖][d-reqwest]\n\nA simple HTTP and HTTPS client. It is built on the popular Rust HTTP\nimplementation, [hyper], which is the HTTP stack developed for\n[Servo].\n\n**Example**: [`examples/reqwest.rs`]\n\n```rust,no_run\nextern crate reqwest;\n\nuse std::collections::HashMap;\nuse std::io::{BufRead, BufReader};\n\nfn main() {\n    // Make a GET request\n    let resp = reqwest::get(\"https://www.rust-lang.org\").unwrap();\n    assert!(resp.status().is_success());\n\n    let lines = BufReader::new(resp)\n                          .lines()\n                          .filter_map(|l| l.ok())\n                          .take(10);\n    for line in lines {\n        println!(\"{}\", line);\n    }\n\n    // Make a POST request\n    let client = reqwest::Client::new().unwrap();\n    let res = client.post(\"http://httpbin.org/post\").unwrap()\n        .body(\"the exact body that is sent\")\n        .send();\n\n    // Convert to/from JSON automatically\n    let mut map = HashMap::new();\n    map.insert(\"lang\", \"rust\");\n    map.insert(\"body\", \"json\");\n\n    // This will POST a body of `{\"lang\":\"rust\",\"body\":\"json\"}`\n    let client = reqwest::Client::new().unwrap();\n    let res = client.post(\"http://httpbin.org/post\").unwrap()\n        .json(\u0026map).unwrap()\n        .send();\n}\n```\n\n\u0026nbsp;\u0026NewLine;\u0026nbsp;\u0026NewLine;\u0026nbsp;\u0026NewLine;\n\n\n\u003ca id=\"semver\"\u003e\u003c/a\u003e\n### `semver = \"0.7.0\"` \u0026emsp; [📖][d-semver]\n\nRust uses [semantic versioning][semver] (also known as \"semver\") for\ncrate versioning. This crate provides the canonical semver\nrepresentation for Rust.\n\n**Example**: [`examples/semver.rs`]\n\n```rust\nextern crate semver;\n\nuse semver::Version;\n\nfn main() {\n    // Construct Version objects\n    assert!(Version::parse(\"1.2.3\") == Ok(Version {\n        major: 1,\n        minor: 2,\n        patch: 3,\n        pre: vec!(),\n        build: vec!(),\n    }));\n\n    // Compare Versions\n    assert!(Version::parse(\"1.2.3-alpha\") != Version::parse(\"1.2.3-beta\"));\n    assert!(Version::parse(\"1.2.3-alpha2\") \u003e  Version::parse(\"1.2.0\"));\n\n    // Increment patch number of mutable Version\n    let mut bugfix_release = Version::parse(\"1.0.0\").unwrap();\n    bugfix_release.increment_patch();\n\n    assert_eq!(Ok(bugfix_release), Version::parse(\"1.0.1\"));\n}\n```\n\n\u0026nbsp;\u0026NewLine;\u0026nbsp;\u0026NewLine;\u0026nbsp;\u0026NewLine;\n\n\n\u003ca id=\"serde\"\u003e\u003c/a\u003e\n### `serde = \"1.0.10\"` \u0026emsp; [📖][d-serde]\n\nSerialization and deserialization of Rust datastructures is fast\nand easy using the `serde` serialization framework. Simply\ntag your data structures with `#[derive(Serialize, Deserialize)]`\nand serde will automatically convert them between formats like\nJSON, TOML, YAML, and more. To best understand serde, read\nits documentation at [serde.rs].\n\n**Supplemental crates**: [`serde_derive = \"1.0.10\"`],\n                         [`serde_json = \"1.0.2\"`],\n                         [`toml = \"0.4.2\"`]\n\n**Example**: [`examples/serde.rs`]\n\n```rust\n#[macro_use]\nextern crate serde_derive;\nextern crate serde_json;\n\nuse serde_json::Value;\n\n#[derive(Serialize, Deserialize, Debug)]\nstruct Contact {\n    name: String,\n    age: u32,\n}\n\nfn main() {\n    let contact = Contact {\n        name: \"Brian\".to_string(),\n        age: 21,\n    };\n\n    // Serialize data structures to strings in JSON format\n    let contact: String = serde_json::to_string(\u0026contact).unwrap();\n    println!(\"{}\", contact);\n\n    // Deserialize data structures from JSON strings\n    let contact: Contact = serde_json::from_str(\u0026contact).unwrap();\n    println!(\"{:?}\", contact);\n\n    // Convert to arbitrary JSON `Value` type\n    let contact: Value = serde_json::to_value(\u0026contact).unwrap();\n    println!(\"{:?}\", contact);\n}\n```\n\n**Alternatives**: [`rustc-serialize`]\n\n\u0026nbsp;\u0026NewLine;\u0026nbsp;\u0026NewLine;\u0026nbsp;\u0026NewLine;\n\n\n\u003ca id=\"serde_json\"\u003e\u003c/a\u003e\n### `serde_json = \"1.0.2\"` \u0026emsp; [📖][d-serde_json]\n\nAccess to [JSON], the \"JavaScript Object Notation\" format,\nwidely used for transmission and storage of data on the Internet.\nThis crate can be used for reading, writing, and manipulation\nof arbitrary JSON in addition to its use for automatic serialization\nwith [serde](#serde).\n\n**Example**: [`examples/json.rs`]\n\n```rust\nextern crate serde_json;\n\nuse serde_json::Value;\n\nfn main() {\n    // Some JSON input data as a \u0026str. Maybe this comes from the user.\n    let data = r#\"{\n                    \"name\": \"John Doe\",\n                    \"age\": 43,\n                    \"phones\": [\n                      \"+44 1234567\",\n                      \"+44 2345678\"\n                    ]\n                  }\"#;\n\n    // Parse the string of data into serde_json::Value.\n    let v: Value = serde_json::from_str(data).unwrap();\n\n    // Access parts of the data by indexing with square brackets.\n    println!(\"Please call {} at the number {}\", v[\"name\"], v[\"phones\"][0]);\n}\n```\n\n**Alternatives**: [`json`]\n\n\u0026nbsp;\u0026NewLine;\u0026nbsp;\u0026NewLine;\u0026nbsp;\u0026NewLine;\n\n\n\u003ca id=\"tar\"\u003e\u003c/a\u003e\n### `tar = \"0.4.23\"` \u0026emsp; [📖][d-tar]\n\nThe \"tar\" archive format is in common use on the web. It is most often\nfound in the form of `.tar.gz` files (called \"tarballs\") that have\nbeen compressed with the [DEFLATE] algorithm, which the `tar` crate\ncan decompress when paired with the [`flate2`][flate2] crate.\n\n**Example**: [`examples/tar.rs`]\n\n```rust,no_run\nextern crate flate2;\nextern crate tar;\n\nuse flate2::read::GzDecoder;\nuse std::env;\nuse std::fs::File;\nuse std::io::{self, BufReader};\nuse tar::Archive;\n\nfn run() -\u003e Result\u003c(), io::Error\u003e {\n    let mut args = env::args().skip(1);\n    let tarball = args.next().expect(\"incorrect argument\");\n    let outdir = args.next().expect(\"incorrect argument\");\n\n    let archive = File::open(tarball)?;\n    let archive = BufReader::new(archive);\n    let archive = GzDecoder::new(archive)?;\n    let mut archive = Archive::new(archive);\n\n    archive.unpack(outdir)?;\n\n    Ok(())\n}\n\nfn main() { run().unwrap() }\n```\n\n\u0026nbsp;\u0026NewLine;\u0026nbsp;\u0026NewLine;\u0026nbsp;\u0026NewLine;\n\n\n\u003ca id=\"tempdir\"\u003e\u003c/a\u003e\n### `tempdir = \"0.3.5\"` \u0026emsp; [📖][d-tempdir]\n\nThe most common way to create temporary directories in Rust,\nthis crate was once part of the standard library.\n\n**Example**: [`examples/tempdir.rs`]\n\n```rust\nextern crate tempdir;\n\nuse std::fs::File;\nuse std::io::Write;\nuse tempdir::TempDir;\n\nfn main() {\n    // Create a directory inside of `std::env::temp_dir()`, named with\n    // the prefix \"example\".\n    let tmp_dir = TempDir::new(\"example\").expect(\"create temp dir\");\n    let file_path = tmp_dir.path().join(\"my-temporary-note.txt\");\n    let mut tmp_file = File::create(file_path).expect(\"create temp file\");\n    writeln!(tmp_file, \"Brian was here. Briefly.\").expect(\"write temp file\");\n\n    // By closing the `TempDir` explicitly, we can check that it has\n    // been deleted successfully. If we don't close it explicitly,\n    // the directory will still be deleted when `tmp_dir` goes out\n    // of scope, but we won't know whether deleting the directory\n    // succeeded.\n    drop(tmp_file);\n    tmp_dir.close().expect(\"delete temp dir\");\n}\n```\n\n\u0026nbsp;\u0026NewLine;\u0026nbsp;\u0026NewLine;\u0026nbsp;\u0026NewLine;\n\n\n\u003ca id=\"threadpool\"\u003e\u003c/a\u003e\n### `threadpool = \"1.4.0\"` \u0026emsp; [📖][d-threadpool]\n\nA thread pool for running a number of jobs on a fixed set of worker threads.\n\n**Example**: [`examples/threadpool.rs`]\n\n```rust\nextern crate threadpool;\nextern crate num_cpus;\n\nuse threadpool::ThreadPool;\nuse std::sync::mpsc::channel;\n\nfn main() {\n    // Get the number of cpus on current machine\n    let n_workers = num_cpus::get();\n    let n_jobs = 8;\n\n    // Create the thread pool with amount of workers equal to cores\n    let pool = ThreadPool::new(n_workers);\n\n    // Create transmitter and receiver channel\n    let (tx, rx) = channel();\n\n    // For each job grab a free worker from the pool and execute\n    for _ in 0..n_jobs {\n        let tx = tx.clone();\n        pool.execute(move || {\n            tx.send(1).unwrap();\n        });\n    }\n\n    assert_eq!(rx.iter().take(n_jobs).fold(0, |a, b| a + b), 8);\n}\n```\n\n**Alternatives**: [`scoped_threadpool`]\n\n\u0026nbsp;\u0026NewLine;\u0026nbsp;\u0026NewLine;\u0026nbsp;\u0026NewLine;\n\n\u003ca id=\"toml\"\u003e\u003c/a\u003e\n### `toml = \"0.4.2\"` \u0026emsp; [📖][d-toml]\n\n[TOML](https://github.com/toml-lang/toml) is a common format for\nconfiguration files, like [Cargo.toml]. It's easy on the eyes, simple\nto parse, and serializes from Rust types with [`serde`](#serde).\n\n**Example**: [`examples/toml.rs`]\n\n```rust\nextern crate toml;\n\nuse toml::Value;\n\nfn main() {\n    let toml = r#\"\n    [test]\n    foo = \"bar\"\n\"#;\n\n    let value = toml.parse::\u003cValue\u003e().unwrap();\n    println!(\"{:?}\", value);\n}\n```\n\n\u0026nbsp;\u0026NewLine;\u0026nbsp;\u0026NewLine;\u0026nbsp;\u0026NewLine;\n\n\n\u003ca id=\"url\"\u003e\u003c/a\u003e\n### `url = \"1.5.1\"` \u0026emsp; [📖][d-url]\n\nThe URL parser and type, originally created for [Servo].\n\n**Example**: [`examples/url.rs`]\n\n```rust\nextern crate url;\n\nuse url::{Url, Host};\n\nfn main() {\n    let issue_list_url = Url::parse(\n        \"https://github.com/rust-lang/rust/issues?labels=E-easy\u0026state=open\"\n    ).unwrap();\n\n    assert!(issue_list_url.scheme() == \"https\");\n    assert!(issue_list_url.username() == \"\");\n    assert!(issue_list_url.password() == None);\n    assert!(issue_list_url.host_str() == Some(\"github.com\"));\n    assert!(issue_list_url.host() == Some(Host::Domain(\"github.com\")));\n    assert!(issue_list_url.port() == None);\n    assert!(issue_list_url.path() == \"/rust-lang/rust/issues\");\n    assert!(issue_list_url.path_segments().map(|c| c.collect::\u003cVec\u003c_\u003e\u003e()) ==\n            Some(vec![\"rust-lang\", \"rust\", \"issues\"]));\n    assert!(issue_list_url.query() == Some(\"labels=E-easy\u0026state=open\"));\n    assert!(issue_list_url.fragment() == None);\n    assert!(!issue_list_url.cannot_be_a_base());\n}\n```\n\n\u0026nbsp;\u0026NewLine;\u0026nbsp;\u0026NewLine;\u0026nbsp;\u0026NewLine;\n\n\n\u003ca id=\"walkdir\"\u003e\u003c/a\u003e\n### `walkdir = \"1.0.7\"` \u0026emsp; [📖][d-walkdir]\n\nA cross platform Rust library for efficiently walking a directory\nrecursively. Note the [`filter_entry`] method on the directory\niterator that short-circuits decent into subdirectories.\n\n**Example**: [`examples/walkdir.rs`]\n\n```rust\nextern crate walkdir;\n\nuse walkdir::{WalkDir, Error};\n\nfn run() -\u003e Result\u003c(), Error\u003e {\n    let wd = WalkDir::new(\".\");\n\n    for entry in wd {\n        let entry = entry?;\n        println!(\"{}\", entry.path().display());\n    }\n\n    Ok(())\n}\n\nfn main() { run().unwrap(); }\n```\n\n\u0026nbsp;\u0026NewLine;\u0026nbsp;\u0026NewLine;\u0026nbsp;\u0026NewLine;\n\n\n## About `stdx`\n\nRust has a lovely and portable standard library, but it is not\nfeatureful enough to write software of any great\nsophistication. Compared to common platforms including Java, Python,\nand Go, Rust's standard library is small.\n\nIn Rust, the libraries we use for even simple tasks live and evolve on\n[crates.io]. This affords the Rust community freedom to experiment -\ndiscovering the Rustiest solutions to even common problems can take\nquite some iteration - but it also means that we're in for a slow\nevolutionary process to converge around the best of those solutions. In\nthe meantime, you just have to know which crates to use for what.\n\n`stdx` contains some of the most important crates in Rust. I mean\nit. If Rust had a more expansive standard library, many of the `stdx`\ncrates would be in it, or at least the features they provide. Many of\nthe crates of `stdx` are maintained by the same authors as the Rust\nstandard library, and they are designed to be idiomatic and\ninteroperable. These are core elements of the crate ecosystem that\nall Rusticians should be aware of.\n\n[crates.io]: https://www.crates.io\n\n## How to use `stdx`\n\n`stdx` is primarily a teaching tool. New and old Rust programmers\nalike will get the most from it by digesting [the list](#list) of\n`stdx` crates, each entry of which links to a description of the crate\nalong with _an example of its basic use_.\n\nThese examples are full working source and are intended to get you\nup and running with any of the `stdx` crates _immediately_. Just\ncopy the crate name and version exactly as written into the `dependencies`\nsection of your `Cargo.toml` like so:\n\n```toml\n[dependencies]\nbitflags = \"0.9.1\"\n```\n\nThen copy the full example into your `examples` directory, like\nso:\n\n**Example**: [`examples/bitflags.rs`]\n\n```rust\n#[macro_use]\nextern crate bitflags;\n\nbitflags! {\n    struct Flags: u32 {\n        const FLAG_A       = 0b00000001;\n        const FLAG_B       = 0b00000010;\n        const FLAG_C       = 0b00000100;\n        const FLAG_ABC     = FLAG_A.bits\n                           | FLAG_B.bits\n                           | FLAG_C.bits;\n    }\n}\n\nfn main() {\n    let e1 = FLAG_A | FLAG_C;\n    let e2 = FLAG_B | FLAG_C;\n    assert_eq!((e1 | e2), FLAG_ABC);   // union\n    assert_eq!((e1 \u0026 e2), FLAG_C);     // intersection\n    assert_eq!((e1 - e2), FLAG_A);     // set difference\n    assert_eq!(!e2, FLAG_A);           // set complement\n}\n```\n\nThen execute the following:\n\n```sh\ncargo run --example bitflags\n```\n\nAnd suddenly you are a slightly-experienced user of that crate.\nNow click on the [📖][d-bitflags] icon to get the rest of the story.\n\nConvinced? [Go check out that list](#list).\n\n\n## Why use `stdx`?\n\nAs a learning tool, I hope the benefit will be evident from a straight\nread-through. But `stdx`, and tools like it, may provide important\nbenefits to users in the future.\n\nTo be clear, `stdx` is experimental. A lot of the below is\nspeculative.\n\n`stdx` provides assurances that the versions of crates it specifes\nwork together correctly in a wide variety of configurations. Today\nthose assurances are few, but they will grow. And these types of\nassurances will become increasingly valuable to Rust.\n\nAs of now, the only validation `stdx` provides is that the exact\nversions of the `stdx` crates resolve correctly by Cargo, and that\nthey build on Linux and Windows. That is already beneficial by\nuncovering problematic combinations and incorrect semver\nspecifications. Here are some other assurances that `stdx` will\nenable:\n\n* Additional integration test cases between the `stdx` crates\n* Testing of all `stdx` crates' own test suites using the `stdx` version lock\n* Testing on all tier 1 platforms\n* Testing on tier 2 platforms\n* Enforcement and coverage of `serde` features and interop\n* Enforcement of other compile-time feature standards\n* `stdx` as version lock - you don't even have to call into it. Just\n  link to it and it locks down a chunk of your crate graph to\n  known-good combinaitons.\n* Ecosystem wide testing using `stdx` version lock - eventually we\n  will be able to say which crates are known to work correctly\n  with `stdx`.\n* The more people use the `stdx` version lock the more assurance they\n  get. This plays into future Rust's LTS directions.\n\nBy applying high quality standards to a small selection of critical\ncrates we can create a high degree of confidence in a larger core of\nthe Rust ecosystem.\n\n\n## Selection criteria\n\nThe criteria for inclusion in `stdx` is conservative, and fuzzy. It's\nmostly crates that are pretty super important, considering criteria\nlike\n\n- portability\n- quality\n- conformance to conventions\n- documentation\n- interoperability with other crates\n- reliability of maintainers\n- de-facto adoption\n- historical context and precedent\n\n`stdx` is focused on core features, crates that are quintessentially\nRust and relied on by many Rust programs. It is intentionally\nlimited for the sake of simplicity and ease of comprehension.\n\nAll crates must work on Rust's tier-1 platforms, currently x86 Linux,\nOS X, and Windows.\n\n\n## Contributing\n\nSee [CONTRIBUTING.md](CONTRIBUTING.md).\n\n\n## License\n\n`stdx` and the crates it links to are licensed under various\n[permissive, BSD-like][perm] licenses. In lay-terms these licenses\nallow their code to be used and distributed freely, and are compatible\nwith [Rust's own license (MIT/Apache 2)][rustlice].\n\n`stdx` itself is dual MIT/Apache 2 licensed, like Rust, and the\ncopyright is owned by its contributors.\n\n[perm]: https://en.wikipedia.org/wiki/Permissive_free_software_licence\n[rustlice]: https://github.com/rust-lang/rust/blob/master/COPYRIGHT\n\n\n\u003c!-- links --\u003e\n\n\u003c!-- stdx crates --\u003e\n\n[`bitflags = \"0.9.1\"`]: #bitflags\n[`byteorder = \"1.1.0\"`]: #byteorder\n[`chrono = \"0.4.0\"`]: #chrono\n[`clap = \"2.25.0\"`]: #clap\n[`encoding_rs = \"0.6.11\"`]: #encoding_rs\n[`error-chain = \"0.10.0\"`]: #error-chain\n[`flate2 = \"0.2.19\"`]: #flate2\n[`fnv = \"1.0.5\"`]: #fnv\n[`itertools = \"0.6.0\"`]: #itertools\n[`serde_json = \"1.0.2\"`]: #serde_json\n[`lazy_static = \"0.2.8\"`]: #lazy_static\n[`libc = \"0.2.25\"`]: #libc\n[`log = \"0.3.8\"`]: #log\n[`memmap = \"0.5.2\"`]: #memmap\n[`ndarray = \"0.9.1\"`]: #ndarray\n[`num = \"0.1.40\"`]: #num\n[`num_cpus = \"1.6.2\"`]: #num_cpus\n[`rand = \"0.3.15\"`]: #rand\n[`rayon = \"0.8.2\"`]: #rayon\n[`regex = \"0.2.2\"`]: #regex\n[`reqwest = \"0.7.1\"`]: #reqwest\n[`semver = \"0.7.0\"`]: #semver\n[`serde = \"1.0.10\"`]: #serde\n[`tar = \"0.4.23\"`]: #tar\n[`tempdir = \"0.3.5\"`]: #tempdir\n[`threadpool = \"1.4.0\"`]: #threadpool\n[`toml = \"0.4.2\"`]: #toml\n[`url = \"1.5.1\"`]: #url\n[`walkdir = \"1.0.7\"`]: #walkdir\n\n\u003c!-- stdx crate doc links --\u003e\n\n[d-bitflags]: https://docs.rs/bitflags/0.9.1/bitflags/\n[d-byteorder]: https://docs.rs/byteorder/1.1.0/byteorder/\n[d-chrono]: https://docs.rs/chrono/0.4.0/chrono/\n[d-clap]: https://docs.rs/clap/2.25.0/clap/\n[d-encoding_rs]: https://docs.rs/encoding_rs/0.6.11/encoding_rs/\n[d-error-chain]: https://docs.rs/error-chain/0.8.1/error_chain/\n[d-flate2]: https://docs.rs/flate2/0.2.19/flate2/\n[d-fnv]: https://docs.rs/fnv/1.0.5/fnv/\n[d-itertools]: https://docs.rs/itertools/0.6.0/itertools/\n[d-lazy_static]: https://docs.rs/lazy_static/0.2.8/lazy_static\n[d-libc]: https://docs.rs/libc/0.2.25/libc/\n[d-log]: https://docs.rs/log/0.3.8/log/\n[d-memmap]: https://docs.rs/memmap/0.5.2/memmap/\n[d-ndarray]: https://docs.rs/ndarray/0.9.1/ndarray/\n[d-num]: https://docs.rs/num/0.1.40/num/\n[d-num_cpus]: https://docs.rs/num_cpus/1.6.2/num_cpus/\n[d-rand]: https://docs.rs/rand/0.3.15/rand/\n[d-rayon]: https://docs.rs/rayon/0.8.2/rayon/\n[d-regex]: https://docs.rs/regex/0.2.2/regex/\n[d-reqwest]: https://docs.rs/reqwest/0.7.1/reqwest/\n[d-serde]: https://docs.rs/serde/1.0.10/serde/\n[d-serde_json]: https://docs.rs/serde_json/1.0.2/serde_json/\n[d-tar]: https://docs.rs/tar/0.4.23/tar/\n[d-tempdir]: https://docs.rs/tempdir/0.3.5/tempdir/\n[d-threadpool]: https://docs.rs/threadpool/1.4.0/threadpool/\n[d-toml]: https://docs.rs/toml/0.4.2/toml/\n[d-url]: https://docs.rs/url/1.5.1/url/\n[d-walkdir]: https://docs.rs/walkdir/1/walkdir/\n[d-semver]: https://docs.rs/semver/0.7.0/semver/\n\n\u003c!-- examples --\u003e\n\n[`examples/bitflags.rs`]: examples/bitflags.rs\n[`examples/byteorder.rs`]: examples/byteorder.rs\n[`examples/chrono.rs`]: examples/chrono.rs\n[`examples/clap.rs`]: examples/clap.rs\n[`examples/encoding_rs.rs`]: examples/encoding_rs.rs\n[`examples/error-chain.rs`]: examples/error-chain.rs\n[`examples/flate2.rs`]: examples/flate2.rs\n[`examples/fnv.rs`]: examples/fnv.rs\n[`examples/itertools.rs`]: examples/itertools.rs\n[`examples/lazy_static.rs`]: examples/lazy_static.rs\n[`examples/libc.rs`]: examples/libc.rs\n[`examples/log.rs`]: examples/log.rs\n[`examples/ndarray.rs`]: examples/ndarray.rs\n[`examples/num.rs`]: examples/num.rs\n[`examples/num_cpus.rs`]: examples/num_cpus.rs\n[`examples/rand.rs`]: examples/rand.rs\n[`examples/rayon.rs`]: examples/rayon.rs\n[`examples/regex.rs`]: examples/regex.rs\n[`examples/reqwest.rs`]: examples/reqwest.rs\n[`examples/serde.rs`]: examples/serde.rs\n[`examples/semver.rs`]: examples/semver.rs\n[`examples/json.rs`]: examples/json.rs\n[`examples/tar.rs`]: examples/tar.rs\n[`examples/tempdir.rs`]: examples/tempdir.rs\n[`examples/threadpool.rs`]: examples/threadpool.rs\n[`examples/toml.rs`]: examples/toml.rs\n[`examples/url.rs`]: examples/url.rs\n[`examples/walkdir.rs`]: examples/walkdir.rs\n\n\u003c!-- Supplemental crates --\u003e\n\n[`env_logger = \"0.4.3\"`]: https://docs.rs/env_logger/0.4.3/env_logger/\n[`serde_derive = \"1.0.10\"`]: https://docs.rs/serde_derive/1.0.10/serde_derive\n\n\u003c!-- Alternative crates --\u003e\n\n[`json`]: https://docs.rs/json\n[`log4rs`]: https://docs.rs/log4rs\n[`rustc-serialize`]: https://docs.rs/rustc-serialize\n[`slog`]: https://docs.rs/slog\n[`quick-error`]: https://docs.rs/quick-error\n[`docopt`]: https://docs.rs/docopt\n[`scoped_threadpool`]: https://docs.rs/scoped_threadpool\n\n\u003c!-- other links --\u003e\n\n[DEFLATE]: https://en.wikipedia.org/wiki/DEFLATE\n[error handling]: https://rust-lang.github.io/book/second-edition/ch09-00-error-handling.html\n['life before main']: https://isocpp.org/wiki/faq/ctors#static-init-order\n[fast]: http://blog.burntsushi.net/ripgrep/\n[flate2]: #flate2\n[JSON]: http://json.org/\n[Cargo.toml]: http://doc.crates.io/manifest.html\n[Servo]: https://servo.org\n[`filter_entry`]: https://docs.rs/walkdir/1.0/walkdir/trait.WalkDirIterator.html#method.filter_entry\n[\"hash flooding\"]: https://en.wikipedia.org/wiki/SipHash\n[`Iterator`]: https://doc.rust-lang.org/stable/std/iter/trait.Iterator.html\n[`batching`]: https://docs.rs/itertools/0.6/itertools/trait.Itertools.html#method.batching\n[`dedup`]: https://docs.rs/itertools/0.6/itertools/trait.Itertools.html#method.dedup\n[`group_by`]: https://docs.rs/itertools/0.6/itertools/trait.Itertools.html#method.group_by\n[`mend_slices`]: https://docs.rs/itertools/0.6/itertools/trait.Itertools.html#method.mend_slices\n[`merge`]: https://docs.rs/itertools/0.6/itertools/trait.Itertools.html#method.merge\n[`sorted`]: https://docs.rs/itertools/0.6/itertools/trait.Itertools.html#method.sorted\n[`join`]: https://docs.rs/itertools/0.6/itertools/trait.Itertools.html#method.join\n[`nix`]: https://docs.rs/nix\n[`winapi`]: https://docs.rs/winapi\n[memory-mapped I/O]: https://en.wikipedia.org/wiki/Memory-mapped_file\n[`mmap`]: https://en.wikipedia.org/wiki/mmap\n[`CreateFileMapping`]: https://msdn.microsoft.com/en-us/library/windows/desktop/aa366537(v=vs.85).aspx\n[`MapViewOfFile`]: https://msdn.microsoft.com/en-us/library/windows/desktop/aa366761(v=vs.85).aspx\n[`bitflags!`]: https://docs.rs/bitflags/0.9/bitflags/macro.bitflags.html\n[\"endianness\"]: https://en.wikipedia.org/wiki/Endianness\n[`RUST_LOG`]: https://docs.rs/env_logger/0.4/env_logger/#filtering-results\n[`error!`]: https://docs.rs/log/0.3/log/macro.error.html\n[`warn!`]: https://docs.rs/log/0.3/log/macro.warn.html\n[`info!`]: https://docs.rs/log/0.3/log/macro.info.html\n[`debug!`]: https://docs.rs/log/0.3/log/macro.debug.html\n[`env_logger`]: https://docs.rs/env_logger\n[hyper]: https://docs.rs/hyper\n[serde.rs]: https://serde.rs/\n[semver]: http://semver.org/\n","funding_links":[],"categories":["Rust","Resources","资源 Resources","资源"],"sub_categories":["Web programming","网络编程 Web programming","网页编程","web编程 Web programming"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbrson%2Fstdx","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbrson%2Fstdx","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbrson%2Fstdx/lists"}