assemblyline_models/types/
sha1.rs1use serde_with::{DeserializeFromStr, SerializeDisplay};
2use struct_metadata::Described;
3
4use crate::{random_hex, ElasticMeta, ModelError};
5
6
7
8#[derive(Debug, SerializeDisplay, DeserializeFromStr, Described, Clone, PartialEq, Eq)]
10#[metadata_type(ElasticMeta)]
11#[metadata(normalizer="lowercase_normalizer")]
12pub struct Sha1(String);
13
14impl std::fmt::Display for Sha1 {
15 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
16 f.write_str(&self.0)
17 }
18}
19
20impl std::ops::Deref for Sha1 {
21 type Target = str;
22
23 fn deref(&self) -> &Self::Target {
24 &self.0
25 }
26}
27
28pub fn is_sha1(hex: &str) -> bool {
29 hex.len() == 40 && hex.chars().all(|c|c.is_ascii_hexdigit())
30}
31
32impl std::str::FromStr for Sha1 {
33 type Err = ModelError;
34
35 fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
36 let hex = s.trim().to_ascii_lowercase();
37 if !is_sha1(&hex) {
38 return Err(ModelError::InvalidSha1(hex))
39 }
40 Ok(Sha1(hex))
41 }
42}
43
44#[cfg(feature = "rand")]
45impl rand::distr::Distribution<Sha1> for rand::distr::StandardUniform {
46 fn sample<R: rand::prelude::Rng + ?Sized>(&self, rng: &mut R) -> Sha1 {
47 Sha1(random_hex(rng, 40))
48 }
49}