Implement 'see also' sections. Use for HTTP crates

This commit is contained in:
Nico Burns 2022-11-08 12:52:13 +00:00
parent 4ca4ed0a88
commit eaaebeac77
3 changed files with 103 additions and 84 deletions

View file

@ -12,7 +12,7 @@
"purposes": [ "purposes": [
{ {
"name": "Random numbers", "name": "Random numbers",
"crates": [{ "recommendations": [{
"name": "rand", "name": "rand",
"notes": "De facto standard random number generation library split out from the standard library" "notes": "De facto standard random number generation library split out from the standard library"
}] }]
@ -20,7 +20,7 @@
{ {
"name": "Time & Date", "name": "Time & Date",
"notes": "Unfortunately there is no clear answer as to which is best between time and chrono.<br />Evaluate for yourself between these two, but be resassured that both are trusted and well-maintained.", "notes": "Unfortunately there is no clear answer as to which is best between time and chrono.<br />Evaluate for yourself between these two, but be resassured that both are trusted and well-maintained.",
"crates": [{ "recommendations": [{
"name": "time", "name": "time",
"notes": "A smaller, simpler library. Preferrable if covers your needs, but it's quite limited in what it provides." "notes": "A smaller, simpler library. Preferrable if covers your needs, but it's quite limited in what it provides."
}, { }, {
@ -31,14 +31,14 @@
{ {
"name": "Serialization (JSON, YAML, etc)", "name": "Serialization (JSON, YAML, etc)",
"notes": "See <a href=\"https://docs.rs/serde/latest/serde/#data-formats\">here</a> for supported formats.", "notes": "See <a href=\"https://docs.rs/serde/latest/serde/#data-formats\">here</a> for supported formats.",
"crates": [{ "recommendations": [{
"name": "serde", "name": "serde",
"notes": "De facto standard serialization library. Use in conjunction with sub-crates like serde_json for the specific format that you are using." "notes": "De facto standard serialization library. Use in conjunction with sub-crates like serde_json for the specific format that you are using."
}] }]
}, },
{ {
"name": "Regular Expressions", "name": "Regular Expressions",
"crates": [{ "recommendations": [{
"name": "regex", "name": "regex",
"notes": "De facto standard regex library. Very fast, but does not support fancier features such as backtracking." "notes": "De facto standard regex library. Very fast, but does not support fancier features such as backtracking."
}, },
@ -49,35 +49,35 @@
}, },
{ {
"name": "UUIDs", "name": "UUIDs",
"crates": [{ "recommendations": [{
"name": "uuid", "name": "uuid",
"notes": "Implements generating and parsing UUIDs and a number of utility functions" "notes": "Implements generating and parsing UUIDs and a number of utility functions"
}] }]
}, },
{ {
"name": "Temporary files", "name": "Temporary files",
"crates": [{ "recommendations": [{
"name": "tempfile", "name": "tempfile",
"notes": "Supports both temporary files and temporary directories" "notes": "Supports both temporary files and temporary directories"
}] }]
}, },
{ {
"name": "Gzip (de)compression", "name": "Gzip (de)compression",
"crates": [{ "recommendations": [{
"name": "flate2", "name": "flate2",
"notes": "Uses a pure-Rust implementation by default. Use feature flags to opt in to system zlib." "notes": "Uses a pure-Rust implementation by default. Use feature flags to opt in to system zlib."
}] }]
}, },
{ {
"name": "Insertion-ordered map", "name": "Insertion-ordered map",
"crates": [{ "recommendations": [{
"name": "indexmap", "name": "indexmap",
"notes": "A HashMap that seperately keeps track of insertion order and allows you to efficiently iterate over its elements in that order" "notes": "A HashMap that seperately keeps track of insertion order and allows you to efficiently iterate over its elements in that order"
}] }]
}, },
{ {
"name": "Stack-allocated arrays", "name": "Stack-allocated arrays",
"crates": [{ "recommendations": [{
"name": "arrayvec", "name": "arrayvec",
"notes": "Arrays that are ONLY stack-allocated with fixed capacity" "notes": "Arrays that are ONLY stack-allocated with fixed capacity"
}, { }, {
@ -90,7 +90,7 @@
}, },
{ {
"name": "HTTP Requests", "name": "HTTP Requests",
"crates": [{ "recommendations": [{
"name": "reqwest", "name": "reqwest",
"notes": "Full-fat HTTP client. Can be used in both synchronous and asynchronous code. Requires tokio runtime." "notes": "Full-fat HTTP client. Can be used in both synchronous and asynchronous code. Requires tokio runtime."
}, { }, {
@ -107,7 +107,7 @@
"purposes": [ "purposes": [
{ {
"name": "For applications", "name": "For applications",
"crates": [{ "recommendations": [{
"name": "anyhow", "name": "anyhow",
"notes": "Provides a boxed error type that can hold any error, and helpers for generating an application-level stack trace." "notes": "Provides a boxed error type that can hold any error, and helpers for generating an application-level stack trace."
}, { }, {
@ -117,7 +117,7 @@
}, },
{ {
"name": "For libraries", "name": "For libraries",
"crates": [{ "recommendations": [{
"name": "thiserror", "name": "thiserror",
"notes": "Helps with generating boilerplate for enum-style error types." "notes": "Helps with generating boilerplate for enum-style error types."
}] }]
@ -131,7 +131,7 @@
"purposes": [ "purposes": [
{ {
"name": "Text-based logging", "name": "Text-based logging",
"crates": [{ "recommendations": [{
"name": "tracing", "name": "tracing",
"notes": "Tracing is now the go-to crate for logging." "notes": "Tracing is now the go-to crate for logging."
}, { }, {
@ -141,7 +141,7 @@
}, },
{ {
"name": "Structured logging", "name": "Structured logging",
"crates": [{ "recommendations": [{
"name": "tracing", "name": "tracing",
"notes": "Tracing is now the go-to crate for logging." "notes": "Tracing is now the go-to crate for logging."
}, { }, {
@ -158,7 +158,7 @@
"purposes": [ "purposes": [
{ {
"name": "Lazy static variable initialization", "name": "Lazy static variable initialization",
"crates": [{ "recommendations": [{
"name": "once_cell", "name": "once_cell",
"notes": "Newer crate with more ergonomic API. On track to be incorporated into the standard library. Should be preferred for all new projects." "notes": "Newer crate with more ergonomic API. On track to be incorporated into the standard library. Should be preferred for all new projects."
}, { }, {
@ -168,14 +168,14 @@
}, },
{ {
"name": "Iterator helpers", "name": "Iterator helpers",
"crates": [{ "recommendations": [{
"name": "itertools", "name": "itertools",
"notes": "A bunch of useful methods on iterators that aren't in the stdlib" "notes": "A bunch of useful methods on iterators that aren't in the stdlib"
}] }]
}, },
{ {
"name": "Macro helpers", "name": "Macro helpers",
"crates": [{ "recommendations": [{
"name": "syn", "name": "syn",
"notes": "Parse rust source code" "notes": "Parse rust source code"
}, { }, {
@ -188,27 +188,27 @@
}, },
{ {
"name": "Abstracting over different number types", "name": "Abstracting over different number types",
"crates": [{ "recommendations": [{
"name": "num", "name": "num",
"notes": "Traits like Number, Add, etc that allow you write functions that are generic over the specific numeric type" "notes": "Traits like Number, Add, etc that allow you write functions that are generic over the specific numeric type"
}] }]
}, },
{ {
"name": "Endian conversion", "name": "Endian conversion",
"crates": [{ "recommendations": [{
"name": "byteorder", "name": "byteorder",
"notes": "Utility functions to convert between different endianness or read/write data with a specific endianness" "notes": "Utility functions to convert between different endianness or read/write data with a specific endianness"
}] }]
}, },
{ {
"name": "Safe type casts", "name": "Safe type casts",
"crates": [{ "recommendations": [{
"name": "bytemuck" "name": "bytemuck"
}] }]
}, },
{ {
"name": "Bitflags", "name": "Bitflags",
"crates": [{ "recommendations": [{
"name": "bitflags", "name": "bitflags",
"notes": "Strongly typed bitflag types" "notes": "Strongly typed bitflag types"
}] }]
@ -222,21 +222,21 @@
"purposes": [ "purposes": [
{ {
"name": "Memory mapping files", "name": "Memory mapping files",
"crates": [{ "recommendations": [{
"name": "memmap2", "name": "memmap2",
"notes": "The older memmap crate is unmaintained." "notes": "The older memmap crate is unmaintained."
}] }]
}, },
{ {
"name": "Libc", "name": "Libc",
"crates": [{ "recommendations": [{
"name": "libc", "name": "libc",
"notes": "Bindings for directly calling libc functions." "notes": "Bindings for directly calling libc functions."
}] }]
}, },
{ {
"name": "Windows (OS)", "name": "Windows (OS)",
"crates": [{ "recommendations": [{
"name": "windows", "name": "windows",
"notes": "The official Microsoft-provided crate for interacting with windows APIs" "notes": "The official Microsoft-provided crate for interacting with windows APIs"
}, { }, {
@ -257,7 +257,7 @@
{ {
"name": "Password Hashing", "name": "Password Hashing",
"notes": "For more algorithms, see <a href=\"https://github.com/RustCrypto/password-hashes#rustcrypto-password-hashes\">Rust Crypto Password Hashes</a>.", "notes": "For more algorithms, see <a href=\"https://github.com/RustCrypto/password-hashes#rustcrypto-password-hashes\">Rust Crypto Password Hashes</a>.",
"crates": [ "recommendations": [
{ "name": "argon2" }, { "name": "argon2" },
{ "name": "scrypt" }, { "name": "scrypt" },
{ "name": "bcrypt" } { "name": "bcrypt" }
@ -266,7 +266,7 @@
{ {
"name": "General Purpose Hashing", "name": "General Purpose Hashing",
"notes": "For more algorithms, see <a href=\"https://github.com/RustCrypto/hashes#rustcrypto-hashes\">Rust Crypto Hashes</a>.", "notes": "For more algorithms, see <a href=\"https://github.com/RustCrypto/hashes#rustcrypto-hashes\">Rust Crypto Hashes</a>.",
"crates": [ "recommendations": [
{ "name": "sha2" }, { "name": "sha2" },
{ "name": "sha1" }, { "name": "sha1" },
{ "name": "md-5" } { "name": "md-5" }
@ -275,7 +275,7 @@
{ {
"name": "AEAD Encryption", "name": "AEAD Encryption",
"notes": "For more algorithms, see <a href=\"https://github.com/RustCrypto/AEADs#rustcrypto-authenticated-encryption-with-associated-data-aead-algorithms\">Rust Crypto AEADs</a>.", "notes": "For more algorithms, see <a href=\"https://github.com/RustCrypto/AEADs#rustcrypto-authenticated-encryption-with-associated-data-aead-algorithms\">Rust Crypto AEADs</a>.",
"crates": [ "recommendations": [
{ "name": "aes-gcm-siv" }, { "name": "aes-gcm-siv" },
{ "name": "aes-gcm" }, { "name": "aes-gcm" },
{ "name": "chacha20poly1305" } { "name": "chacha20poly1305" }
@ -283,14 +283,14 @@
}, },
{ {
"name": "RSA", "name": "RSA",
"crates": [ "recommendations": [
{ "name": "rsa" } { "name": "rsa" }
] ]
}, },
{ {
"name": "Digital Signatures", "name": "Digital Signatures",
"notes": "For more algorithms, see <a href=\"https://github.com/RustCrypto/signatures#rustcrypto-signatures--\">Rust Crypto Signatures</a>.", "notes": "For more algorithms, see <a href=\"https://github.com/RustCrypto/signatures#rustcrypto-signatures--\">Rust Crypto Signatures</a>.",
"crates": [ "recommendations": [
{ "name": "ed25519", "notes": "Use in conjunction with the ed25519-dalek crate." }, { "name": "ed25519", "notes": "Use in conjunction with the ed25519-dalek crate." },
{ "name": "ecdsa" }, { "name": "ecdsa" },
{ "name": "dsa" } { "name": "dsa" }
@ -299,7 +299,7 @@
{ {
"name": "Certificate Formats", "name": "Certificate Formats",
"notes": "For more formats, see <a href=\"https://github.com/RustCrypto/formats#rustcrypto-formats--\">Rust Crypto Formats</a>.", "notes": "For more formats, see <a href=\"https://github.com/RustCrypto/formats#rustcrypto-formats--\">Rust Crypto Formats</a>.",
"crates": [ "recommendations": [
{ "name": "der" }, { "name": "der" },
{ "name": "pemrfc7468" }, { "name": "pemrfc7468" },
{ "name": "pkcs8" }, { "name": "pkcs8" },
@ -308,7 +308,7 @@
}, },
{ {
"name": "TLS / SSL", "name": "TLS / SSL",
"crates": [{ "recommendations": [{
"name": "rustls", "name": "rustls",
"notes": "A portable pure-rust high-level implementation of TLS. Implements TLS 1.2 and higher." "notes": "A portable pure-rust high-level implementation of TLS. Implements TLS 1.2 and higher."
}, { }, {
@ -324,7 +324,7 @@
}, },
{ {
"name": "Utilities", "name": "Utilities",
"crates": [{ "recommendations": [{
"name": "subtle", "name": "subtle",
"notes": "Utilities for writing constant-time algorithms" "notes": "Utilities for writing constant-time algorithms"
}, },
@ -348,7 +348,7 @@
"purposes": [ "purposes": [
{ {
"name": "General purpose", "name": "General purpose",
"crates": [{ "recommendations": [{
"name": "tokio", "name": "tokio",
"notes": "The oldest async runtime in the Rust ecosystem and still the most widely supported. Recommended for new projects." "notes": "The oldest async runtime in the Rust ecosystem and still the most widely supported. Recommended for new projects."
}, { }, {
@ -358,7 +358,7 @@
}, },
{ {
"name": "io_uring", "name": "io_uring",
"crates": [{ "recommendations": [{
"name": "glommio", "name": "glommio",
"notes": "Use if you need io_uring support. Still somewhat experimental but rapidly maturing." "notes": "Use if you need io_uring support. Still somewhat experimental but rapidly maturing."
}] }]
@ -372,42 +372,44 @@
"purposes": [ "purposes": [
{ {
"name": "Types & Interfaces", "name": "Types & Interfaces",
"crates": [{ "recommendations": [{
"name": "http", "name": "http",
"notes": "The `http` crate doesn't actually contain an HTTP implementation. Just types and interfaces to help interoperability." "notes": "The `http` crate doesn't actually contain an HTTP implementation. Just types and interfaces to help interoperability."
}] }]
}, },
{ {
"name": "Low-level HTTP Implementation", "name": "Low-level HTTP Implementation",
"crates": [{ "recommendations": [{
"name": "hyper", "name": "hyper",
"notes": "A low-level HTTP implementation (both client and server). Implements HTTP 1, 2, and 3. Requires the tokio async runtime." "notes": "A low-level HTTP implementation (both client and server). Implements HTTP 1, 2, and 3. Requires the tokio async runtime."
}] }]
}, },
{ {
"name": "HTTP Client", "name": "HTTP Client",
"crates": [{ "recommendations": [{
"name": "reqwest", "name": "reqwest",
"notes": "Full-fat HTTP client. Can be used in both synchronous and asynchronous code. Requires tokio runtime." "notes": "Full-fat HTTP client. Can be used in both synchronous and asynchronous code. Requires tokio runtime."
},{
"name": "surf",
"notes": "Client that uses the async-std runtime rather than the tokio runtime."
}, { }, {
"name": "ureq", "name": "ureq",
"notes": "Minimal synchronous HTTP client focussed on simplicity and minimising dependencies." "notes": "Minimal synchronous HTTP client focussed on simplicity and minimising dependencies."
}],
"see_also": [{
"name": "surf",
"notes": "Client that uses the async-std runtime rather than the tokio runtime. Not well maintained."
}] }]
}, },
{ {
"name": "HTTP Server", "name": "HTTP Server",
"crates": [{ "recommendations": [{
"name": "axum", "name": "axum",
"notes": "A minimal and ergonomic framework. An official part of the tokio project. Recommend for most new projects." "notes": "A minimal and ergonomic framework. An official part of the tokio project. Recommend for most new projects."
}, {
"name": "tide",
"notes": "Similar to Axum, but based on async-std rather than tokio"
}, { }, {
"name": "actix-web", "name": "actix-web",
"notes": "A performance focussed framework. All Rust frameworks are fast, but choose actix-web if you need the absolutely maximum performance." "notes": "A performance focussed framework. All Rust frameworks are fast, but choose actix-web if you need the absolutely maximum performance."
}],
"see_also": [{
"name": "rocket",
"notes": "Focussed on ergonomics. This is a solid framework, however development has stalled. Avoid for new projects."
}, { }, {
"name": "poem", "name": "poem",
"notes": "Automatically generates OpenAPI defintions." "notes": "Automatically generates OpenAPI defintions."
@ -415,13 +417,13 @@
"name": "warp", "name": "warp",
"notes": "Very similar to axum but with a quirkier API. This is a solid framework, but you should probably prefer Axum unless you particular like the API" "notes": "Very similar to axum but with a quirkier API. This is a solid framework, but you should probably prefer Axum unless you particular like the API"
}, { }, {
"name": "rocket", "name": "tide",
"notes": "Focussed on ergonomics. This is a solid framework, however development has stalled. Avoid for new projects." "notes": "Similar to Axum, but based on async-std rather than tokio"
}] }]
}, },
{ {
"name": "GraphQL Server", "name": "GraphQL Server",
"crates": [{ "recommendations": [{
"name": "async-graphql", "name": "async-graphql",
"notes": "A high-performance graphql server library that's fully specification compliant. Integrates with actix-web, axum, poem, rocket, tide, warp." "notes": "A high-performance graphql server library that's fully specification compliant. Integrates with actix-web, axum, poem, rocket, tide, warp."
}] }]
@ -435,14 +437,14 @@
"purposes": [ "purposes": [
{ {
"name": "Low-level", "name": "Low-level",
"crates": [{ "recommendations": [{
"name": "tungstenite-rs", "name": "tungstenite-rs",
"notes": "Low-level crate that others build on" "notes": "Low-level crate that others build on"
}] }]
}, },
{ {
"name": "General Purpose", "name": "General Purpose",
"crates": [{ "recommendations": [{
"name": "tokio-tungstenite", "name": "tokio-tungstenite",
"notes": "If you are using the tokio executor" "notes": "If you are using the tokio executor"
}, { }, {
@ -458,7 +460,7 @@
"purposes": [ "purposes": [
{ {
"name": "General Purpose", "name": "General Purpose",
"crates": [{ "recommendations": [{
"name": "tonic", "name": "tonic",
"notes": "gRPC over HTTP/2 with full support for asynchronous code. Works with tokio" "notes": "gRPC over HTTP/2 with full support for asynchronous code. Works with tokio"
}] }]
@ -477,14 +479,14 @@
"purposes": [ "purposes": [
{ {
"name": "Multi Database", "name": "Multi Database",
"crates": [{ "recommendations": [{
"name": "sqlx", "name": "sqlx",
"notes": "Works with Postgres, MySQL, SQLite, and MS SQL.<br />Supports compile time checking of queries. Async: supports both tokio and async-std." "notes": "Works with Postgres, MySQL, SQLite, and MS SQL.<br />Supports compile time checking of queries. Async: supports both tokio and async-std."
}] }]
}, },
{ {
"name": "ORMs", "name": "ORMs",
"crates": [{ "recommendations": [{
"name": "sea-orm", "name": "sea-orm",
"notes": "Recommended. Built on top of sqlx. There is also a related sea-query crate that provides a query builder without full ORM functionality." "notes": "Recommended. Built on top of sqlx. There is also a related sea-query crate that provides a query builder without full ORM functionality."
}, { }, {
@ -494,7 +496,7 @@
}, },
{ {
"name": "Postgres", "name": "Postgres",
"crates": [{ "recommendations": [{
"name": "sqlx" "name": "sqlx"
}, { }, {
"name": "tokio-postgres", "name": "tokio-postgres",
@ -503,7 +505,7 @@
}, },
{ {
"name": "MySQL", "name": "MySQL",
"crates": [{ "recommendations": [{
"name": "sqlx" "name": "sqlx"
}, { }, {
"name": "mysql_async", "name": "mysql_async",
@ -512,7 +514,7 @@
}, },
{ {
"name": "SQLite", "name": "SQLite",
"crates": [{ "recommendations": [{
"name": "sqlx" "name": "sqlx"
}, { }, {
"name": "rustqlite", "name": "rustqlite",
@ -521,7 +523,7 @@
}, },
{ {
"name": "MS SQL", "name": "MS SQL",
"crates": [{ "recommendations": [{
"name": "sqlx" "name": "sqlx"
}, { }, {
"name": "tiberius", "name": "tiberius",
@ -530,7 +532,7 @@
}, },
{ {
"name": "Oracle", "name": "Oracle",
"crates": [{ "recommendations": [{
"name": "oracle", "name": "oracle",
"notes": "Rust bindings to ODPI-C" "notes": "Rust bindings to ODPI-C"
}] }]
@ -543,13 +545,13 @@
"purposes": [ "purposes": [
{ {
"name": "Redis", "name": "Redis",
"crates": [{ "recommendations": [{
"name": "redis" "name": "redis"
}] }]
}, },
{ {
"name": "MongoDB", "name": "MongoDB",
"crates": [{ "recommendations": [{
"name": "mongodb" "name": "mongodb"
}] }]
} }
@ -568,14 +570,14 @@
"purposes": [ "purposes": [
{ {
"name": "Fully-featured", "name": "Fully-featured",
"crates": [{ "recommendations": [{
"name": "clap", "name": "clap",
"notes": "Ergonomic, supports everything, and is fast at runtime. However compile times can be slow" "notes": "Ergonomic, supports everything, and is fast at runtime. However compile times can be slow"
}] }]
}, },
{ {
"name": "Minimal", "name": "Minimal",
"crates": [{ "recommendations": [{
"name": "lexopt", "name": "lexopt",
"notes": "Fast compile times, fast runtime, pedantic about correctness. API is less ergonomic" "notes": "Fast compile times, fast runtime, pedantic about correctness. API is less ergonomic"
}, { }, {
@ -592,14 +594,14 @@
"purposes": [ "purposes": [
{ {
"name": "Globbing", "name": "Globbing",
"crates": [{ "recommendations": [{
"name": "globset", "name": "globset",
"notes": "High-performance globbing that allows multiple globs to be evaluated at once" "notes": "High-performance globbing that allows multiple globs to be evaluated at once"
}] }]
}, },
{ {
"name": "Directory walking", "name": "Directory walking",
"crates": [{ "recommendations": [{
"name": "walkdir", "name": "walkdir",
"notes": "Basic recursive filesystem walking." "notes": "Basic recursive filesystem walking."
}, { }, {
@ -609,14 +611,14 @@
}, },
{ {
"name": "Filesystem helpers", "name": "Filesystem helpers",
"crates": [{ "recommendations": [{
"name": "fs_extra", "name": "fs_extra",
"notes": "Recursively move, copy, and delete the files in a directory" "notes": "Recursively move, copy, and delete the files in a directory"
}] }]
}, },
{ {
"name": "File watching", "name": "File watching",
"crates": [{ "recommendations": [{
"name": "notify", "name": "notify",
"notes": "Watch files or directories and execute a function when they change" "notes": "Watch files or directories and execute a function when they change"
}] }]
@ -630,21 +632,21 @@
"purposes": [ "purposes": [
{ {
"name": "Coloured Output", "name": "Coloured Output",
"crates": [{ "recommendations": [{
"name": "termcolor", "name": "termcolor",
"notes": "Cross-platform terminal colour output" "notes": "Cross-platform terminal colour output"
}] }]
}, },
{ {
"name": "Progress indicators", "name": "Progress indicators",
"crates": [{ "recommendations": [{
"name": "indicatif", "name": "indicatif",
"notes": "Progress bars and spinners" "notes": "Progress bars and spinners"
}] }]
}, },
{ {
"name": "Full TUI library", "name": "Full TUI library",
"crates": [{ "recommendations": [{
"name": "crossterm", "name": "crossterm",
"notes": "Cross-platform terminal rendering and event handling" "notes": "Cross-platform terminal rendering and event handling"
}] }]
@ -663,14 +665,14 @@
"purposes": [ "purposes": [
{ {
"name": "Mutex", "name": "Mutex",
"crates": [{ "recommendations": [{
"name": "parking_lot", "name": "parking_lot",
"notes": "std::mutex also works fine. But Parking Lot is faster." "notes": "std::mutex also works fine. But Parking Lot is faster."
}] }]
}, },
{ {
"name": "Atomic pointer swapping", "name": "Atomic pointer swapping",
"crates": [{ "recommendations": [{
"name": "arc_swap", "name": "arc_swap",
"notes": "Useful for sharing data that has many readers but few writers" "notes": "Useful for sharing data that has many readers but few writers"
}] }]
@ -678,7 +680,7 @@
{ {
"name": "Concurrent HashMap", "name": "Concurrent HashMap",
"notes": "See <a target=\"_blank\" href=\"https://github.com/xacrimon/conc-map-bench\">conc-map-bench</a> for comparative benchmarks of concurrent HashMaps.", "notes": "See <a target=\"_blank\" href=\"https://github.com/xacrimon/conc-map-bench\">conc-map-bench</a> for comparative benchmarks of concurrent HashMaps.",
"crates": [{ "recommendations": [{
"name": "dashmap", "name": "dashmap",
"notes": "The fastest for general purpose workloads" "notes": "The fastest for general purpose workloads"
}, { }, {
@ -689,7 +691,7 @@
{ {
"name": "Channels", "name": "Channels",
"notes": "See <a href=\"https://docs.rs/tokio/latest/tokio/sync/mpsc/index.html#communicating-between-sync-and-async-code\">communicating-between-sync-and-async-code</a> for notes on when to use async-specific channels vs general purpose channels.", "notes": "See <a href=\"https://docs.rs/tokio/latest/tokio/sync/mpsc/index.html#communicating-between-sync-and-async-code\">communicating-between-sync-and-async-code</a> for notes on when to use async-specific channels vs general purpose channels.",
"crates": [ "recommendations": [
{ {
"name": "crossbeam_channel", "name": "crossbeam_channel",
"notes": "The absolute fastest channel implementation available. Implements Go-like 'select' feature." "notes": "The absolute fastest channel implementation available. Implements Go-like 'select' feature."
@ -704,7 +706,7 @@
}, },
{ {
"name": "Parallel computation", "name": "Parallel computation",
"crates": [ "recommendations": [
{ {
"name": "rayon", "name": "rayon",
"notes": "Convert sequential computation into parallel computation with one call - `par_iter` instead of `iter`" "notes": "Convert sequential computation into parallel computation with one call - `par_iter` instead of `iter`"

View file

@ -60,7 +60,8 @@ struct Crate {
struct Purpose { struct Purpose {
name: String, name: String,
notes: Option<String>, notes: Option<String>,
crates: Vec<Crate>, recommendations: Option<Vec<Crate>>,
see_also: Option<Vec<Crate>>,
} }
#[derive(Debug, Clone, Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]

View file

@ -12,9 +12,9 @@
</thead> </thead>
{% for purpose in purposes %} {% for purpose in purposes %}
<tbody> <tbody>
<!--{% for crate in purpose.crates %} <!--{% for crate in purpose.recommendations %}
<tr> <tr>
{% if loop.index0 == 0 %}<td rowspan="{{ purpose.crates | length }} ">{{ purpose.name }}</td>{% endif %} {% if loop.index0 == 0 %}<td rowspan="{{ purpose.recommendations | length }} ">{{ purpose.name }}</td>{% endif %}
<td><a href="https://docs.rs/{{ crate.name }}">{{ crate.name }}</a></td> <td><a href="https://docs.rs/{{ crate.name }}">{{ crate.name }}</a></td>
<td class="crate-notes">{{ crate.notes | safe }}</td> <td class="crate-notes">{{ crate.notes | safe }}</td>
</tr> </tr>
@ -26,15 +26,31 @@
{% if purpose.notes %} {% if purpose.notes %}
<p style="margin: 3px 6px 6px 6px;font-style: italic;color: #666">{{ purpose.notes | safe }}</p> <p style="margin: 3px 6px 6px 6px;font-style: italic;color: #666">{{ purpose.notes | safe }}</p>
{% endif %} {% endif %}
{% for crate in purpose.crates %}
<p style="margin: 3px 6px;max-width: 600px"> {% for crate in purpose.recommendations %}
<b><a href="{% if crate.link %}{{ crate.link }}{% else %}https://lib.rs/{{ crate.name }}{% endif %}">{{ crate.name }}</a></b>{% if not crate.link %} <p style="margin: 3px 6px;max-width: 600px">
<a style="margin-left: 3px;opacity: 0.7;color: #333;text-decoration: none" href="https://docs.rs/{{ crate.name }}"> [docs]</a> <b><a href="{% if crate.link %}{{ crate.link }}{% else %}https://lib.rs/{{ crate.name }}{% endif %}">{{ crate.name }}</a></b>{% if not crate.link %}
{% endif %} <a style="margin-left: 3px;opacity: 0.7;color: #333;text-decoration: none" href="https://docs.rs/{{ crate.name }}"> [docs]</a>
<br /> {% endif %}
{% if crate.notes %}{{ crate.notes | safe }}{% endif %} <br />
</p> {% if crate.notes %}{{ crate.notes | safe }}{% endif %}
</p>
{% endfor %} {% endfor %}
{% if purpose.see_also %}
<details style="margin-top: 6px">
<summary style="cursor: pointer"><b><i>See also</i></b> <span style="color: #999">(click to open)</span></summary>
{% for crate in purpose.see_also %}
<p style="margin: 3px 6px;max-width: 600px">
<b><a href="{% if crate.link %}{{ crate.link }}{% else %}https://lib.rs/{{ crate.name }}{% endif %}">{{ crate.name }}</a></b>{% if not crate.link %}
<a style="margin-left: 3px;opacity: 0.7;color: #333;text-decoration: none" href="https://docs.rs/{{ crate.name }}"> [docs]</a>
{% endif %}
<br />
{% if crate.notes %}{{ crate.notes | safe }}{% endif %}
</p>
{% endfor %}
</details>
{% endif %}
<!-- </ul> --> <!-- </ul> -->
</td> </td>
</tr> </tr>