drawbridge_type/digest/
algorithm.rs

1// SPDX-License-Identifier: Apache-2.0
2
3use super::{Error, Reader, Writer};
4
5use std::str::FromStr;
6
7use serde::{de::Visitor, Deserialize, Serialize};
8use sha2::{digest::DynDigest, Digest as _, Sha224, Sha256, Sha384, Sha512};
9
10/// A hashing algorithm
11#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
12#[non_exhaustive]
13pub enum Algorithm {
14    Sha224,
15    Sha256,
16    Sha384,
17    Sha512,
18}
19
20impl AsRef<str> for Algorithm {
21    fn as_ref(&self) -> &str {
22        match self {
23            Self::Sha224 => "sha-224",
24            Self::Sha256 => "sha-256",
25            Self::Sha384 => "sha-384",
26            Self::Sha512 => "sha-512",
27        }
28    }
29}
30
31impl std::fmt::Display for Algorithm {
32    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
33        f.write_str(self.as_ref())
34    }
35}
36
37impl FromStr for Algorithm {
38    type Err = Error;
39
40    fn from_str(s: &str) -> Result<Self, Self::Err> {
41        match &*s.to_ascii_lowercase() {
42            "sha-224" => Ok(Self::Sha224),
43            "sha-256" => Ok(Self::Sha256),
44            "sha-384" => Ok(Self::Sha384),
45            "sha-512" => Ok(Self::Sha512),
46            _ => Err(Error::UnknownAlgorithm),
47        }
48    }
49}
50
51impl Serialize for Algorithm {
52    fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
53        self.as_ref().serialize(serializer)
54    }
55}
56
57impl<'de> Deserialize<'de> for Algorithm {
58    fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
59        struct StrVisitor;
60
61        impl Visitor<'_> for StrVisitor {
62            type Value = Algorithm;
63
64            fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
65                formatter.write_str("a Content-Digest algorithm name")
66            }
67
68            fn visit_str<E: serde::de::Error>(self, v: &str) -> Result<Self::Value, E> {
69                v.parse().map_err(|_| E::custom("unknown algorithm"))
70            }
71
72            fn visit_string<E: serde::de::Error>(self, v: String) -> Result<Self::Value, E> {
73                v.parse().map_err(|_| E::custom("unknown algorithm"))
74            }
75        }
76
77        deserializer.deserialize_str(StrVisitor)
78    }
79}
80
81impl Algorithm {
82    pub(crate) fn hasher(self) -> Box<dyn DynDigest> {
83        match self {
84            Self::Sha224 => Box::new(Sha224::new()),
85            Self::Sha256 => Box::new(Sha256::new()),
86            Self::Sha384 => Box::new(Sha384::new()),
87            Self::Sha512 => Box::new(Sha512::new()),
88        }
89    }
90
91    /// Creates a reader instance
92    pub fn reader<T>(&self, reader: T) -> Reader<T> {
93        Reader::new(reader, [*self])
94    }
95
96    /// Creates a writer instance
97    pub fn writer<T>(&self, writer: T) -> Writer<T> {
98        Writer::new(writer, [*self])
99    }
100}