Skip to main content

worker/
crypto.rs

1use js_sys::{ArrayBuffer, Uint8Array};
2use wasm_bindgen::prelude::*;
3use wasm_bindgen_futures::JsFuture;
4
5use crate::send::SendFuture;
6
7/// A Rust-friendly wrapper around the non-standard [crypto.DigestStream](https://developers.cloudflare.com/workers/runtime-apis/web-crypto/#constructors) API
8///
9/// Example usage:
10/// ```rust
11/// let digest_stream = DigestStream::new(DigestStreamAlgorithm::Sha256);
12///
13/// // create a ReadableStream from a string
14/// let mut req_init = web_sys::RequestInit::new();
15/// req_init.method("POST");
16/// req_init.body(Some(&JsValue::from_str("foo")));
17/// let req = web_sys::Request::new_with_str_and_init("http://internal", &req_init).unwrap();
18/// let body = req.body().unwrap();
19///
20/// // just kick the promise off to the background, we'll await the digest itself
21/// // since this is piped to a JS readable stream, call .raw() to get the underlying JS object
22/// let _ = body.pipe_to(digest_stream.raw());
23///
24/// let bytes:Vec<u8> = digest_stream.digest().await.unwrap().to_vec();
25/// ```
26#[derive(Debug)]
27pub struct DigestStream {
28    inner: worker_sys::DigestStream,
29}
30
31impl DigestStream {
32    pub fn new(algo: DigestStreamAlgorithm) -> Self {
33        Self {
34            inner: worker_sys::DigestStream::new(algo.as_str()),
35        }
36    }
37
38    pub async fn digest(&self) -> Result<Uint8Array, crate::Error> {
39        let fut = SendFuture::new(JsFuture::from(self.inner.digest()));
40        let buffer: ArrayBuffer = fut.await?.unchecked_into();
41        Ok(Uint8Array::new(&buffer))
42    }
43
44    pub fn raw(&self) -> &worker_sys::DigestStream {
45        &self.inner
46    }
47}
48
49// from https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/digest#syntax
50#[derive(Debug, Clone, Copy, PartialEq)]
51pub enum DigestStreamAlgorithm {
52    Sha1,
53    Sha256,
54    Sha384,
55    Sha512,
56}
57
58impl DigestStreamAlgorithm {
59    pub fn as_str(self) -> &'static str {
60        match self {
61            Self::Sha1 => "SHA-1",
62            Self::Sha256 => "SHA-256",
63            Self::Sha384 => "SHA-384",
64            Self::Sha512 => "SHA-512",
65        }
66    }
67}