asteroid_mq_model/
endpoint.rs

1use serde::{Deserialize, Serialize};
2
3use typeshare::typeshare;
4
5#[derive(Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
6#[typeshare(serialized_as = "String")]
7#[cfg_attr(feature = "bincode", derive(bincode::Decode, bincode::Encode))]
8pub struct EndpointAddr {
9    pub bytes: [u8; 16],
10}
11
12impl From<[u8; 16]> for EndpointAddr {
13    fn from(bytes: [u8; 16]) -> Self {
14        Self { bytes }
15    }
16}
17impl From<EndpointAddr> for [u8; 16] {
18    fn from(val: EndpointAddr) -> Self {
19        val.bytes
20    }
21}
22
23impl Serialize for EndpointAddr {
24    fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
25        if serializer.is_human_readable() {
26            use base64::Engine;
27            serializer.serialize_str(&base64::engine::general_purpose::URL_SAFE.encode(self.bytes))
28        } else {
29            <[u8; 16]>::serialize(&self.bytes, serializer)
30        }
31    }
32}
33
34impl<'de> Deserialize<'de> for EndpointAddr {
35    fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
36        if deserializer.is_human_readable() {
37            use base64::Engine;
38            use serde::de::Error;
39            let s = String::deserialize(deserializer)?;
40            let bytes = base64::engine::general_purpose::URL_SAFE
41                .decode(s.as_bytes())
42                .map_err(D::Error::custom)?;
43            if bytes.len() != 16 {
44                return Err(D::Error::custom("invalid length"));
45            }
46            let mut addr = [0; 16];
47            addr.copy_from_slice(&bytes);
48            Ok(Self { bytes: addr })
49        } else {
50            let bytes = <[u8; 16]>::deserialize(deserializer)?;
51            Ok(Self { bytes })
52        }
53    }
54}
55
56impl std::fmt::Debug for EndpointAddr {
57    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
58        f.debug_tuple("EndpointAddr")
59            .field(&crate::util::dashed(&[
60                crate::util::hex(&self.bytes[0..8]),
61                crate::util::hex(&self.bytes[8..12]),
62                crate::util::hex(&self.bytes[12..16]),
63            ]))
64            .finish()
65    }
66}
67
68impl EndpointAddr {
69    pub fn new_snowflake() -> Self {
70        thread_local! {
71            static COUNTER: std::cell::Cell<u32> = const { std::cell::Cell::new(0) };
72        }
73        let timestamp = crate::util::timestamp_sec();
74        let counter = COUNTER.with(|c| {
75            let v = c.get();
76            c.set(v.wrapping_add(1));
77            v
78        });
79        let eid = crate::util::executor_digest() as u32;
80        let mut bytes = [0; 16];
81        bytes[0..8].copy_from_slice(&timestamp.to_be_bytes());
82        bytes[8..12].copy_from_slice(&counter.to_be_bytes());
83        bytes[12..16].copy_from_slice(&eid.to_be_bytes());
84        Self { bytes }
85    }
86    pub fn hash64(&self) -> u64 {
87        use std::hash::{DefaultHasher, Hasher};
88        let mut hasher = DefaultHasher::new();
89        Hasher::write(&mut hasher, &self.bytes);
90        Hasher::finish(&hasher)
91    }
92}