winget_types/shared/
sha_256.rs

1use std::{
2    io,
3    io::{Error, ErrorKind, Read},
4    str::FromStr,
5};
6
7use derive_more::Display;
8use heapless::String;
9use serde::{Deserialize, Serialize};
10use sha2::{Digest, Sha256};
11
12// 256 bits / 4 bits per hex character
13const SHA256_DIGEST_LEN: usize = 256 / 0xFu8.count_ones() as usize;
14
15#[derive(Clone, Debug, Display, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize, Deserialize)]
16pub struct Sha256String(String<SHA256_DIGEST_LEN>);
17
18impl Sha256String {
19    pub fn from_hasher(data: &[u8]) -> Result<Self, base16ct::Error> {
20        let mut encode_buf = [0; SHA256_DIGEST_LEN];
21        let sha_256 = base16ct::upper::encode_str(data, &mut encode_buf)?;
22        Ok(Self(
23            String::<SHA256_DIGEST_LEN>::from_str(sha_256).unwrap_or_else(|()| unreachable!()),
24        ))
25    }
26
27    pub fn from_reader<R: Read>(mut reader: R) -> io::Result<Self> {
28        let mut hasher = Sha256::new();
29        let mut buffer = [0; 1 << 12];
30
31        loop {
32            let count = reader.read(&mut buffer)?;
33            if count == 0 {
34                break;
35            }
36            hasher.update(&buffer[..count]);
37        }
38
39        Self::from_hasher(&hasher.finalize()).map_err(|err| Error::new(ErrorKind::Other, err))
40    }
41}
42
43impl Default for Sha256String {
44    fn default() -> Self {
45        Self(std::iter::repeat_n('0', SHA256_DIGEST_LEN).collect::<_>())
46    }
47}