assemblyline_models/types/
sha256.rs

1use std::str::FromStr;
2
3use serde_with::{DeserializeFromStr, SerializeDisplay};
4use struct_metadata::Described;
5
6use crate::{ElasticMeta, ModelError};
7
8
9/// sha256 hash of a file
10#[derive(Debug, SerializeDisplay, DeserializeFromStr, Described, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
11#[metadata(normalizer="lowercase_normalizer")]
12#[metadata_type(ElasticMeta)]
13pub struct Sha256(String);
14
15// impl Described<ElasticMeta> for internment::ArcIntern<String> {
16//     fn metadata() -> struct_metadata::Descriptor<ElasticMeta> {
17//         String::metadata()
18//     }
19// }
20
21impl std::fmt::Display for Sha256 {
22    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
23        f.write_str(&self.0)
24    }
25}
26
27impl std::ops::Deref for Sha256 {
28    type Target = str;
29
30    fn deref(&self) -> &Self::Target {
31        &self.0
32    }
33}
34
35pub fn is_sha256(hex: &str) -> bool {
36    hex.len() == 64 && hex.chars().all(|c|c.is_ascii_hexdigit())
37}
38
39impl FromStr for Sha256 {
40    type Err = ModelError;
41
42    fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
43        let hex = s.trim().to_ascii_lowercase();
44        if !is_sha256(&hex) {
45            return Err(ModelError::InvalidSha256(hex))
46        }
47        Ok(Sha256(hex))
48    }
49}
50
51impl TryFrom<&[u8]> for Sha256 {
52    type Error = ModelError;
53
54    fn try_from(value: &[u8]) -> Result<Self, Self::Error> {
55        Self::from_str(&hex::encode(value))
56    }
57}
58
59
60#[cfg(feature = "rand")]
61impl rand::distr::Distribution<Sha256> for rand::distr::StandardUniform {
62    fn sample<R: rand::prelude::Rng + ?Sized>(&self, rng: &mut R) -> Sha256 {
63        use crate::random_hex;
64
65        Sha256(random_hex(rng, 64))
66    }
67}