first-err
Find first Err in Iterator<Result<T, E>> and allow to iterating continuously.
This crate is specifically designed to replace the following pattern without allocation:
// iter: impl Iterator<Result<T, E>>
iter..map;
Features
- Find first
ErrinIterator<Result<T, E>>and allow to iterating continuously. - Speed: rough on par with hand write loop, use lazy evaluation and without alloc.
- Minimized:
no_std, noalloc, no dependency.
Getting Started
This crate help you to take first Err in a Result and keep iterating without
pay for allocation, here is a sample:
use FirstErr;
// Everything is Ok.
let ans =
.into_iter
.first_err_or_else;
assert_eq!;
// Contains some `Err` values.
let ans =
.into_iter
.first_err_or_else;
assert_eq!;
Please check API document for more detail.
Why
In Rust, I always encountered a kind of pattern which is I need to do something on all items within an iterator, and should also cancel as soon as possible if any error is found in current working layer. But, if no error found, the iterator should able to run continuously and allow me to do further transform.
The pattern typically looks as follows:
let array: = ;
let ans = fallible_sum;
assert_eq!;
In theory, this allocation is not necessary. We can just write that code as an old good loop:
let array: = ;
let ans = fallible_sum;
assert_eq!
Using a loop is not bad at all. But for some situation, I would like to keep iterator chainable as much as possible. This crate offers another approach to achieve it.
And even further, sometime life may not simple like previous example. consider is one:
// The second layer `Result` is usually created by further transform after the first layer
// `Result` be processed. But for the sake of simplicity, we've just use pre-defined values.
let array: = ;
let ans = fallible_sum;
assert_eq!;
Above logic may little hard to write as a loop without alloc. But this crate can do it for you:
let array: = ;
let ans = fallible_sum;
assert_eq!;
Benchmark
This crate's performance character is designed for rough on par with hand write loop. But compiler may do some better optimization for one or another in difference situations.
If you want do benchmark by yourself, use follows command:
And don't forget check which code I actual bench in benches folder.
Environment
- cpu: AMD Ryzen 5 3600 6-Core Processor
- os: Debian GNU/Linux 12 (bookworm)
- kernel: Linux 6.1.0-10-amd64 #1 SMP PREEMPT_DYNAMIC Debian 6.1.38-1 (2023-07-14)
- rustc: 1.72.0 (5680fa18f 2023-08-23)
- cargo: 1.72.0 (103a7ff2e 2023-08-15)
Results
test bench_100000_err_at_0______/__collect ... bench: 13 ns/iter (+/- 0)
test bench_100000_err_at_0______/_____loop ... bench: 1 ns/iter (+/- 0)
test bench_100000_err_at_0______/first_err ... bench: 1 ns/iter (+/- 0)
test bench_100000_err_at_1______/__collect ... bench: 19 ns/iter (+/- 0)
test bench_100000_err_at_1______/_____loop ... bench: 2 ns/iter (+/- 0)
test bench_100000_err_at_1______/first_err ... bench: 2 ns/iter (+/- 0)
test bench_100000_err_at_10_____/__collect ... bench: 82 ns/iter (+/- 1)
test bench_100000_err_at_10_____/_____loop ... bench: 3 ns/iter (+/- 0)
test bench_100000_err_at_10_____/first_err ... bench: 3 ns/iter (+/- 0)
test bench_100000_err_at_100____/__collect ... bench: 276 ns/iter (+/- 3)
test bench_100000_err_at_100____/_____loop ... bench: 9 ns/iter (+/- 0)
test bench_100000_err_at_100____/first_err ... bench: 7 ns/iter (+/- 0)
test bench_100000_err_at_1000___/__collect ... bench: 1027 ns/iter (+/- 39)
test bench_100000_err_at_1000___/_____loop ... bench: 66 ns/iter (+/- 1)
test bench_100000_err_at_1000___/first_err ... bench: 60 ns/iter (+/- 0)
test bench_100000_err_at_10000__/__collect ... bench: 6168 ns/iter (+/- 149)
test bench_100000_err_at_10000__/_____loop ... bench: 604 ns/iter (+/- 10)
test bench_100000_err_at_10000__/first_err ... bench: 605 ns/iter (+/- 1)
test bench_100000_err_at_99999__/__collect ... bench: 57075 ns/iter (+/- 344)
test bench_100000_err_at_99999__/_____loop ... bench: 5985 ns/iter (+/- 19)
test bench_100000_err_at_99999__/first_err ... bench: 5980 ns/iter (+/- 11)
test bench_100000_err_at_100000_/__collect ... bench: 60171 ns/iter (+/- 4611)
test bench_100000_err_at_100000_/_____loop ... bench: 5982 ns/iter (+/- 8)
test bench_100000_err_at_100000_/first_err ... bench: 5987 ns/iter (+/- 33)
test bench_100000_err_not_exists/__collect ... bench: 58460 ns/iter (+/- 343)
test bench_100000_err_not_exists/_____loop ... bench: 1 ns/iter (+/- 0)
test bench_100000_err_not_exists/first_err ... bench: 1 ns/iter (+/- 0)
test bench_100000_l1_err_at_0_______l2_err_at_1000___/__collect ... bench: 14 ns/iter (+/- 0)
test bench_100000_l1_err_at_0_______l2_err_at_1000___/_____loop ... bench: 3 ns/iter (+/- 0)
test bench_100000_l1_err_at_0_______l2_err_at_1000___/first_err ... bench: 6 ns/iter (+/- 0)
test bench_100000_l1_err_at_1_______l2_err_at_1000___/__collect ... bench: 21 ns/iter (+/- 0)
test bench_100000_l1_err_at_1_______l2_err_at_1000___/_____loop ... bench: 3 ns/iter (+/- 0)
test bench_100000_l1_err_at_1_______l2_err_at_1000___/first_err ... bench: 6 ns/iter (+/- 0)
test bench_100000_l1_err_at_10______l2_err_at_1000___/__collect ... bench: 95 ns/iter (+/- 1)
test bench_100000_l1_err_at_10______l2_err_at_1000___/_____loop ... bench: 13 ns/iter (+/- 0)
test bench_100000_l1_err_at_10______l2_err_at_1000___/first_err ... bench: 10 ns/iter (+/- 0)
test bench_100000_l1_err_at_100_____l2_err_at_1000___/__collect ... bench: 362 ns/iter (+/- 3)
test bench_100000_l1_err_at_100_____l2_err_at_1000___/_____loop ... bench: 110 ns/iter (+/- 2)
test bench_100000_l1_err_at_100_____l2_err_at_1000___/first_err ... bench: 72 ns/iter (+/- 0)
test bench_100000_l1_err_at_1000____l2_err_at_1000___/__collect ... bench: 1319 ns/iter (+/- 14)
test bench_100000_l1_err_at_1000____l2_err_at_1000___/_____loop ... bench: 1020 ns/iter (+/- 15)
test bench_100000_l1_err_at_1000____l2_err_at_1000___/first_err ... bench: 626 ns/iter (+/- 6)
test bench_100000_l1_err_at_10000___l2_err_at_1000___/__collect ... bench: 9883 ns/iter (+/- 633)
test bench_100000_l1_err_at_10000___l2_err_at_1000___/_____loop ... bench: 1115 ns/iter (+/- 5)
test bench_100000_l1_err_at_10000___l2_err_at_1000___/first_err ... bench: 774 ns/iter (+/- 52)
test bench_100000_l1_err_at_99999___l2_err_at_1000___/__collect ... bench: 94787 ns/iter (+/- 330)
test bench_100000_l1_err_at_99999___l2_err_at_1000___/_____loop ... bench: 1780 ns/iter (+/- 4)
test bench_100000_l1_err_at_99999___l2_err_at_1000___/first_err ... bench: 2123 ns/iter (+/- 5)
test bench_100000_l1_err_at_100000__l2_err_at_1000___/__collect ... bench: 96160 ns/iter (+/- 161)
test bench_100000_l1_err_at_100000__l2_err_at_1000___/_____loop ... bench: 1787 ns/iter (+/- 3)
test bench_100000_l1_err_at_100000__l2_err_at_1000___/first_err ... bench: 2118 ns/iter (+/- 123)
test bench_100000_l1_err_at_none____l2_err_at_0______/__collect ... bench: 89359 ns/iter (+/- 309)
test bench_100000_l1_err_at_none____l2_err_at_0______/_____loop ... bench: 3 ns/iter (+/- 0)
test bench_100000_l1_err_at_none____l2_err_at_0______/first_err ... bench: 6 ns/iter (+/- 0)
test bench_100000_l1_err_at_none____l2_err_at_1______/__collect ... bench: 89247 ns/iter (+/- 211)
test bench_100000_l1_err_at_none____l2_err_at_1______/_____loop ... bench: 4 ns/iter (+/- 0)
test bench_100000_l1_err_at_none____l2_err_at_1______/first_err ... bench: 6 ns/iter (+/- 0)
test bench_100000_l1_err_at_none____l2_err_at_10_____/__collect ... bench: 89375 ns/iter (+/- 131)
test bench_100000_l1_err_at_none____l2_err_at_10_____/_____loop ... bench: 13 ns/iter (+/- 0)
test bench_100000_l1_err_at_none____l2_err_at_10_____/first_err ... bench: 11 ns/iter (+/- 0)
test bench_100000_l1_err_at_none____l2_err_at_100____/__collect ... bench: 89231 ns/iter (+/- 161)
test bench_100000_l1_err_at_none____l2_err_at_100____/_____loop ... bench: 106 ns/iter (+/- 0)
test bench_100000_l1_err_at_none____l2_err_at_100____/first_err ... bench: 73 ns/iter (+/- 2)
test bench_100000_l1_err_at_none____l2_err_at_1000___/__collect ... bench: 89982 ns/iter (+/- 84)
test bench_100000_l1_err_at_none____l2_err_at_1000___/_____loop ... bench: 966 ns/iter (+/- 0)
test bench_100000_l1_err_at_none____l2_err_at_1000___/first_err ... bench: 616 ns/iter (+/- 3)
test bench_100000_l1_err_at_none____l2_err_at_10000__/__collect ... bench: 96578 ns/iter (+/- 352)
test bench_100000_l1_err_at_none____l2_err_at_10000__/_____loop ... bench: 9569 ns/iter (+/- 47)
test bench_100000_l1_err_at_none____l2_err_at_10000__/first_err ... bench: 6058 ns/iter (+/- 8)
test bench_100000_l1_err_at_none____l2_err_at_99999__/__collect ... bench: 173763 ns/iter (+/- 646)
test bench_100000_l1_err_at_none____l2_err_at_99999__/_____loop ... bench: 95541 ns/iter (+/- 490)
test bench_100000_l1_err_at_none____l2_err_at_99999__/first_err ... bench: 60196 ns/iter (+/- 539)
test bench_100000_l1_err_at_none____l2_err_at_100000_/__collect ... bench: 167568 ns/iter (+/- 1418)
test bench_100000_l1_err_at_none____l2_err_at_100000_/_____loop ... bench: 95596 ns/iter (+/- 178)
test bench_100000_l1_err_at_none____l2_err_at_100000_/first_err ... bench: 50250 ns/iter (+/- 3401)
test bench_100000_err_not_exists_____________________/__collect ... bench: 182434 ns/iter (+/- 1666)
test bench_100000_err_not_exists_____________________/_____loop ... bench: 95634 ns/iter (+/- 82)
test bench_100000_err_not_exists_____________________/first_err ... bench: 5 ns/iter (+/- 0)
Licence
MIT