Add integration tests

This patch adds an integration test suite using the insta crate for
snapshot testing.  The test suite is tested for all supported Rust
versions and should always succeed for the MSRV (currently 1.40.0) and
the current stable Rust version.

However there are some minor changes in the configuration format between
Rust versions, so tests that don’t work on all supported Rust versions
are marked with the ignore attribute.  But even the ignored tests should
work on the stable Rust release.
This commit is contained in:
Robin Krahl 2020-07-27 14:49:51 +02:00
parent 17e407d6b1
commit 1a518d7509
No known key found for this signature in database
GPG Key ID: 8E9B0870524F69D8
28 changed files with 2439 additions and 3 deletions

View File

@ -29,6 +29,7 @@ tasks:
cd rusty-man
cargo doc
cargo test
cargo test -- --ignored
- clippy: |
cd rusty-man
cargo clippy -- -D warnings

21
.reuse/dep5 Normal file
View File

@ -0,0 +1,21 @@
Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
Upstream-Name: rusty-man
Upstream-Contact: Robin Krahl <robin.krahl@ireas.org>
Source: https://sr.ht/~ireas/rusty-man
Files: tests/snapshots/*_anyhow*
Copyright: 2020 Robin Krahl <robin.krahl@ireas.org>
Copyright: 2019-2020 David Tolnay <dtolnay@gmail.com>
License: MIT
Files: tests/snapshots/*_log*
Copyright: 2020 Robin Krahl <robin.krahl@ireas.org>
Copyright: 2014 The Rust Project Developers
License: MIT
Files: tests/snapshots/*_rand_core*
Copyright: 2020 Robin Krahl <robin.krahl@ireas.org>
Copyright: 2014 The Rust Project Developers
Copyright: 2018 Developers of the Rand project
License: MIT

View File

@ -20,6 +20,7 @@ SPDX-License-Identifier: MIT
options.
- Add the `--config-file [file]` option to set a custom configuration file.
- Improve line break rendering when displaying code.
- Add integration test suite.
## v0.1.3 (2020-07-28)

View File

@ -51,9 +51,15 @@ Please submit patches by sending a mail to the mailing list
## Testing and checking the code
- rusty-man currently has a very small test suite. You can execute it using
`cargo test`, but make sure to generate rusty-mans documentation with `cargo
doc` before running the tests!
- rusty-man currently has very few unit tests. You can execute them using
`cargo test --bins`, but make sure to generate rusty-mans documentation with
`cargo doc` before running the tests!
- rusty-man has an integration test suite that uses [`insta`][] for snapshot
testing. The test suite takes care of generating the required documentation
so you dont have to run `cargo doc` manually. Use `cargo test` to execute
the tests that should work on all supported Rust versions. Use `cargo test
-- --ignored` to run the tests that only work with the latest stable Rust
version.
- Use `cargo fmt` for code formatting.
- Fix all warnings and errors reported by `clippy`.
@ -69,3 +75,4 @@ Please submit patches by sending a mail to the mailing list
[`git request-pull`]: https://git-scm.com/docs/git-request-pull
[guide]: https://git-send-email.io
[contact me]: mailto:robin.krahl@ireas.org
[`insta`]: https://lib.rs/crates/insta

172
Cargo.lock generated
View File

@ -25,6 +25,18 @@ name = "arc-swap"
version = "0.4.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "assert_cmd"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"doc-comment 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
"predicates 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
"predicates-core 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"predicates-tree 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"wait-timeout 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "autocfg"
version = "1.0.0"
@ -104,6 +116,19 @@ dependencies = [
"bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "console"
version = "0.11.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"encode_unicode 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.72 (registry+https://github.com/rust-lang/crates.io-index)",
"terminal_size 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)",
"termios 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "crc32fast"
version = "1.2.0"
@ -170,6 +195,16 @@ dependencies = [
"syn 1.0.34 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "difference"
version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "doc-comment"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "dtoa"
version = "0.4.6"
@ -183,6 +218,11 @@ dependencies = [
"dtoa 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "encode_unicode"
version = "0.3.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "env_logger"
version = "0.7.1"
@ -312,6 +352,19 @@ dependencies = [
"hashbrown 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "insta"
version = "0.16.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"console 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)",
"difference 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.114 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_json 1.0.56 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_yaml 0.8.13 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "itoa"
version = "0.4.6"
@ -351,6 +404,11 @@ dependencies = [
"safemem 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "linked-hash-map"
version = "0.5.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "lock_api"
version = "0.3.4"
@ -602,6 +660,29 @@ name = "precomputed-hash"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "predicates"
version = "1.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"difference 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"predicates-core 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "predicates-core"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "predicates-tree"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"predicates-core 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"treeline 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "proc-macro-error"
version = "1.0.3"
@ -703,6 +784,14 @@ name = "regex-syntax"
version = "0.6.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "remove_dir_all"
version = "0.5.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"winapi 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "rustc-demangle"
version = "0.1.16"
@ -713,9 +802,11 @@ name = "rusty-man"
version = "0.1.3"
dependencies = [
"anyhow 1.0.31 (registry+https://github.com/rust-lang/crates.io-index)",
"assert_cmd 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
"crossterm 0.17.7 (registry+https://github.com/rust-lang/crates.io-index)",
"env_logger 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
"html2text 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)",
"insta 0.16.1 (registry+https://github.com/rust-lang/crates.io-index)",
"kuchiki 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)",
"markup5ever 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
@ -726,6 +817,7 @@ dependencies = [
"serde_tuple 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
"structopt 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)",
"syntect 4.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"toml 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)",
"xdg 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
@ -829,6 +921,17 @@ dependencies = [
"syn 1.0.34 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "serde_yaml"
version = "0.8.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"dtoa 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
"linked-hash-map 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.114 (registry+https://github.com/rust-lang/crates.io-index)",
"yaml-rust 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "servo_arc"
version = "0.1.1"
@ -968,6 +1071,19 @@ dependencies = [
"walkdir 2.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "tempfile"
version = "3.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.72 (registry+https://github.com/rust-lang/crates.io-index)",
"rand 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)",
"redox_syscall 0.1.57 (registry+https://github.com/rust-lang/crates.io-index)",
"remove_dir_all 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "tendril"
version = "0.4.1"
@ -978,6 +1094,23 @@ dependencies = [
"utf-8 0.7.5 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "terminal_size"
version = "0.1.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"libc 0.2.72 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "termios"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"libc 0.2.72 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "textwrap"
version = "0.11.0"
@ -1008,6 +1141,11 @@ dependencies = [
"serde 1.0.114 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "treeline"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "unicode-segmentation"
version = "1.6.0"
@ -1033,6 +1171,14 @@ name = "version_check"
version = "0.9.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "wait-timeout"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"libc 0.2.72 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "walkdir"
version = "2.3.1"
@ -1096,11 +1242,20 @@ dependencies = [
"time 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "yaml-rust"
version = "0.4.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"linked-hash-map 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)",
]
[metadata]
"checksum addr2line 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1b6a2d3371669ab3ca9797670853d61402b03d0b4b9ebf33d677dfa720203072"
"checksum adler 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ee2a4ec343196209d6594e19543ae87a39f96d5534d7174822a3ad825dd6ed7e"
"checksum anyhow 1.0.31 (registry+https://github.com/rust-lang/crates.io-index)" = "85bb70cc08ec97ca5450e6eba421deeea5f172c0fc61f78b5357b2a8e8be195f"
"checksum arc-swap 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)" = "4d25d88fd6b8041580a654f9d0c581a047baee2b3efee13275f2fc392fc75034"
"checksum assert_cmd 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c88b9ca26f9c16ec830350d309397e74ee9abdfd8eb1f71cb6ecc71a3fc818da"
"checksum autocfg 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f8aac770f1885fd7e387acedd76065302551364496e46b3dd00860b2f8359b9d"
"checksum backtrace 0.3.50 (registry+https://github.com/rust-lang/crates.io-index)" = "46254cf2fdcdf1badb5934448c1bcbe046a56537b3987d96c51a7afc5d03f293"
"checksum base64 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3441f0f7b02788e948e47f457ca01f1d7e6d92c693bc132c22b087d3141c03ff"
@ -1112,14 +1267,18 @@ dependencies = [
"checksum chrono 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)" = "c74d84029116787153e02106bf53e66828452a4b325cc8652b788b5967c0a0b6"
"checksum clap 2.33.1 (registry+https://github.com/rust-lang/crates.io-index)" = "bdfa80d47f954d53a35a64987ca1422f495b8d6483c0fe9f7117b36c2a792129"
"checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f"
"checksum console 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8c0994e656bba7b922d8dd1245db90672ffb701e684e45be58f20719d69abc5a"
"checksum crc32fast 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ba125de2af0df55319f41944744ad91c71113bf74a4646efff39afe1f6842db1"
"checksum crossterm 0.17.7 (registry+https://github.com/rust-lang/crates.io-index)" = "6f4919d60f26ae233e14233cc39746c8c8bb8cd7b05840ace83604917b51b6c7"
"checksum crossterm_winapi 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "057b7146d02fb50175fd7dbe5158f6097f33d02831f43b4ee8ae4ddf67b68f5c"
"checksum cssparser 0.27.2 (registry+https://github.com/rust-lang/crates.io-index)" = "754b69d351cdc2d8ee09ae203db831e005560fc6030da058f86ad60c92a9cb0a"
"checksum cssparser-macros 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "dfae75de57f2b2e85e8768c3ea840fd159c8f33e2b6522c7835b7abac81be16e"
"checksum derive_more 0.99.9 (registry+https://github.com/rust-lang/crates.io-index)" = "298998b1cf6b5b2c8a7b023dfd45821825ce3ba8a8af55c921a0e734e4653f76"
"checksum difference 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "524cbf6897b527295dff137cec09ecf3a05f4fddffd7dfcd1585403449e74198"
"checksum doc-comment 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10"
"checksum dtoa 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "134951f4028bdadb9b84baf4232681efbf277da25144b9b0ad65df75946c422b"
"checksum dtoa-short 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "59020b8513b76630c49d918c33db9f4c91638e7d3404a28084083b87e33f76f2"
"checksum encode_unicode 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f"
"checksum env_logger 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "44533bbbb3bb3c1fa17d9f2e4e38bbbaf8396ba82193c4cb1b6445d711445d36"
"checksum errno 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "6eab5ee3df98a279d9b316b1af6ac95422127b1290317e6d18c1743c99418b01"
"checksum errno-dragonfly 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "14ca354e36190500e1e1fb267c647932382b54053c50b14970856c0b00a35067"
@ -1135,12 +1294,14 @@ dependencies = [
"checksum html2text 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "95797be56798f96288153e94dadaef204266254e66f4cbc1046fe03d35a14e6b"
"checksum html5ever 0.25.1 (registry+https://github.com/rust-lang/crates.io-index)" = "aafcf38a1a36118242d29b92e1b08ef84e67e4a5ed06e0a80be20e6a32bfed6b"
"checksum indexmap 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "86b45e59b16c76b11bf9738fd5d38879d3bd28ad292d7b313608becb17ae2df9"
"checksum insta 0.16.1 (registry+https://github.com/rust-lang/crates.io-index)" = "617e921abc813f96a3b00958c079e7bf1e2db998f8a04f1546dd967373a418ee"
"checksum itoa 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "dc6f3ad7b9d11a0c00842ff8de1b60ee58661048eb8049ed33c73594f359d7e6"
"checksum kuchiki 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1beeffc5ae5ab0def2cb85e26063a8e6b4f579b0adec3805bf87472086948956"
"checksum lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
"checksum lazycell 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b294d6fa9ee409a054354afc4352b0b9ef7ca222c69b8812cbea9e7d2bf3783f"
"checksum libc 0.2.72 (registry+https://github.com/rust-lang/crates.io-index)" = "a9f8082297d534141b30c8d39e9b1773713ab50fdbe4ff30f750d063b3bfd701"
"checksum line-wrap 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f30344350a2a51da54c1d53be93fade8a237e545dbcc4bdbe635413f2117cab9"
"checksum linked-hash-map 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8dd5a6d5999d9907cda8ed67bbd137d3af8085216c2ac62de5be860bd41f304a"
"checksum lock_api 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "c4da24a77a3d8a6d4862d95f72e6fdb9c09a643ecdb402d754004a557f2bec75"
"checksum log 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)" = "4fabed175da42fed1fa0746b0ea71f412aa9d35e76e95e59b192c64b9dc2bf8b"
"checksum mac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c41e0c4fef86961ac6d6f8a82609f55f31b05e4fce149ac5710e439df7619ba4"
@ -1170,6 +1331,9 @@ dependencies = [
"checksum plist 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7b336d94e8e4ce29bf15bba393164629764744c567e8ad306cc1fdd0119967fd"
"checksum ppv-lite86 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "237a5ed80e274dbc66f86bd59c1e25edc039660be53194b5fe0a482e0f2612ea"
"checksum precomputed-hash 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c"
"checksum predicates 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "96bfead12e90dccead362d62bb2c90a5f6fc4584963645bc7f71a735e0b0735a"
"checksum predicates-core 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "06075c3a3e92559ff8929e7a280684489ea27fe44805174c3ebd9328dcb37178"
"checksum predicates-tree 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8e63c4859013b38a76eca2414c64911fba30def9e3202ac461a2d22831220124"
"checksum proc-macro-error 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "fc175e9777c3116627248584e8f8b3e2987405cabe1c0adf7d1dd28f09dc7880"
"checksum proc-macro-error-attr 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3cc9795ca17eb581285ec44936da7fc2335a3f34f2ddd13118b6f4d515435c50"
"checksum proc-macro-hack 0.5.16 (registry+https://github.com/rust-lang/crates.io-index)" = "7e0456befd48169b9f13ef0f0ad46d492cf9d2dbb918bcf38e01eed4ce3ec5e4"
@ -1182,6 +1346,7 @@ dependencies = [
"checksum rand_pcg 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "16abd0c1b639e9eb4d7c50c0b8100b0d0f849be2349829c740fe8e6eb4816429"
"checksum redox_syscall 0.1.57 (registry+https://github.com/rust-lang/crates.io-index)" = "41cc0f7e4d5d4544e8861606a285bb08d3e70712ccc7d2b84d7c0ccfaf4b05ce"
"checksum regex-syntax 0.6.18 (registry+https://github.com/rust-lang/crates.io-index)" = "26412eb97c6b088a6997e05f69403a802a92d520de2f8e63c2b65f9e0f47c4e8"
"checksum remove_dir_all 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7"
"checksum rustc-demangle 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "4c691c0e608126e00913e33f0ccf3727d5fc84573623b8d65b2df340b5201783"
"checksum ryu 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e"
"checksum safemem 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ef703b7cb59335eae2eb93ceb664c0eb7ea6bf567079d843e09420219668e072"
@ -1194,6 +1359,7 @@ dependencies = [
"checksum serde_repr 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2dc6b7951b17b051f3210b063f12cc17320e2fe30ae05b0fe2a3abb068551c76"
"checksum serde_tuple 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f4f025b91216f15a2a32aa39669329a475733590a015835d1783549a56d09427"
"checksum serde_tuple_macros 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4076151d1a2b688e25aaf236997933c66e18b870d0369f8b248b8ab2be630d7e"
"checksum serde_yaml 0.8.13 (registry+https://github.com/rust-lang/crates.io-index)" = "ae3e2dd40a7cdc18ca80db804b7f461a39bb721160a85c9a1fa30134bf3c02a5"
"checksum servo_arc 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d98238b800e0d1576d8b6e3de32827c2d74bee68bb97748dcf5071fb53965432"
"checksum signal-hook 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "604508c1418b99dfe1925ca9224829bb2a8a9a04dda655cc01fcad46f4ab05ed"
"checksum signal-hook-registry 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "94f478ede9f64724c5d173d7bb56099ec3e2d9fc2774aac65d34b8b890405f41"
@ -1208,16 +1374,21 @@ dependencies = [
"checksum syn 1.0.34 (registry+https://github.com/rust-lang/crates.io-index)" = "936cae2873c940d92e697597c5eee105fb570cd5689c695806f672883653349b"
"checksum syn-mid 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7be3539f6c128a931cf19dcee741c1af532c7fd387baa739c03dd2e96479338a"
"checksum syntect 4.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b57a45fdcf4891bc79f635be5c559210a4cfa464891f969724944c713282eedb"
"checksum tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e24d9338a0a5be79593e2fa15a648add6138caa803e2d5bc782c371732ca9"
"checksum tendril 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "707feda9f2582d5d680d733e38755547a3e8fb471e7ba11452ecfd9ce93a5d3b"
"checksum terminal_size 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "9a14cd9f8c72704232f0bfc8455c0e861f0ad4eb60cc9ec8a170e231414c1e13"
"checksum termios 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6f0fcee7b24a25675de40d5bb4de6e41b0df07bc9856295e7e2b3a3600c400c2"
"checksum textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060"
"checksum thin-slice 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8eaa81235c7058867fa8c0e7314f33dcce9c215f535d1913822a2b3f5e289f3c"
"checksum time 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)" = "ca8a50ef2360fbd1eeb0ecd46795a87a19024eb4b53c5dc916ca1fd95fe62438"
"checksum toml 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)" = "ffc92d160b1eef40665be3a05630d003936a3bc7da7421277846c2613e92c71a"
"checksum treeline 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a7f741b240f1a48843f9b8e0444fb55fb2a4ff67293b50a9179dfd5ea67f8d41"
"checksum unicode-segmentation 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e83e153d1053cbb5a118eeff7fd5be06ed99153f00dbcd8ae310c5fb2b22edc0"
"checksum unicode-width 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "9337591893a19b88d8d87f2cec1e73fad5cdfd10e5a6f349f498ad6ea2ffb1e3"
"checksum unicode-xid 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564"
"checksum utf-8 0.7.5 (registry+https://github.com/rust-lang/crates.io-index)" = "05e42f7c18b8f902290b009cde6d651262f956c98bc51bca4cd1d511c9cd85c7"
"checksum version_check 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b5a972e5669d67ba988ce3dc826706fb0a8b01471c088cb0b6110b805cc36aed"
"checksum wait-timeout 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9f200f5b12eb75f8c1ed65abd4b2db8a6e1b138a20de009dacee265a2498f3f6"
"checksum walkdir 2.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "777182bc735b6424e1a57516d35ed72cb8019d85c8c9bf536dccb3445c1a2f7d"
"checksum wasi 0.9.0+wasi-snapshot-preview1 (registry+https://github.com/rust-lang/crates.io-index)" = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519"
"checksum winapi 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
@ -1227,3 +1398,4 @@ dependencies = [
"checksum xdg 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d089681aa106a86fade1b0128fb5daf07d5867a509ab036d99988dec80429a57"
"checksum xml-rs 0.8.3 (registry+https://github.com/rust-lang/crates.io-index)" = "b07db065a5cf61a7e4ba64f29e67db906fb1787316516c4e6e5ff0fea1efcd8a"
"checksum xml5ever 0.16.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0b1b52e6e8614d4a58b8e70cf51ec0cc21b256ad8206708bcff8139b5bbd6a59"
"checksum yaml-rust 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "39f0c922f1a334134dc2f7a8b67dc5d25f0735263feec974345ff706bcf20b0d"

View File

@ -45,3 +45,8 @@ default-features = false
version = "4.3.0"
default-features = false
features = ["parsing", "regex-onig", "assets", "dump-load"]
[dev-dependencies]
assert_cmd = "1.0.1"
insta = "0.16.1"
tempfile = "3.1.0"

119
tests/output.rs Normal file
View File

@ -0,0 +1,119 @@
// SPDX-FileCopyrightText: 2020 Robin Krahl <robin.krahl@ireas.org>
// SPDX-License-Identifier: MIT
use std::env;
use std::process;
use std::sync;
use assert_cmd::prelude::*;
static mut DIR: Option<tempfile::TempDir> = None;
static INIT: sync::Once = sync::Once::new();
fn run_cargo_doc() {
INIT.call_once(|| {
let dir = tempfile::tempdir().unwrap();
process::Command::new(env::var_os("CARGO").unwrap())
.arg("doc")
.args(&["--package", "anyhow"])
.args(&["--package", "log"])
.args(&["--package", "rand_core"])
.arg("--target-dir")
.arg(dir.path())
.output()
.unwrap();
unsafe {
DIR = Some(dir);
}
});
}
fn run(args: &[&str]) -> assert_cmd::assert::Assert {
run_cargo_doc();
let dir = unsafe { DIR.as_ref().unwrap() };
process::Command::cargo_bin(env!("CARGO_PKG_NAME"))
.unwrap()
.args(&["--no-default-sources", "--source"])
.arg(dir.path().join("doc"))
.args(&["--viewer", "plain"])
.args(args)
.assert()
}
fn get_stdout(args: &[&str]) -> String {
let cmd = run(args).success().stderr("");
String::from_utf8(cmd.get_output().stdout.clone()).unwrap()
}
fn assert_doc(item: &str) {
insta::assert_snapshot!(get_stdout(&[item]));
}
fn assert_examples(item: &str) {
insta::assert_snapshot!(get_stdout(&["-e", item]));
}
macro_rules! assert_doc {
($( $( #[$attrs:meta] )* $name:ident: $item:literal ),* $(,)? ) => {
$(
#[test]
$( #[$attrs] )*
fn $name() {
assert_doc($item);
}
)*
};
}
macro_rules! assert_examples {
($( $( #[$attrs:meta] )* $name:ident: $item:literal ),* $(,)? ) => {
$(
#[test]
$( #[$attrs] )*
fn $name() {
assert_examples($item);
}
)*
};
}
assert_doc![
test_mod_anyhow: "anyhow",
test_macro_anyhow_anyhow: "anyhow::anyhow",
test_macro_anyhow_ensure: "anyhow::ensure",
#[ignore]
test_struct_anyhow_error: "anyhow::Error",
test_trait_anyhow_context: "anyhow::Context",
test_type_anyhow_result: "anyhow::Result",
];
assert_doc![
#[ignore]
test_mod_log: "log",
#[ignore]
test_macro_log_debug: "log::debug",
#[ignore]
test_struct_log_metadata: "log::Metadata",
test_enum_log_level: "log::Level",
#[ignore]
test_constant_log_static_max_level: "log::STATIC_MAX_LEVEL",
test_trait_log_log: "log::Log",
test_fn_log_logger: "log::logger",
test_fn_log_set_logger_racy: "log::set_logger_racy",
];
assert_doc![
test_mod_rand_core: "rand_core",
test_trait_rand_core_rngcore: "rand_core::RngCore",
test_trait_rand_core_seedablerng: "rand_core::SeedableRng",
test_struct_rand_core_block_blockrng: "rand_core::block::BlockRng",
];
assert_examples![
test_examples_mod_anyhow: "anyhow",
#[ignore]
test_examples_mod_log: "log",
test_examples_struct_rand_core_rngcore: "rand_core::RngCore",
];

View File

@ -0,0 +1,19 @@
---
source: tests/output.rs
expression: "get_stdout(&[item])"
---
log Constant log::STATIC_MAX_LEVEL rusty-man
SYNOPSIS
pub const STATIC_MAX_LEVEL: LevelFilter;
DESCRIPTION
The statically resolved maximum log level.
See the crate level documentation for information on how to configure this.
This value is checked by the log macros, but not by the `Log`ger returned by the `logger`
function. Code that manually calls functions on that value should compare the level against
this value.

View File

@ -0,0 +1,178 @@
---
source: tests/output.rs
expression: "get_stdout(&[item])"
---
log Enum log::Level rusty-man
SYNOPSIS
#[repr(usize)]
pub enum Level {
Error,
Warn,
Info,
Debug,
Trace,
}
DESCRIPTION
An enum representing the available verbosity levels of the logger.
Typical usage includes: checking if a certain `Level` is enabled with `log_enabled!`,
specifying the `Level` of `log!`, and comparing a `Level` directly to a `LevelFilter`.
VARIANTS
Error
Error
The "error" level.
Designates very serious errors.
Warn
Warn
The "warn" level.
Designates hazardous situations.
Info
Info
The "info" level.
Designates useful information.
Debug
Debug
The "debug" level.
Designates lower priority information.
Trace
Trace
The "trace" level.
Designates very low priority, often extremely verbose, information.
METHODS
impl Level
max
pub fn max() -> Level
Returns the most verbose logging level.
to_level_filter
pub fn to_level_filter(&self) -> LevelFilter
Converts the `Level` to the equivalent `LevelFilter`.
IMPLEMENTATIONS
Trait Implementations
Clone
impl Clone for Level
Copy
impl Copy for Level
Debug
impl Debug for Level
Display
impl Display for Level
Eq
impl Eq for Level
FromStr
impl FromStr for Level
Hash
impl Hash for Level
Ord
impl Ord for Level
PartialEq
impl PartialEq<Level> for Level
PartialEq
impl PartialEq<Level> for LevelFilter
PartialEq
impl PartialEq<LevelFilter> for Level
PartialOrd
impl PartialOrd<Level> for Level
PartialOrd
impl PartialOrd<Level> for LevelFilter
PartialOrd
impl PartialOrd<LevelFilter> for Level
StructuralEq
impl StructuralEq for Level
Auto Trait Implementations
RefUnwindSafe
impl RefUnwindSafe for Level
Send
impl Send for Level
Sync
impl Sync for Level
Unpin
impl Unpin for Level
UnwindSafe
impl UnwindSafe for Level
Blanket Implementations
Any
impl<T> Any for T
where
    T: 'static + ?Sized,
Borrow
impl<T> Borrow<T> for T
where
    T: ?Sized,
BorrowMut
impl<T> BorrowMut<T> for T
where
    T: ?Sized,
From
impl<T> From<T> for T
Into
impl<T, U> Into<U> for T
where
    U: From<T>,
ToOwned
impl<T> ToOwned for T
where
    T: Clone,
ToString
impl<T> ToString for T
where
    T: Display + ?Sized,
TryFrom
impl<T, U> TryFrom<U> for T
where
    U: Into<T>,
TryInto
impl<T, U> TryInto<U> for T
where
    U: TryFrom<T>,

View File

@ -0,0 +1,54 @@
---
source: tests/output.rs
expression: "get_stdout(&[\"-e\", item])"
---
anyhow Module anyhow rusty-man
EXAMPLES
Example 1 of 5
use anyhow::Result;
fn get_cluster_info() -> Result<ClusterMap> {
let config = std::fs::read_to_string("cluster.json")?;
let map: ClusterMap = serde_json::from_str(&config)?;
Ok(map)
}
Example 2 of 5
use anyhow::{Context, Result};
fn main() -> Result<()> {
...
it.detach().context("Failed to detach the important thing")?;
let content = std::fs::read(path)
.with_context(|| format!("Failed to read instrs from {}", path))?;
...
}
Example 3 of 5
// If the error was caused by redaction, then return a
// tombstone instead of the content.
match root_cause.downcast_ref::<DataStoreError>() {
Some(DataStoreError::Censored(_)) => Ok(Poll::Ready(REDACTED_CONTENT)),
None => Err(error),
}
Example 4 of 5
use thiserror::Error;
#[derive(Error, Debug)]
pub enum FormatError {
#[error("Invalid header (expected {expected:?}, got {found:?})")]
InvalidHeader {
expected: String,
found: String,
},
#[error("Missing attribute: {0}")]
MissingAttribute(String),
}
Example 5 of 5
return Err(anyhow!("Missing attribute: {}", missing));

View File

@ -0,0 +1,63 @@
---
source: tests/output.rs
expression: "get_stdout(&[\"-e\", item])"
---
log Module log rusty-man
EXAMPLES
Example 1 of 4
use log::{info, warn};
pub fn shave_the_yak(yak: &mut Yak) {
info!(target: "yak_events", "Commencing yak shaving for {:?}", yak);
loop {
match find_a_razor() {
Ok(razor) => {
info!("Razor located: {}", razor);
yak.shave(razor);
break;
}
Err(err) => {
warn!("Unable to locate a razor: {}, retrying", err);
}
}
}
}
Example 2 of 4
use log::{Record, Level, Metadata};
struct SimpleLogger;
impl log::Log for SimpleLogger {
fn enabled(&self, metadata: &Metadata) -> bool {
metadata.level() <= Level::Info
}
fn log(&self, record: &Record) {
if self.enabled(record.metadata()) {
println!("{} - {}", record.level(), record.args());
}
}
fn flush(&self) {}
}
Example 3 of 4
use log::{SetLoggerError, LevelFilter};
static LOGGER: SimpleLogger = SimpleLogger;
pub fn init() -> Result<(), SetLoggerError> {
log::set_logger(&LOGGER)
.map(|()| log::set_max_level(LevelFilter::Info))
}
Example 4 of 4
pub fn init() -> Result<(), SetLoggerError> {
log::set_boxed_logger(Box::new(SimpleLogger))
.map(|()| log::set_max_level(LevelFilter::Info))
}

View File

@ -0,0 +1,34 @@
---
source: tests/output.rs
expression: "get_stdout(&[\"-e\", item])"
---
rand_core Trait rand_core::RngCore rusty-man
EXAMPLES
A simple example, obviously not generating very *random* output:
#![allow(dead_code)]
use rand_core::{RngCore, Error, impls};
struct CountingRng(u64);
impl RngCore for CountingRng {
fn next_u32(&mut self) -> u32 {
self.next_u64() as u32
}
fn next_u64(&mut self) -> u64 {
self.0 += 1;
self.0
}
fn fill_bytes(&mut self, dest: &mut [u8]) {
impls::fill_bytes_via_next(self, dest)
}
fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error> {
Ok(self.fill_bytes(dest))
}
}

View File

@ -0,0 +1,15 @@
---
source: tests/output.rs
expression: "get_stdout(&[item])"
---
log Function log::logger rusty-man
SYNOPSIS
pub fn logger() -> &'static dyn Log
DESCRIPTION
Returns a reference to the logger.
If a logger has not been set, a no-op implementation is returned.

View File

@ -0,0 +1,31 @@
---
source: tests/output.rs
expression: "get_stdout(&[item])"
---
log Function log::set_logger_racy rusty-man
SYNOPSIS
pub unsafe fn set_logger_racy(
    logger: &'static dyn Log
) -> Result<(), SetLoggerError>
DESCRIPTION
A thread-unsafe version of `set_logger`.
This function is available on all platforms, even those that do not have support for atomics
that is needed by `set_logger`.
In almost all cases, `set_logger` should be preferred.
# Safety
This function is only safe to call when no other logger initialization function is called
while this function still executes.
This can be upheld by (for example) making sure that **there are no other threads**, and (on
embedded) that **interrupts are disabled**.
It is safe to use other logging functions while this function runs (including all logging
macros).

View File

@ -0,0 +1,30 @@
---
source: tests/output.rs
expression: "get_stdout(&[item])"
---
anyhow Macro anyhow::anyhow rusty-man
SYNOPSIS
macro_rules! anyhow {
($msg:literal $(,)?) => { ... };
($err:expr $(,)?) => { ... };
($fmt:expr, $($arg:tt)*) => { ... };
}
DESCRIPTION
Construct an ad-hoc error from a string.
This evaluates to an `Error`. It can take either just a string, or a format string with
arguments. It also can take any custom type which implements `Debug` and `Display`.
# Example
use anyhow::{anyhow, Result};
fn lookup(key: &str) -> Result<V> {
if key.len() != 16 {
return Err(anyhow!("key length must be 16 characters, got {:?}", key));
}
// ...
}

View File

@ -0,0 +1,33 @@
---
source: tests/output.rs
expression: "get_stdout(&[item])"
---
anyhow Macro anyhow::ensure rusty-man
SYNOPSIS
macro_rules! ensure {
($cond:expr, $msg:literal $(,)?) => { ... };
($cond:expr, $err:expr $(,)?) => { ... };
($cond:expr, $fmt:expr, $($arg:tt)*) => { ... };
}
DESCRIPTION
Return early with an error if a condition is not satisfied.
This macro is equivalent to `if !$cond { return Err(From::from($err)); }`.
Analogously to `assert!`, `ensure!` takes a condition and exits the function if the condition
fails. Unlike `assert!`, `ensure!` returns an `Error` rather than panicking.
# Example
ensure!(user == 0, "only user 0 is allowed");
#[derive(Error, Debug)]
enum ScienceError {
#[error("recursion limit exceeded")]
RecursionLimitExceeded,
...
}
ensure!(depth <= MAX_DEPTH, ScienceError::RecursionLimitExceeded);

View File

@ -0,0 +1,24 @@
---
source: tests/output.rs
expression: "get_stdout(&[item])"
---
log Macro log::debug rusty-man
SYNOPSIS
macro_rules! debug {
(target: $target:expr, $($arg:tt)+) => { ... };
($($arg:tt)+) => { ... };
}
DESCRIPTION
Logs a message at the debug level.
# Examples
ⓘThis code runs with edition 2018
use log::debug;
let pos = Position { x: 3.234, y: -1.223 };
debug!("New position: x: {}, y: {}", pos.x, pos.y);
debug!(target: "app_events", "New position: x: {}, y: {}", pos.x, pos.y);

View File

@ -0,0 +1,134 @@
---
source: tests/output.rs
expression: "get_stdout(&[item])"
---
anyhow Module anyhow rusty-man
DESCRIPTION
[[github]][1] [[crates-io]][2] [[docs-rs]][3]
This library provides [`anyhow::Error`][Error], a trait object based error type for easy
idiomatic error handling in Rust applications.
# Details
* Use `Result<T, anyhow::Error>`, or equivalently `anyhow::Result<T>`, as the return type of
any fallible function.
Within the function, use `?` to easily propagate any error that implements the
`std::error::Error` trait.
use anyhow::Result;
fn get_cluster_info() -> Result<ClusterMap> {
let config = std::fs::read_to_string("cluster.json")?;
let map: ClusterMap = serde_json::from_str(&config)?;
Ok(map)
}
* Attach context to help the person troubleshooting the error understand where things went
wrong. A low-level error like "No such file or directory" can be annoying to debug without
more context about what higher level step the application was in the middle of.
use anyhow::{Context, Result};
fn main() -> Result<()> {
...
it.detach().context("Failed to detach the important thing")?;
let content = std::fs::read(path)
.with_context(|| format!("Failed to read instrs from {}", path))?;
...
}
`Error: Failed to read instrs from ./path/to/instrs.json
Caused by:
No such file or directory (os error 2)
`
* Downcasting is supported and can be by value, by shared reference, or by mutable reference
as needed.
// If the error was caused by redaction, then return a
// tombstone instead of the content.
match root_cause.downcast_ref::<DataStoreError>() {
Some(DataStoreError::Censored(_)) => Ok(Poll::Ready(REDACTED_CONTENT)),
None => Err(error),
}
* If using the nightly channel, a backtrace is captured and printed with the error if the
underlying error type does not already provide its own. In order to see backtraces, they
must be enabled through the environment variables described in [`std::backtrace`][1]:
* If you want panics and errors to both have backtraces, set `RUST_BACKTRACE=1`;
* If you want only errors to have backtraces, set `RUST_LIB_BACKTRACE=1`;
* If you want only panics to have backtraces, set `RUST_BACKTRACE=1` and
`RUST_LIB_BACKTRACE=0`.
The tracking issue for this feature is [rust-lang/rust#53487][2].
[1] https://doc.rust-lang.org/std/backtrace/index.html#environment-variables
[2] https://github.com/rust-lang/rust/issues/53487
* Anyhow works with any error type that has an impl of `std::error::Error`, including ones
defined in your crate. We do not bundle a `derive(Error)` macro but you can write the impls
yourself or use a standalone macro like [thiserror][1].
use thiserror::Error;
#[derive(Error, Debug)]
pub enum FormatError {
#[error("Invalid header (expected {expected:?}, got {found:?})")]
InvalidHeader {
expected: String,
found: String,
},
#[error("Missing attribute: {0}")]
MissingAttribute(String),
}
[1] https://github.com/dtolnay/thiserror
* One-off error messages can be constructed using the `anyhow!` macro, which supports string
interpolation and produces an `anyhow::Error`.
return Err(anyhow!("Missing attribute: {}", missing));
# No-std support
In no_std mode, the same API is almost all available and works the same way. To depend on
Anyhow in no_std mode, disable our default enabled "std" feature in Cargo.toml. A global
allocator is required.
`[dependencies]
anyhow = { version = "1.0", default-features = false }
`
Since the `?`-based error conversions would normally rely on the `std::error::Error` trait
which is only available through std, no_std mode will require an explicit
`.map_err(Error::msg)` when working with a non-Anyhow error type inside a function that
returns Anyhow's error type.
[1] https://github.com/dtolnay/anyhow
[2] https://crates.io/crates/anyhow
[3] https://docs.rs/anyhow
MACROS
anyhow
Construct an ad-hoc error from a string.
bail
Return early with an error.
ensure
Return early with an error if a condition is not satisfied.
STRUCTS
Chain
Iterator of a chain of source errors.
Error
The `Error` type, a wrapper around a dynamic error type.
TRAITS
Context
Provides the `context` method for `Result`.
TYPEDEFS
Result
`Result<T, Error>`

View File

@ -0,0 +1,299 @@
---
source: tests/output.rs
expression: "get_stdout(&[item])"
---
log Module log rusty-man
DESCRIPTION
A lightweight logging facade.
The `log` crate provides a single logging API that abstracts over the actual logging
implementation. Libraries can use the logging API provided by this crate, and the consumer of
those libraries can choose the logging implementation that is most suitable for its use case.
If no logging implementation is selected, the facade falls back to a "noop" implementation
that ignores all log messages. The overhead in this case is very small - just an integer load,
comparison and jump.
A log request consists of a *target*, a *level*, and a *body*. A target is a string which
defaults to the module path of the location of the log request, though that default may be
overridden. Logger implementations typically use the target to filter requests based on some
user configuration.
# Use
The basic use of the log crate is through the five logging macros: `error!`, `warn!`, `info!`,
`debug!` and `trace!` where `error!` represents the highest-priority log messages and `trace!`
the lowest. The log messages are filtered by configuring the log level to exclude messages
with a lower priority. Each of these macros accept format strings similarly to
[`println!`][1].
## In libraries
Libraries should link only to the `log` crate, and use the provided macros to log whatever
information will be useful to downstream consumers.
### Examples
ⓘThis code runs with edition 2018
use log::{info, warn};
pub fn shave_the_yak(yak: &mut Yak) {
info!(target: "yak_events", "Commencing yak shaving for {:?}", yak);
loop {
match find_a_razor() {
Ok(razor) => {
info!("Razor located: {}", razor);
yak.shave(razor);
break;
}
Err(err) => {
warn!("Unable to locate a razor: {}, retrying", err);
}
}
}
}
## In executables
Executables should choose a logging implementation and initialize it early in the runtime of
the program. Logging implementations will typically include a function to do this. Any log
messages generated before the implementation is initialized will be ignored.
The executable itself may use the `log` crate to log as well.
### Warning
The logging system may only be initialized once.
# Available logging implementations
In order to produce log output executables have to use a logger implementation compatible with
the facade. There are many available implementations to choose from, here are some of the most
popular ones:
* Simple minimal loggers:
* [env_logger][1]
[1] https://docs.rs/env_logger/*/env_logger/
* [simple_logger][1]
[1] https://github.com/borntyping/rust-simple_logger
* [simplelog][1]
[1] https://github.com/drakulix/simplelog.rs
* [pretty_env_logger][1]
[1] https://docs.rs/pretty_env_logger/*/pretty_env_logger/
* [stderrlog][1]
[1] https://docs.rs/stderrlog/*/stderrlog/
* [flexi_logger][1]
[1] https://docs.rs/flexi_logger/*/flexi_logger/
* Complex configurable frameworks:
* [log4rs][1]
[1] https://docs.rs/log4rs/*/log4rs/
* [fern][1]
[1] https://docs.rs/fern/*/fern/
* Adaptors for other facilities:
* [syslog][1]
[1] https://docs.rs/syslog/*/syslog/
* [slog-stdlog][1]
[1] https://docs.rs/slog-stdlog/*/slog_stdlog/
# Implementing a Logger
Loggers implement the `Log` trait. Here's a very basic example that simply logs all messages
at the `Error`, `Warn` or `Info` levels to stdout:
ⓘThis code runs with edition 2018
use log::{Record, Level, Metadata};
struct SimpleLogger;
impl log::Log for SimpleLogger {
fn enabled(&self, metadata: &Metadata) -> bool {
metadata.level() <= Level::Info
}
fn log(&self, record: &Record) {
if self.enabled(record.metadata()) {
println!("{} - {}", record.level(), record.args());
}
}
fn flush(&self) {}
}
Loggers are installed by calling the `set_logger` function. The maximum log level also needs
to be adjusted via the `set_max_level` function. The logging facade uses this as an
optimization to improve performance of log messages at levels that are disabled. It's
important to set it, as it defaults to `Off`, so no log messages will ever be captured! In the
case of our example logger, we'll want to set the maximum log level to `Info`, since we ignore
any `Debug` or `Trace` level log messages. A logging implementation should provide a function
that wraps a call to `set_logger` and `set_max_level`, handling initialization of the logger:
ⓘThis code runs with edition 2018
use log::{SetLoggerError, LevelFilter};
static LOGGER: SimpleLogger = SimpleLogger;
pub fn init() -> Result<(), SetLoggerError> {
log::set_logger(&LOGGER)
.map(|()| log::set_max_level(LevelFilter::Info))
}
Implementations that adjust their configurations at runtime should take care to adjust the
maximum log level as well.
# Use with `std`
`set_logger` requires you to provide a `&'static Log`, which can be hard to obtain if your
logger depends on some runtime configuration. The `set_boxed_logger` function is available
with the `std` Cargo feature. It is identical to `set_logger` except that it takes a
`Box<Log>` rather than a `&'static Log`:
ⓘThis code runs with edition 2018
pub fn init() -> Result<(), SetLoggerError> {
log::set_boxed_logger(Box::new(SimpleLogger))
.map(|()| log::set_max_level(LevelFilter::Info))
}
# Compile time filters
Log levels can be statically disabled at compile time via Cargo features. Log invocations at
disabled levels will be skipped and will not even be present in the resulting binary. This
level is configured separately for release and debug builds. The features are:
* `max_level_off`
* `max_level_error`
* `max_level_warn`
* `max_level_info`
* `max_level_debug`
* `max_level_trace`
* `release_max_level_off`
* `release_max_level_error`
* `release_max_level_warn`
* `release_max_level_info`
* `release_max_level_debug`
* `release_max_level_trace`
These features control the value of the `STATIC_MAX_LEVEL` constant. The logging macros check
this value before logging a message. By default, no levels are disabled.
Libraries should avoid using the max level features because they're global and can't be
changed once they're set.
For example, a crate can disable trace level logs in debug builds and trace, debug, and info
level logs in release builds with the following configuration:
`[dependencies]
log = { version = "0.4", features = ["max_level_debug", "release_max_level_warn"] }
`
# Crate Feature Flags
The following crate feature flags are available in addition to the filters. They are
configured in your `Cargo.toml`.
* `std` allows use of `std` crate instead of the default `core`. Enables using `std::error`
and `set_boxed_logger` functionality.
* `serde` enables support for serialization and deserialization of `Level` and `LevelFilter`.
`[dependencies]
log = { version = "0.4", features = ["std", "serde"] }
`
# Version compatibility
The 0.3 and 0.4 versions of the `log` crate are almost entirely compatible. Log messages made
using `log` 0.3 will forward transparently to a logger implementation using `log` 0.4. Log
messages made using `log` 0.4 will forward to a logger implementation using `log` 0.3, but the
module path and file name information associated with the message will unfortunately be lost.
[1] https://doc.rust-lang.org/stable/std/macro.println.html
MACROS
debug
Logs a message at the debug level.
error
Logs a message at the error level.
info
Logs a message at the info level.
log
The standard logging macro.
log_enabled
Determines if a message logged at the specified level in that module will be logged.
trace
Logs a message at the trace level.
warn
Logs a message at the warn level.
STRUCTS
Metadata
Metadata about a log message.
MetadataBuilder
Builder for `Metadata`.
ParseLevelError
The type returned by [`from_str`][1] when the string doesn't match any of the log
levels.
[1] https://doc.rust-lang.org/std/str/trait.FromStr.html#tymethod.from_str
Record
The "payload" of a log message.
RecordBuilder
Builder for `Record`.
SetLoggerError
The type returned by `set_logger` if `set_logger` has already been called.
ENUMS
Level
An enum representing the available verbosity levels of the logger.
LevelFilter
An enum representing the available verbosity level filters of the logger.
CONSTANTS
STATIC_MAX_LEVEL
The statically resolved maximum log level.
TRAITS
Log
A trait encapsulating the operations required of a logger.
FUNCTIONS
logger
Returns a reference to the logger.
max_level
Returns the current maximum log level.
set_boxed_logger
Sets the global logger to a `Box<Log>`.
set_logger
Sets the global logger to a `&'static Log`.
set_logger_racy
A thread-unsafe version of `set_logger`.
set_max_level
Sets the global maximum log level.

View File

@ -0,0 +1,55 @@
---
source: tests/output.rs
expression: "get_stdout(&[item])"
---
rand_core Module rand_core rusty-man
DESCRIPTION
Random number generation traits
This crate is mainly of interest to crates publishing implementations of [`RngCore`]. Other
users are encouraged to use the [`rand`][1] crate instead which re-exports the main traits and
error types.
[`RngCore`] is the core trait implemented by algorithmic pseudo-random number generators and
external random-number sources.
[`SeedableRng`] is an extension trait for construction from fixed seeds and other random
number generators.
[`Error`] is provided for error-handling. It is safe to use in `no_std` environments.
The [`impls`] and [`le`] sub-modules include a few small functions to assist implementation of
[`RngCore`].
[1] https://docs.rs/rand
MODULES
block
The `BlockRngCore` trait and implementation helpers
impls
Helper functions for implementing `RngCore` functions.
le
Little-Endian utilities
STRUCTS
Error
Error type of random number generators
OsRng
A random number generator that retrieves randomness from from the operating system.
TRAITS
CryptoRng
A marker trait used to indicate that an [`RngCore`] or `BlockRngCore` implementation is
supposed to be cryptographically secure.
RngCore
The core of a random number generator.
SeedableRng
A random number generator that can be explicitly seeded.

View File

@ -0,0 +1,356 @@
---
source: tests/output.rs
expression: "get_stdout(&[item])"
---
anyhow Struct anyhow::Error rusty-man
SYNOPSIS
pub struct Error { /* fields omitted */ }
DESCRIPTION
The `Error` type, a wrapper around a dynamic error type.
`Error` works a lot like `Box<dyn std::error::Error>`, but with these differences:
* `Error` requires that the error is `Send`, `Sync`, and `'static`.
* `Error` guarantees that a backtrace is available, even if the underlying error type does not
provide one.
* `Error` is represented as a narrow pointer — exactly one word in size instead of two.
# Display representations
When you print an error object using "{}" or to_string(), only the outermost underlying error
or context is printed, not any of the lower level causes. This is exactly as if you had called
the Display impl of the error from which you constructed your anyhow::Error.
`Failed to read instrs from ./path/to/instrs.json
`
To print causes as well using anyhow's default formatting of causes, use the alternate
selector "{:#}".
`Failed to read instrs from ./path/to/instrs.json: No such file or directory (os error 2)
`
The Debug format "{:?}" includes your backtrace if one was captured. Note that this is the
representation you get by default if you return an error from `fn main` instead of printing it
explicitly yourself.
`Error: Failed to read instrs from ./path/to/instrs.json
Caused by:
No such file or directory (os error 2)
`
and if there is a backtrace available:
`Error: Failed to read instrs from ./path/to/instrs.json
Caused by:
No such file or directory (os error 2)
Stack backtrace:
0: <E as anyhow::context::ext::StdError>::ext_context
at /git/anyhow/src/backtrace.rs:26
1: core::result::Result<T,E>::map_err
at /git/rustc/src/libcore/result.rs:596
2: anyhow::context::<impl anyhow::Context<T,E> for core::result::Result<T,E>>::with_context
at /git/anyhow/src/context.rs:58
3: testing::main
at src/main.rs:5
4: std::rt::lang_start
at /git/rustc/src/libstd/rt.rs:61
5: main
6: __libc_start_main
7: _start
`
To see a conventional struct-style Debug representation, use "{:#?}".
`Error {
context: "Failed to read instrs from ./path/to/instrs.json",
source: Os {
code: 2,
kind: NotFound,
message: "No such file or directory",
},
}
`
If none of the built-in representations are appropriate and you would prefer to render the
error and its cause chain yourself, it can be done something like this:
use anyhow::{Context, Result};
fn main() {
if let Err(err) = try_main() {
eprintln!("ERROR: {}", err);
err.chain().skip(1).for_each(|cause| eprintln!("because: {}", cause));
std::process::exit(1);
}
}
fn try_main() -> Result<()> {
...
}
METHODS
impl Error
new
pub fn new<E>(error: E) -> Self
where
    E: StdError + Send + Sync + 'static,
Create a new error object from any error type.
The error type must be threadsafe and `'static`, so that the `Error` will be as well.
If the error type does not provide a backtrace, a backtrace will be created here to
ensure that a backtrace exists.
msg
pub fn msg<M>(message: M) -> Self
where
    M: Display + Debug + Send + Sync + 'static,
Create a new error object from a printable error message.
If the argument implements std::error::Error, prefer `Error::new` instead which
preserves the underlying error's cause chain and backtrace. If the argument may or may
not implement std::error::Error now or in the future, use `anyhow!(err)` which handles
either way correctly.
`Error::msg("...")` is equivalent to `anyhow!("...")` but occasionally convenient in
places where a function is preferable over a macro, such as iterator or stream
combinators:
use anyhow::{Error, Result};
use futures::stream::{Stream, StreamExt, TryStreamExt};
async fn demo<S>(stream: S) -> Result<Vec<Output>>
where
S: Stream<Item = Input>,
{
stream
.then(ffi::do_some_work) // returns Result<Output, &str>
.map_err(Error::msg)
.try_collect()
.await
}
context
pub fn context<C>(self, context: C) -> Self
where
    C: Display + Send + Sync + 'static,
Wrap the error value with additional context.
For attaching context to a `Result` as it is propagated, the [`Context`][crate::Context]
extension trait may be more convenient than this function.
The primary reason to use `error.context(...)` instead of `result.context(...)` via the
`Context` trait would be if the context needs to depend on some data held by the
underlying error:
use anyhow::Result;
use std::fs::File;
use std::path::Path;
struct ParseError {
line: usize,
column: usize,
}
fn parse_impl(file: File) -> Result<T, ParseError> {
...
}
pub fn parse(path: impl AsRef<Path>) -> Result<T> {
let file = File::open(&path)?;
parse_impl(file).map_err(|error| {
let context = format!(
"only the first {} lines of {} are valid",
error.line, path.as_ref().display(),
);
anyhow::Error::new(error).context(context)
})
}
chain
pub fn chain(&self) -> Chain
An iterator of the chain of source errors contained by this Error.
This iterator will visit every error in the cause chain of this error object, beginning
with the error that this error object was created from.
# Example
use anyhow::Error;
use std::io;
pub fn underlying_io_error_kind(error: &Error) -> Option<io::ErrorKind> {
for cause in error.chain() {
if let Some(io_error) = cause.downcast_ref::<io::Error>() {
return Some(io_error.kind());
}
}
None
}
root_cause
pub fn root_cause(&self) -> &(dyn StdError + 'static)
The lowest level cause of this error — this error's cause's cause's cause etc.
The root cause is the last error in the iterator produced by [`chain()`][Error::chain].
is
pub fn is<E>(&self) -> bool
where
    E: Display + Debug + Send + Sync + 'static,
Returns true if `E` is the type held by this error object.
For errors with context, this method returns true if `E` matches the type of the context
`C` **or** the type of the error on which the context has been attached. For details
about the interaction between context and downcasting, see here.
downcast
pub fn downcast<E>(self) -> Result<E, Self>
where
    E: Display + Debug + Send + Sync + 'static,
Attempt to downcast the error object to a concrete type.
downcast_ref
pub fn downcast_ref<E>(&self) -> Option<&E>
where
    E: Display + Debug + Send + Sync + 'static,
Downcast this error object by reference.
# Example
// If the error was caused by redaction, then return a tombstone instead
// of the content.
match root_cause.downcast_ref::<DataStoreError>() {
Some(DataStoreError::Censored(_)) => Ok(Poll::Ready(REDACTED_CONTENT)),
None => Err(error),
}
downcast_mut
pub fn downcast_mut<E>(&mut self) -> Option<&mut E>
where
    E: Display + Debug + Send + Sync + 'static,
Downcast this error object by mutable reference.
Methods from Deref<Target = dyn StdError + Send + Sync + 'static>
is-1
pub fn is<T>(&self) -> bool
where
    T: 'static + Error,
Returns `true` if the boxed type is the same as `T`
downcast_ref-1
pub fn downcast_ref<T>(&self) -> Option<&T>
where
    T: 'static + Error,
Returns some reference to the boxed value if it is of type `T`, or `None` if it isn't.
downcast_mut-1
pub fn downcast_mut<T>(&mut self) -> Option<&mut T>
where
    T: 'static + Error,
Returns some mutable reference to the boxed value if it is of type `T`, or `None` if it
isn't.
IMPLEMENTATIONS
Trait Implementations
AsRef
impl AsRef<dyn Error + 'static + Send + Sync> for Error
AsRef
impl AsRef<dyn Error + 'static> for Error
Debug
impl Debug for Error
Deref
impl Deref for Error
DerefMut
impl DerefMut for Error
Display
impl Display for Error
Drop
impl Drop for Error
From
impl From<Error> for Box<dyn StdError + 'static>
From
impl From<Error> for Box<dyn StdError + Send + Sync + 'static>
From
impl<E> From<E> for Error
where
    E: StdError + Send + Sync + 'static,
Auto Trait Implementations
RefUnwindSafe
impl RefUnwindSafe for Error
Send
impl Send for Error
Sync
impl Sync for Error
Unpin
impl Unpin for Error
UnwindSafe
impl UnwindSafe for Error
Blanket Implementations
Any
impl<T> Any for T
where
    T: 'static + ?Sized,
Borrow
impl<T> Borrow<T> for T
where
    T: ?Sized,
BorrowMut
impl<T> BorrowMut<T> for T
where
    T: ?Sized,
From
impl<T> From<!> for T
From
impl<T> From<T> for T
Into
impl<T, U> Into<U> for T
where
    U: From<T>,
ToString
impl<T> ToString for T
where
    T: Display + ?Sized,
TryFrom
impl<T, U> TryFrom<U> for T
where
    U: Into<T>,
TryInto
impl<T, U> TryInto<U> for T
where
    U: TryFrom<T>,

View File

@ -0,0 +1,142 @@
---
source: tests/output.rs
expression: "get_stdout(&[item])"
---
log Struct log::Metadata rusty-man
SYNOPSIS
pub struct Metadata<'a> { /* fields omitted */ }
DESCRIPTION
Metadata about a log message.
# Use
`Metadata` structs are created when users of the library use logging macros.
They are consumed by implementations of the `Log` trait in the `enabled` method.
`Record`s use `Metadata` to determine the log message's severity and target.
Users should use the `log_enabled!` macro in their code to avoid constructing expensive log
messages.
# Examples
ⓘThis code runs with edition 2018
use log::{Record, Level, Metadata};
struct MyLogger;
impl log::Log for MyLogger {
fn enabled(&self, metadata: &Metadata) -> bool {
metadata.level() <= Level::Info
}
fn log(&self, record: &Record) {
if self.enabled(record.metadata()) {
println!("{} - {}", record.level(), record.args());
}
}
fn flush(&self) {}
}
METHODS
impl<'a> Metadata<'a>
builder
pub fn builder() -> MetadataBuilder<'a>
Returns a new builder.
level
pub fn level(&self) -> Level
The verbosity level of the message.
target
pub fn target(&self) -> &'a str
The name of the target of the directive.
IMPLEMENTATIONS
Trait Implementations
Clone
impl<'a> Clone for Metadata<'a>
Debug
impl<'a> Debug for Metadata<'a>
Eq
impl<'a> Eq for Metadata<'a>
Hash
impl<'a> Hash for Metadata<'a>
Ord
impl<'a> Ord for Metadata<'a>
PartialEq
impl<'a> PartialEq<Metadata<'a>> for Metadata<'a>
PartialOrd
impl<'a> PartialOrd<Metadata<'a>> for Metadata<'a>
StructuralEq
impl<'a> StructuralEq for Metadata<'a>
StructuralPartialEq
impl<'a> StructuralPartialEq for Metadata<'a>
Auto Trait Implementations
RefUnwindSafe
impl<'a> RefUnwindSafe for Metadata<'a>
Send
impl<'a> Send for Metadata<'a>
Sync
impl<'a> Sync for Metadata<'a>
Unpin
impl<'a> Unpin for Metadata<'a>
UnwindSafe
impl<'a> UnwindSafe for Metadata<'a>
Blanket Implementations
Any
impl<T> Any for T
where
    T: 'static + ?Sized,
Borrow
impl<T> Borrow<T> for T
where
    T: ?Sized,
BorrowMut
impl<T> BorrowMut<T> for T
where
    T: ?Sized,
From
impl<T> From<T> for T
Into
impl<T, U> Into<U> for T
where
    U: From<T>,
ToOwned
impl<T> ToOwned for T
where
    T: Clone,
TryFrom
impl<T, U> TryFrom<U> for T
where
    U: Into<T>,
TryInto
impl<T, U> TryInto<U> for T
where
    U: TryFrom<T>,

View File

@ -0,0 +1,163 @@
---
source: tests/output.rs
expression: "get_stdout(&[item])"
---
rand_core Struct rand_core::block::BlockRng rusty-man
SYNOPSIS
pub struct BlockRng<R: BlockRngCore + ?Sized> {
pub core: R,
// some fields omitted
}
DESCRIPTION
A wrapper type implementing [`RngCore`] for some type implementing [`BlockRngCore`] with `u32`
array buffer; i.e. this can be used to implement a full RNG from just a `generate` function.
The `core` field may be accessed directly but the results buffer may not. PRNG implementations
can simply use a type alias (`pub type MyRng = BlockRng<MyRngCore>;`) but might prefer to use
a wrapper type (`pub struct MyRng(BlockRng<MyRngCore>);`); the latter must re-implement
`RngCore` but hides the implementation details and allows extra functionality to be defined on
the RNG (e.g. `impl MyRng { fn set_stream(...){...} }`).
`BlockRng` has heavily optimized implementations of the [`RngCore`] methods reading values
from the results buffer, as well as calling [`BlockRngCore::generate`] directly on the output
array when `fill_bytes` / `try_fill_bytes` is called on a large array. These methods also
handle the bookkeeping of when to generate a new batch of values.
No whole generated `u32` values are thown away and all values are consumed in-order.
`next_u32` simply takes the next available `u32` value. `next_u64` is implemented by combining
two `u32` values, least significant first. `fill_bytes` and `try_fill_bytes` consume a whole
number of `u32` values, converting each `u32` to a byte slice in little-endian order. If the
requested byte length is not a multiple of 4, some bytes will be discarded.
See also [`BlockRng64`] which uses `u64` array buffers. Currently there is no direct support
for other buffer types.
For easy initialization `BlockRng` also implements [`SeedableRng`].
FIELDS
core
core: R
The *core* part of the RNG, implementing the `generate` function.
METHODS
impl<R: BlockRngCore> BlockRng<R>
new
pub fn new(core: R) -> BlockRng<R>
Create a new `BlockRng` from an existing RNG implementing `BlockRngCore`. Results will
be generated on first use.
index
pub fn index(&self) -> usize
Get the index into the result buffer.
If this is equal to or larger than the size of the result buffer then the buffer is
"empty" and `generate()` must be called to produce new results.
reset
pub fn reset(&mut self)
Reset the number of available results. This will force a new set of results to be
generated on next use.
generate_and_set
pub fn generate_and_set(&mut self, index: usize)
Generate a new set of results immediately, setting the index to the given value.
IMPLEMENTATIONS
Trait Implementations
BlockRngCore
impl<R: BlockRngCore + CryptoRng> CryptoRng for BlockRng<R>
BlockRngCore
impl<R: BlockRngCore + Debug> Debug for BlockRng<R>
BlockRngCore
impl<R: BlockRngCore + SeedableRng> SeedableRng for BlockRng<R>
BlockRngCore
impl<R: BlockRngCore<Item = u32>> RngCore for BlockRng<R>
where
    <R as BlockRngCore>::Results: AsRef<[u32]> + AsMut<[u32]>,
Clone
impl<R: Clone + BlockRngCore + ?Sized> Clone for BlockRng<R>
where
    R::Results: Clone,
Auto Trait Implementations
Sized
impl<R: ?Sized> RefUnwindSafe for BlockRng<R>
where
    R: RefUnwindSafe,
    <R as BlockRngCore>::Results: RefUnwindSafe,
Sized
impl<R: ?Sized> Send for BlockRng<R>
where
    R: Send,
    <R as BlockRngCore>::Results: Send,
Sized
impl<R: ?Sized> Sync for BlockRng<R>
where
    R: Sync,
    <R as BlockRngCore>::Results: Sync,
Sized
impl<R: ?Sized> Unpin for BlockRng<R>
where
    R: Unpin,
    <R as BlockRngCore>::Results: Unpin,
Sized
impl<R: ?Sized> UnwindSafe for BlockRng<R>
where
    R: UnwindSafe,
    <R as BlockRngCore>::Results: UnwindSafe,
Blanket Implementations
Any
impl<T> Any for T
where
    T: 'static + ?Sized,
Borrow
impl<T> Borrow<T> for T
where
    T: ?Sized,
BorrowMut
impl<T> BorrowMut<T> for T
where
    T: ?Sized,
From
impl<T> From<T> for T
Into
impl<T, U> Into<U> for T
where
    U: From<T>,
ToOwned
impl<T> ToOwned for T
where
    T: Clone,
TryFrom
impl<T, U> TryFrom<U> for T
where
    U: Into<T>,
TryInto
impl<T, U> TryInto<U> for T
where
    U: TryFrom<T>,

View File

@ -0,0 +1,120 @@
---
source: tests/output.rs
expression: "get_stdout(&[item])"
---
anyhow Trait anyhow::Context rusty-man
SYNOPSIS
pub trait Context<T, E>: Sealed {
fn context<C>(self, context: C) -> Result<T, Error>
    where
        C: Display + Send + Sync + 'static;
fn with_context<C, F>(self, f: F) -> Result<T, Error>
    where
        C: Display + Send + Sync + 'static,
        F: FnOnce() -> C;
}
DESCRIPTION
Provides the `context` method for `Result`.
This trait is sealed and cannot be implemented for types outside of `anyhow`.
# Example
use anyhow::{Context, Result};
use std::fs;
use std::path::PathBuf;
pub struct ImportantThing {
path: PathBuf,
}
impl ImportantThing {
pub fn detach(&mut self) -> Result<()> {...}
}
pub fn do_it(mut it: ImportantThing) -> Result<Vec<u8>> {
it.detach().context("Failed to detach the important thing")?;
let path = &it.path;
let content = fs::read(path)
.with_context(|| format!("Failed to read instrs from {}", path.display()))?;
Ok(content)
}
When printed, the outermost context would be printed first and the lower level underlying
causes would be enumerated below.
`Error: Failed to read instrs from ./path/to/instrs.json
Caused by:
No such file or directory (os error 2)
`
# Effect on downcasting
After attaching context of type `C` onto an error of type `E`, the resulting `anyhow::Error`
may be downcast to `C` **or** to `E`.
That is, in codebases that rely on downcasting, Anyhow's context supports both of the
following use cases:
* **Attaching context whose type is insignificant onto errors whose type is used in
downcasts.**
In other error libraries whose context is not designed this way, it can be risky to
introduce context to existing code because new context might break existing working
downcasts. In Anyhow, any downcast that worked before adding context will continue to work
after you add a context, so you should freely add human-readable context to errors wherever
it would be helpful.
use anyhow::{Context, Result};
fn do_it() -> Result<()> {
helper().context("Failed to complete the work")?;
...
}
fn main() {
let err = do_it().unwrap_err();
if let Some(e) = err.downcast_ref::<SuspiciousError>() {
// If helper() returned SuspiciousError, this downcast will
// correctly succeed even with the context in between.
}
}
* **Attaching context whose type is used in downcasts onto errors whose type is
insignificant.**
Some codebases prefer to use machine-readable context to categorize lower level errors in a
way that will be actionable to higher levels of the application.
use anyhow::{Context, Result};
fn do_it() -> Result<()> {
helper().context(HelperFailed)?;
...
}
fn main() {
let err = do_it().unwrap_err();
if let Some(e) = err.downcast_ref::<HelperFailed>() {
// If helper failed, this downcast will succeed because
// HelperFailed is the context that has been attached to
// that error.
}
}
METHODS
Required Methods
context
fn context<C>(self, context: C) -> Result<T, Error>
where
    C: Display + Send + Sync + 'static,
Wrap the error value with additional context.
with_context
fn with_context<C, F>(self, f: F) -> Result<T, Error>
where
    C: Display + Send + Sync + 'static,
    F: FnOnce() -> C,
Wrap the error value with additional context that is evaluated lazily only once an error
does occur.

View File

@ -0,0 +1,40 @@
---
source: tests/output.rs
expression: "get_stdout(&[item])"
---
log Trait log::Log rusty-man
SYNOPSIS
pub trait Log: Sync + Send {
fn enabled(&self, metadata: &Metadata) -> bool;
fn log(&self, record: &Record);
fn flush(&self);
}
DESCRIPTION
A trait encapsulating the operations required of a logger.
METHODS
Required Methods
enabled
fn enabled(&self, metadata: &Metadata) -> bool
Determines if a log message with the specified metadata would be logged.
This is used by the `log_enabled!` macro to allow callers to avoid expensive computation
of log message arguments if the message would be discarded anyway.
log
fn log(&self, record: &Record)
Logs the `Record`.
Note that `enabled` is *not* necessarily called before this method. Implementations of
`log` should perform all necessary filtering internally.
flush
fn flush(&self)
Flushes any buffered records.

View File

@ -0,0 +1,134 @@
---
source: tests/output.rs
expression: "get_stdout(&[item])"
---
rand_core Trait rand_core::RngCore rusty-man
SYNOPSIS
pub trait RngCore {
fn next_u32(&mut self) -> u32;
fn next_u64(&mut self) -> u64;
fn fill_bytes(&mut self, dest: &mut [u8]);
fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error>;
}
DESCRIPTION
The core of a random number generator.
This trait encapsulates the low-level functionality common to all generators, and is the "back
end", to be implemented by generators. End users should normally use the `Rng` trait from the
[`rand`][1] crate, which is automatically implemented for every type implementing `RngCore`.
Three different methods for generating random data are provided since the optimal
implementation of each is dependent on the type of generator. There is no required
relationship between the output of each; e.g. many implementations of `fill_bytes` consume a
whole number of `u32` or `u64` values and drop any remaining unused bytes.
The `try_fill_bytes` method is a variant of `fill_bytes` allowing error handling; it is not
deemed sufficiently useful to add equivalents for `next_u32` or `next_u64` since the latter
methods are almost always used with algorithmic generators (PRNGs), which are normally
infallible.
Algorithmic generators implementing [`SeedableRng`] should normally have *portable,
reproducible* output, i.e. fix Endianness when converting values to avoid platform
differences, and avoid making any changes which affect output (except by communicating that
the release has breaking changes).
Typically implementators will implement only one of the methods available in this trait
directly, then use the helper functions from the [`impls`] module to implement the other
methods.
It is recommended that implementations also implement:
* `Debug` with a custom implementation which *does not* print any internal state (at least,
[`CryptoRng`]s should not risk leaking state through `Debug`).
* `Serialize` and `Deserialize` (from Serde), preferably making Serde support optional at the
crate level in PRNG libs.
* `Clone`, if possible.
* *never* implement `Copy` (accidental copies may cause repeated values).
* *do not* implement `Default` for pseudorandom generators, but instead implement
[`SeedableRng`], to guide users towards proper seeding. External / hardware RNGs can choose
to implement `Default`.
* `Eq` and `PartialEq` could be implemented, but are probably not useful.
# Example
A simple example, obviously not generating very *random* output:
#![allow(dead_code)]
use rand_core::{RngCore, Error, impls};
struct CountingRng(u64);
impl RngCore for CountingRng {
fn next_u32(&mut self) -> u32 {
self.next_u64() as u32
}
fn next_u64(&mut self) -> u64 {
self.0 += 1;
self.0
}
fn fill_bytes(&mut self, dest: &mut [u8]) {
impls::fill_bytes_via_next(self, dest)
}
fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error> {
Ok(self.fill_bytes(dest))
}
}
[1] https://docs.rs/rand
METHODS
Required Methods
next_u32
fn next_u32(&mut self) -> u32
Return the next random `u32`.
RNGs must implement at least one method from this trait directly. In the case this
method is not implemented directly, it can be implemented using `self.next_u64() as u32`
or via `fill_bytes`.
next_u64
fn next_u64(&mut self) -> u64
Return the next random `u64`.
RNGs must implement at least one method from this trait directly. In the case this
method is not implemented directly, it can be implemented via `next_u32` or via
`fill_bytes`.
fill_bytes
fn fill_bytes(&mut self, dest: &mut [u8])
Fill `dest` with random data.
RNGs must implement at least one method from this trait directly. In the case this
method is not implemented directly, it can be implemented via `next_u*` or via
`try_fill_bytes`; if this generator can fail the implementation must choose how best to
handle errors here (e.g. panic with a descriptive message or log a warning and retry a
few times).
This method should guarantee that `dest` is entirely filled with new data, and may panic
if this is impossible (e.g. reading past the end of a file that is being used as the
source of randomness).
try_fill_bytes
fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error>
Fill `dest` entirely with random data.
This is the only method which allows an RNG to report errors while generating random
data thus making this the primary method implemented by external (true) RNGs (e.g.
`OsRng`) which can fail. It may be used directly to generate keys and to seed
(infallible) PRNGs.
Other than error handling, this method is identical to `fill_bytes`; thus this may be
implemented using `Ok(self.fill_bytes(dest))` or `fill_bytes` may be implemented with
`self.try_fill_bytes(dest).unwrap()` or more specific error handling.
IMPLEMENTATIONS
Trait Implementations
Read
impl Read for dyn RngCore

View File

@ -0,0 +1,150 @@
---
source: tests/output.rs
expression: "get_stdout(&[item])"
---
rand_core Trait rand_core::SeedableRng rusty-man
SYNOPSIS
pub trait SeedableRng: Sized {
type Seed: Sized + Default + AsMut<[u8]>;
fn from_seed(seed: Self::Seed) -> Self;
fn seed_from_u64(state: u64) -> Self { ... }
fn from_rng<R: RngCore>(rng: R) -> Result<Self, Error> { ... }
fn from_entropy() -> Self { ... }
}
DESCRIPTION
A random number generator that can be explicitly seeded.
This trait encapsulates the low-level functionality common to all pseudo-random number
generators (PRNGs, or algorithmic generators).
ASSOCIATED TYPES
Seed
type Seed: Sized + Default + AsMut<[u8]>
Seed type, which is restricted to types mutably-dereferencable as `u8` arrays (we
recommend `[u8; N]` for some `N`).
It is recommended to seed PRNGs with a seed of at least circa 100 bits, which means an
array of `[u8; 12]` or greater to avoid picking RNGs with partially overlapping periods.
For cryptographic RNG's a seed of 256 bits is recommended, `[u8; 32]`.
# Implementing `SeedableRng` for RNGs with large seeds
Note that the required traits `core::default::Default` and `core::convert::AsMut<u8>`
are not implemented for large arrays `[u8; N]` with `N` > 32. To be able to implement
the traits required by `SeedableRng` for RNGs with such large seeds, the newtype pattern
can be used:
use rand_core::SeedableRng;
const N: usize = 64;
pub struct MyRngSeed(pub [u8; N]);
pub struct MyRng(MyRngSeed);
impl Default for MyRngSeed {
fn default() -> MyRngSeed {
MyRngSeed([0; N])
}
}
impl AsMut<[u8]> for MyRngSeed {
fn as_mut(&mut self) -> &mut [u8] {
&mut self.0
}
}
impl SeedableRng for MyRng {
type Seed = MyRngSeed;
fn from_seed(seed: MyRngSeed) -> MyRng {
MyRng(seed)
}
}
METHODS
Required Methods
from_seed
fn from_seed(seed: Self::Seed) -> Self
Create a new PRNG using the given seed.
PRNG implementations are allowed to assume that bits in the seed are well distributed.
That means usually that the number of one and zero bits are roughly equal, and values
like 0, 1 and (size - 1) are unlikely. Note that many non-cryptographic PRNGs will show
poor quality output if this is not adhered to. If you wish to seed from simple numbers,
use `seed_from_u64` instead.
All PRNG implementations should be reproducible unless otherwise noted: given a fixed
`seed`, the same sequence of output should be produced on all runs, library versions and
architectures (e.g. check endianness). Any "value-breaking" changes to the generator
should require bumping at least the minor version and documentation of the change.
It is not required that this function yield the same state as a reference implementation
of the PRNG given equivalent seed; if necessary another constructor replicating
behaviour from a reference implementation can be added.
PRNG implementations should make sure `from_seed` never panics. In the case that some
special values (like an all zero seed) are not viable seeds it is preferable to map
these to alternative constant value(s), for example `0xBAD5EEDu32` or
`0x0DDB1A5E5BAD5EEDu64` ("odd biases? bad seed"). This is assuming only a small number
of values must be rejected.
Provided Methods
seed_from_u64
fn seed_from_u64(state: u64) -> Self
Create a new PRNG using a `u64` seed.
This is a convenience-wrapper around `from_seed` to allow construction of any
`SeedableRng` from a simple `u64` value. It is designed such that low Hamming Weight
numbers like 0 and 1 can be used and should still result in good, independent seeds to
the PRNG which is returned.
This **is not suitable for cryptography**, as should be clear given that the input size
is only 64 bits.
Implementations for PRNGs *may* provide their own implementations of this function, but
the default implementation should be good enough for all purposes. *Changing* the
implementation of this function should be considered a value-breaking change.
from_rng
fn from_rng<R: RngCore>(rng: R) -> Result<Self, Error>
Create a new PRNG seeded from another `Rng`.
This may be useful when needing to rapidly seed many PRNGs from a master PRNG, and to
allow forking of PRNGs. It may be considered deterministic.
The master PRNG should be at least as high quality as the child PRNGs. When seeding
non-cryptographic child PRNGs, we recommend using a different algorithm for the master
PRNG (ideally a CSPRNG) to avoid correlations between the child PRNGs. If this is not
possible (e.g. forking using small non-crypto PRNGs) ensure that your PRNG has a good
mixing function on the output or consider use of a hash function with `from_seed`.
Note that seeding `XorShiftRng` from another `XorShiftRng` provides an extreme example
of what can go wrong: the new PRNG will be a clone of the parent.
PRNG implementations are allowed to assume that a good RNG is provided for seeding, and
that it is cryptographically secure when appropriate. As of `rand` 0.7 / `rand_core`
0.5, implementations overriding this method should ensure the implementation satisfies
reproducibility (in prior versions this was not required).
from_entropy
fn from_entropy() -> Self
Creates a new instance of the RNG seeded via [`getrandom`][1].
This method is the recommended way to construct non-deterministic PRNGs since it is
convenient and secure.
In case the overhead of using [`getrandom`][2] to seed *many* PRNGs is an issue, one may
prefer to seed from a local PRNG, e.g. `from_rng(thread_rng()).unwrap()`.
# Panics
If [`getrandom`][3] is unable to provide secure entropy this method will panic.
[1] https://docs.rs/getrandom
[2] https://docs.rs/getrandom
[3] https://docs.rs/getrandom

View File

@ -0,0 +1,36 @@
---
source: tests/output.rs
expression: "get_stdout(&[item])"
---
anyhow Typedef anyhow::Result rusty-man
SYNOPSIS
type Result<T, E = Error> = Result<T, E>;
DESCRIPTION
`Result<T, Error>`
This is a reasonable return type to use throughout your application but also for `fn main`; if
you do, failures will be printed along with any [context][Context] and a backtrace if one was
captured.
`anyhow::Result` may be used with one *or* two type parameters.
use anyhow::Result;
fn demo1() -> Result<T> {...}
// ^ equivalent to std::result::Result<T, anyhow::Error>
fn demo2() -> Result<T, OtherError> {...}
// ^ equivalent to std::result::Result<T, OtherError>
# Example
use anyhow::Result;
fn main() -> Result<()> {
let config = std::fs::read_to_string("cluster.json")?;
let map: ClusterMap = serde_json::from_str(&config)?;
println!("cluster info: {:#?}", map);
Ok(())
}