1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
//! A crate that provides a [`read_chunks`][ReadExt::read_chunks] extension to types implementing [`std::io::Read`] (including unsized ones).
//!
//! # Motivation
//! Sometimes you may be reading a file to the end to do processing on it, but do not want the
//! entire file in memory. Sometimes [`bytes`] is the answer to this, but if you wish to
//! process larger chunks of data at once, maybe for SIMD, that cannot be used.
//!
//! Calling into [`read`] repeatedly to get a chunk until the end is tedious as it may return
//! significantly less bytes than you expected (slowing down bulk processing), or encounter a recoverable
//! error, and handling that yourself is a chore.
//!
//! A more correct implementation may be to use [`read_exact`] for that purpose, as it
//! guarantees the whole chunk. The problem with that is at the end of the file you will lose the
//! data that was read, as [`read_exact`] leaves the buffer contents unspecified at EOF.
//!
//! The method implemented in this crate addresses both problems, it guarantees the full buffer size
//! requested whenever it can, handles recoverable errors, and at the end of the Read stream will
//! simply return a final smaller buffer before returning [`None`] to signal the end of the stream was
//! detected. That is to say, you will always get the full buffer length until the last chunk where
//! you get a tail, similar to [`slice::chunks`][slice::chunks], but for a [`Read`].
//!
//! # Usage
//! Simply add `use read_chunks::ReadExt;` to your module and use the new [`read_chunks`][ReadExt::read_chunks] method that
//! should appear on any type implementing [`Read`].
//!
//! # Standard Library Inclusion
//! This crate was written because it is useful to me for hashing files incrementally with SIMD
//! optimized hashing functions like [blake3](https://crates.io/crates/blake3). This crate may
//! attempt to be added to the rust standard library if it is seen as generally useful and people
//! agree with the design. For this reason, the api may break in order to prototype
//! what could work best for the standard library.
//!
//! In particular, a `read_chunks_exact` api may be desirable that mirrors [`slice::chunks_exact`],
//! giving the remainder in a separate function, and asserting the length of the buffer in the main
//! iterator remains constant,
//!
//! It may also be put into question if the return type should be `&[u8]` or `&mut [u8]`. Currently
//! a `&mut [u8]` is returned because that is allowed by the implementation, but whether that makes
//! sense as an api is unknown at this time.
//!
//! [`bytes`]: Read::bytes
//! [`read`]: Read::read
//! [`read_exact`]: Read::read_exact
use ;
/// Trait that extends any type implementing [`Read`] with [`ReadChunks`]
/// Tries to read to fill up the whole buffer, returning Ok(n) even if the function only managed to fill up n
/// bytes which was not the length of buf (this implies an EOF was reached)
Sized>
/// A lending iterator that allows reading chunks of `n` bytes at a time from a reader.