harmos_domain/message/
identity.rs1use std::fmt;
20use serde::{Deserialize, Deserializer, Serialize, Serializer};
22macro_rules! identity {
29 ($ty:ident) => {
30 impl fmt::Display for $ty {
31 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
32 for byte in self.0 {
33 write!(formatter, "{byte:02x}")?;
34 }
35 Ok(())
36 }
37 }
38
39 impl Serialize for $ty {
40 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
41 if serializer.is_human_readable() { serializer.collect_str(self) } else { self.0.serialize(serializer) }
42 }
43 }
44
45 impl<'de> Deserialize<'de> for $ty {
46 fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
47 if !deserializer.is_human_readable() {
48 return <[u8; 32]>::deserialize(deserializer).map(Self);
49 }
50 let text = String::deserialize(deserializer)?;
51 if text.len() != 64 || !text.bytes().all(|byte| byte.is_ascii_digit() || (b'a'..=b'f').contains(&byte)) {
52 return Err(serde::de::Error::custom("identity must be 64 lowercase hexadecimal digits"));
53 }
54 let mut bytes = [0; 32];
55 for (index, byte) in bytes.iter_mut().enumerate() {
56 *byte = u8::from_str_radix(&text[index * 2..index * 2 + 2], 16).map_err(serde::de::Error::custom)?;
57 }
58 Ok(Self(bytes))
59 }
60 }
61 };
62}
63
64identity!(Fingerprint);
65identity!(Digest);
66
67#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
72pub struct Fingerprint(pub [u8; 32]);
73
74#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
75pub struct Digest(pub [u8; 32]);
76
77#[cfg(test)]
90mod tests {
91 use crate::{Message, Portable};
92
93 #[test]
94 fn float_identity_vectors() {
95 assert_eq!(f64::fingerprint().to_string(), "c2be9d59dd899a0610a0733ea228e01124f88493c4769be406a3298311a6c907");
96 for (bits, expected) in [
97 (0, "35f3767c67d333522f9e1bbc6af672f58ab5b5ce79a682eb73b07509495ef0bf"),
98 (0x8000000000000000, "119a7f9f7f4abd037483acd7fc28dff27e8790b537c553e6d95c274dfc4c6cc3"),
99 (0x7ff8000000000001, "f79e77241c991154c361b16a433784f1bacbe34570cbf8afda3f0543a3112802"),
100 (0x7ff8000000000002, "73786941275e993a7bc30aa530a9b6a7c765139f8e47a576c8e71b5d99989a83"),
101 ] {
102 let value = f64::from_bits(bits);
103 assert_eq!(value.digest().to_string(), expected);
104 assert_eq!(f64::decode(&value.encode()).unwrap().to_bits(), bits);
105 }
106 let fingerprint = f64::fingerprint();
107 assert_eq!(postcard::to_allocvec(&fingerprint).unwrap(), fingerprint.0);
108 assert_eq!(serde_json::from_str::<super::Fingerprint>(&serde_json::to_string(&fingerprint).unwrap()).unwrap(), fingerprint);
109 }
110}