···11//! Stream utilities.
2233+mod hash_reader;
44+35use std::collections::VecDeque;
46use std::future::Future;
57use std::marker::Unpin;
68use std::pin::Pin;
77-use std::sync::Arc;
88-use std::task::{Context, Poll};
991010use async_stream::try_stream;
1111use bytes::{Bytes, BytesMut};
1212-use digest::{Digest, Output as DigestOutput};
1312use futures::stream::{BoxStream, Stream, StreamExt};
1414-use tokio::io::{AsyncRead, AsyncReadExt, ReadBuf};
1515-use tokio::sync::OnceCell;
1313+use tokio::io::{AsyncRead, AsyncReadExt};
1614use tokio::task::spawn;
17151818-/// Stream filter that hashes the bytes that have been read.
1919-///
2020-/// The hash is finalized when EOF is reached.
2121-pub struct StreamHasher<R: AsyncRead + Unpin, D: Digest + Unpin> {
2222- inner: R,
2323- digest: Option<D>,
2424- bytes_read: usize,
2525- finalized: Arc<OnceCell<(DigestOutput<D>, usize)>>,
2626-}
1616+pub use hash_reader::HashReader;
27172818/// Merge chunks lazily into a continuous stream.
2919///
···9888 Box::pin(s)
9989}
10090101101-impl<R: AsyncRead + Unpin, D: Digest + Unpin> StreamHasher<R, D> {
102102- pub fn new(inner: R, digest: D) -> (Self, Arc<OnceCell<(DigestOutput<D>, usize)>>) {
103103- let finalized = Arc::new(OnceCell::new());
104104-105105- (
106106- Self {
107107- inner,
108108- digest: Some(digest),
109109- bytes_read: 0,
110110- finalized: finalized.clone(),
111111- },
112112- finalized,
113113- )
114114- }
115115-}
116116-117117-impl<R: AsyncRead + Unpin, D: Digest + Unpin> AsyncRead for StreamHasher<R, D> {
118118- fn poll_read(
119119- mut self: Pin<&mut Self>,
120120- cx: &mut Context<'_>,
121121- buf: &mut ReadBuf<'_>,
122122- ) -> Poll<tokio::io::Result<()>> {
123123- let old_filled = buf.filled().len();
124124- let r = Pin::new(&mut self.inner).poll_read(cx, buf);
125125- let read_len = buf.filled().len() - old_filled;
126126-127127- match r {
128128- Poll::Ready(Ok(())) => {
129129- if read_len == 0 {
130130- // EOF
131131- if let Some(digest) = self.digest.take() {
132132- self.finalized
133133- .set((digest.finalize(), self.bytes_read))
134134- .expect("Hash has already been finalized");
135135- }
136136- } else {
137137- // Read something
138138- let digest = self.digest.as_mut().expect("Stream has data after EOF");
139139-140140- let filled = buf.filled();
141141- digest.update(&filled[filled.len() - read_len..]);
142142- self.bytes_read += read_len;
143143- }
144144- }
145145- Poll::Ready(Err(_)) => {
146146- assert!(read_len == 0);
147147- }
148148- Poll::Pending => {}
149149- }
150150-151151- r
152152- }
153153-}
154154-15591/// Greedily reads from a stream to fill a buffer.
15692pub async fn read_chunk_async<S: AsyncRead + Unpin + Send>(
15793 stream: &mut S,
···175111 use async_stream::stream;
176112 use bytes::{BufMut, BytesMut};
177113 use futures::future;
178178- use tokio::io::AsyncReadExt;
179179-180180- #[tokio::test]
181181- async fn test_stream_hasher() {
182182- let expected = b"hello world";
183183- let expected_sha256 =
184184- hex::decode("b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9")
185185- .unwrap();
186186-187187- let (mut read, finalized) = StreamHasher::new(expected.as_slice(), sha2::Sha256::new());
188188- assert!(finalized.get().is_none());
189189-190190- // force multiple reads
191191- let mut buf = vec![0u8; 100];
192192- let mut bytes_read = 0;
193193- bytes_read += read
194194- .read(&mut buf[bytes_read..bytes_read + 5])
195195- .await
196196- .unwrap();
197197- bytes_read += read
198198- .read(&mut buf[bytes_read..bytes_read + 5])
199199- .await
200200- .unwrap();
201201- bytes_read += read
202202- .read(&mut buf[bytes_read..bytes_read + 5])
203203- .await
204204- .unwrap();
205205- bytes_read += read
206206- .read(&mut buf[bytes_read..bytes_read + 5])
207207- .await
208208- .unwrap();
209209-210210- assert_eq!(expected.len(), bytes_read);
211211- assert_eq!(expected, &buf[..bytes_read]);
212212-213213- let (hash, count) = finalized.get().expect("Hash wasn't finalized");
214214-215215- assert_eq!(expected_sha256.as_slice(), hash.as_slice());
216216- assert_eq!(expected.len(), *count);
217217- eprintln!("finalized = {:x?}", finalized);
218218- }
219114220115 #[tokio::test]
221116 async fn test_merge_chunks() {
+2-2
attic/src/lib.rs
···2121pub mod chunking;
2222pub mod error;
2323pub mod hash;
2424+#[cfg(feature = "io")]
2525+pub mod io;
2426pub mod mime;
2527pub mod nix_store;
2628pub mod signing;
2727-#[cfg(feature = "io")]
2828-pub mod io;
2929#[cfg(target_family = "unix")]
3030pub mod testing;
3131#[cfg(feature = "tokio")]