1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
use crate::identifier::derive::{digest::DigestDerivator, Derivator};
use base64::decode_config;
use borsh::{BorshDeserialize, BorshSerialize};
use serde::{Deserialize, Deserializer, Serialize, Serializer};
use std::str::FromStr;

use super::error::Error;
use super::Derivable;

/// Digest based identifier
#[derive(Debug, PartialEq, Clone, Eq, Hash, BorshSerialize, BorshDeserialize, PartialOrd)]
pub struct DigestIdentifier {
    pub derivator: DigestDerivator,
    pub digest: Vec<u8>,
}

impl DigestIdentifier {
    pub fn from_serializable<S: Serialize>(data: &S) -> Result<Self, Error> {
        let bytes = serde_json::to_vec(data)?;
        let bytes = DigestDerivator::Blake3_256.digest(&bytes);
        Ok(DigestIdentifier::new(DigestDerivator::Blake3_256, &bytes))
    }

    pub fn from_serializable_borsh<T: BorshSerialize>(
        serializable: T,
    ) -> Result<Self, crate::commons::errors::Error> {
        let bytes = match serializable.try_to_vec() {
            Ok(bytes) => bytes,
            Err(_) => return Err(crate::commons::errors::Error::BorshSerializationFailed),
        };
        let bytes = DigestDerivator::Blake3_256.digest(&bytes);
        Ok(DigestIdentifier::new(DigestDerivator::Blake3_256, &bytes))
    }

    pub fn new(derivator: DigestDerivator, digest: &[u8]) -> Self {
        Self {
            derivator,
            digest: digest.to_vec(),
        }
    }
}

impl Default for DigestIdentifier {
    fn default() -> Self {
        Self {
            derivator: DigestDerivator::Blake3_256,
            digest: vec![],
        }
    }
}

/// From string to KeyIdentifier
impl FromStr for DigestIdentifier {
    type Err = Error;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        if s.is_empty() {
            return Ok(DigestIdentifier::default());
        }
        let code = DigestDerivator::from_str(s)?;
        if s.len() == code.material_len() {
            Ok(Self::new(
                code,
                &decode_config(&s[code.code_len()..code.material_len()], base64::URL_SAFE)?,
            ))
        } else {
            Err(Error::SemanticError(format!(
                "Incorrect Prefix Length: {}",
                s
            )))
        }
    }
}

impl Derivable for DigestIdentifier {
    fn derivative(&self) -> Vec<u8> {
        self.digest.to_owned()
    }
    fn derivation_code(&self) -> String {
        self.derivator.to_str()
    }
}

impl Serialize for DigestIdentifier {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        serializer.serialize_str(&self.to_str())
    }
}

impl<'de> Deserialize<'de> for DigestIdentifier {
    fn deserialize<D>(deserializer: D) -> Result<DigestIdentifier, D::Error>
    where
        D: Deserializer<'de>,
    {
        let s = <std::string::String as Deserialize>::deserialize(deserializer)?;
        if s.is_empty() {
            Ok(DigestIdentifier::default())
        } else {
            DigestIdentifier::from_str(&s).map_err(serde::de::Error::custom)
        }
    }
}

#[cfg(test)]
mod tests {

    use super::DigestIdentifier;

    #[test]
    fn test_digest_identifier_serde() {
        let id = DigestIdentifier::default();
        let id_str = serde_json::to_string_pretty(&id).unwrap();
        let new_id: DigestIdentifier = serde_json::from_str(&id_str).unwrap();
        assert_eq!(id, new_id);
    }
}