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
//! A collection of various utilities for asyncifying things, publicly exposed for convenience of
//! those consuming Bindle as a Rust SDK
use std::io::Write;
use std::pin::Pin;
use std::sync::Mutex;
use std::task::{Context, Poll};
use sha2::{Digest, Sha256};
/// A wrapper to implement `AsyncWrite` on Sha256
pub struct AsyncSha256 {
inner: Mutex<Sha256>,
}
impl Default for AsyncSha256 {
fn default() -> Self {
AsyncSha256::new()
}
}
impl AsyncSha256 {
/// Equivalent to the `Sha256::new()` function
pub fn new() -> Self {
AsyncSha256 {
inner: Mutex::new(Sha256::new()),
}
}
/// Consumes self and returns the bare Sha256. This should only be called once you are done
/// writing. This will only return an error if for some reason the underlying mutex was poisoned
pub fn into_inner(self) -> std::sync::LockResult<Sha256> {
self.inner.into_inner()
}
}
impl tokio::io::AsyncWrite for AsyncSha256 {
fn poll_write(
self: Pin<&mut Self>,
_cx: &mut Context<'_>,
buf: &[u8],
) -> Poll<std::result::Result<usize, std::io::Error>> {
// Because the hasher is all in memory, we only need to make sure only one caller at a time
// can write using the mutex
let mut inner = match self.inner.try_lock() {
Ok(l) => l,
Err(_) => return Poll::Pending,
};
Poll::Ready(inner.write(buf))
}
fn poll_flush(
self: Pin<&mut Self>,
_cx: &mut Context<'_>,
) -> Poll<std::result::Result<(), std::io::Error>> {
let mut inner = match self.inner.try_lock() {
Ok(l) => l,
Err(_) => return Poll::Pending,
};
Poll::Ready(inner.flush())
}
fn poll_shutdown(
self: Pin<&mut Self>,
cx: &mut Context<'_>,
) -> Poll<std::result::Result<(), std::io::Error>> {
// There are no actual shutdown tasks to perform, so just flush things as defined in the
// trait documentation
self.poll_flush(cx)
}
}