claim169_core/model/
biometrics.rs

1use serde::{Deserialize, Serialize};
2
3use super::enums::{BiometricFormat, BiometricSubFormat};
4
5/// A single biometric data entry
6#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
7#[serde(rename_all = "camelCase")]
8pub struct Biometric {
9    /// Binary biometric data (key 0)
10    #[serde(with = "serde_bytes_base64")]
11    pub data: Vec<u8>,
12
13    /// Data format: Image, Template, Sound, BioHash (key 1)
14    #[serde(skip_serializing_if = "Option::is_none")]
15    pub format: Option<BiometricFormat>,
16
17    /// Data sub-format depending on format type (key 2)
18    #[serde(skip_serializing_if = "Option::is_none")]
19    pub sub_format: Option<BiometricSubFormat>,
20
21    /// Biometric data issuer (key 3)
22    #[serde(skip_serializing_if = "Option::is_none")]
23    pub issuer: Option<String>,
24}
25
26impl Biometric {
27    pub fn new(data: Vec<u8>) -> Self {
28        Self {
29            data,
30            format: None,
31            sub_format: None,
32            issuer: None,
33        }
34    }
35
36    pub fn with_format(mut self, format: BiometricFormat) -> Self {
37        self.format = Some(format);
38        self
39    }
40
41    pub fn with_sub_format(mut self, sub_format: BiometricSubFormat) -> Self {
42        self.sub_format = Some(sub_format);
43        self
44    }
45
46    pub fn with_issuer(mut self, issuer: impl Into<String>) -> Self {
47        self.issuer = Some(issuer.into());
48        self
49    }
50}
51
52/// Custom serde module for base64-encoding byte arrays in JSON
53mod serde_bytes_base64 {
54    use serde::{Deserialize, Deserializer, Serializer};
55
56    pub fn serialize<S>(bytes: &[u8], serializer: S) -> Result<S::Ok, S::Error>
57    where
58        S: Serializer,
59    {
60        use base64::Engine;
61        let b64 = base64::engine::general_purpose::STANDARD.encode(bytes);
62        serializer.serialize_str(&b64)
63    }
64
65    pub fn deserialize<'de, D>(deserializer: D) -> Result<Vec<u8>, D::Error>
66    where
67        D: Deserializer<'de>,
68    {
69        use base64::Engine;
70        let s = String::deserialize(deserializer)?;
71        base64::engine::general_purpose::STANDARD
72            .decode(&s)
73            .map_err(serde::de::Error::custom)
74    }
75}
76
77#[cfg(test)]
78mod tests {
79    use super::*;
80
81    #[test]
82    fn test_biometric_builder() {
83        let bio = Biometric::new(vec![1, 2, 3])
84            .with_format(BiometricFormat::Image)
85            .with_sub_format(BiometricSubFormat::Image(
86                super::super::enums::ImageSubFormat::Jpeg,
87            ))
88            .with_issuer("VendorA");
89
90        assert_eq!(bio.data, vec![1, 2, 3]);
91        assert_eq!(bio.format, Some(BiometricFormat::Image));
92        assert_eq!(bio.issuer, Some("VendorA".to_string()));
93    }
94
95    #[test]
96    fn test_biometric_json_serialization() {
97        let bio = Biometric::new(vec![0x48, 0x65, 0x6c, 0x6c, 0x6f]); // "Hello"
98
99        let json = serde_json::to_string(&bio).unwrap();
100        assert!(json.contains("SGVsbG8=")); // Base64 of "Hello"
101
102        let deserialized: Biometric = serde_json::from_str(&json).unwrap();
103        assert_eq!(deserialized.data, bio.data);
104    }
105}