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:
parent
17e407d6b1
commit
1a518d7509
@ -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
21
.reuse/dep5
Normal 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
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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-man’s 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-man’s 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 don’t 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
172
Cargo.lock
generated
@ -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"
|
||||
|
@ -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
119
tests/output.rs
Normal 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",
|
||||
];
|
19
tests/snapshots/output__constant_log_static_max_level.snap
Normal file
19
tests/snapshots/output__constant_log_static_max_level.snap
Normal 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.
|
||||
|
||||
|
178
tests/snapshots/output__enum_log_level.snap
Normal file
178
tests/snapshots/output__enum_log_level.snap
Normal 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>,
|
||||
|
||||
|
54
tests/snapshots/output__examples_mod_anyhow.snap
Normal file
54
tests/snapshots/output__examples_mod_anyhow.snap
Normal 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));
|
||||
|
||||
|
63
tests/snapshots/output__examples_mod_log.snap
Normal file
63
tests/snapshots/output__examples_mod_log.snap
Normal 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))
|
||||
}
|
||||
|
||||
|
@ -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))
|
||||
}
|
||||
}
|
||||
|
||||
|
15
tests/snapshots/output__fn_log_logger.snap
Normal file
15
tests/snapshots/output__fn_log_logger.snap
Normal 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.
|
||||
|
||||
|
31
tests/snapshots/output__fn_log_set_logger_racy.snap
Normal file
31
tests/snapshots/output__fn_log_set_logger_racy.snap
Normal 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).
|
||||
|
||||
|
30
tests/snapshots/output__macro_anyhow_anyhow.snap
Normal file
30
tests/snapshots/output__macro_anyhow_anyhow.snap
Normal 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));
|
||||
}
|
||||
// ...
|
||||
}
|
||||
|
||||
|
33
tests/snapshots/output__macro_anyhow_ensure.snap
Normal file
33
tests/snapshots/output__macro_anyhow_ensure.snap
Normal 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);
|
||||
|
||||
|
24
tests/snapshots/output__macro_log_debug.snap
Normal file
24
tests/snapshots/output__macro_log_debug.snap
Normal 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);
|
||||
|
||||
|
134
tests/snapshots/output__mod_anyhow.snap
Normal file
134
tests/snapshots/output__mod_anyhow.snap
Normal 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>`
|
||||
|
||||
|
299
tests/snapshots/output__mod_log.snap
Normal file
299
tests/snapshots/output__mod_log.snap
Normal 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.
|
||||
|
||||
|
55
tests/snapshots/output__mod_rand_core.snap
Normal file
55
tests/snapshots/output__mod_rand_core.snap
Normal 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.
|
||||
|
||||
|
356
tests/snapshots/output__struct_anyhow_error.snap
Normal file
356
tests/snapshots/output__struct_anyhow_error.snap
Normal 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>,
|
||||
|
||||
|
142
tests/snapshots/output__struct_log_metadata.snap
Normal file
142
tests/snapshots/output__struct_log_metadata.snap
Normal 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>,
|
||||
|
||||
|
163
tests/snapshots/output__struct_rand_core_block_blockrng.snap
Normal file
163
tests/snapshots/output__struct_rand_core_block_blockrng.snap
Normal 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>,
|
||||
|
||||
|
120
tests/snapshots/output__trait_anyhow_context.snap
Normal file
120
tests/snapshots/output__trait_anyhow_context.snap
Normal 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.
|
||||
|
||||
|
40
tests/snapshots/output__trait_log_log.snap
Normal file
40
tests/snapshots/output__trait_log_log.snap
Normal 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.
|
||||
|
||||
|
134
tests/snapshots/output__trait_rand_core_rngcore.snap
Normal file
134
tests/snapshots/output__trait_rand_core_rngcore.snap
Normal 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
|
||||
|
||||
|
150
tests/snapshots/output__trait_rand_core_seedablerng.snap
Normal file
150
tests/snapshots/output__trait_rand_core_seedablerng.snap
Normal 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
|
||||
|
||||
|
36
tests/snapshots/output__type_anyhow_result.snap
Normal file
36
tests/snapshots/output__type_anyhow_result.snap
Normal 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(())
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user