asteroid_mq_model/
node.rs1use std::sync;
2
3use serde::{Deserialize, Serialize};
4use typeshare::typeshare;
5
6#[derive(Default, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
7#[typeshare(serialized_as = "string")]
8pub struct NodeId {
9 pub bytes: [u8; 16],
10}
11
12impl Serialize for NodeId {
13 fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
14 if serializer.is_human_readable() {
15 serializer.serialize_str(&self.to_base64())
16 } else {
17 <[u8; 16]>::serialize(&self.bytes, serializer)
18 }
19 }
20}
21
22impl<'de> Deserialize<'de> for NodeId {
23 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
24 where
25 D: serde::Deserializer<'de>,
26 {
27 use serde::de::Error;
28 if deserializer.is_human_readable() {
29 let s = <&'de str>::deserialize(deserializer)?;
30 NodeId::from_base64(s).map_err(D::Error::custom)
31 } else {
32 let bytes = <[u8; 16]>::deserialize(deserializer)?;
33 Ok(NodeId { bytes })
34 }
35 }
36}
37
38impl From<u64> for NodeId {
39 fn from(id: u64) -> Self {
40 Self::new_indexed(id)
41 }
42}
43
44impl std::fmt::Debug for NodeId {
45 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
46 f.debug_tuple("NodeId")
47 .field(&crate::util::dashed(&[
48 crate::util::hex(&self.bytes[0..1]),
49 crate::util::hex(&self.bytes[1..9]),
50 crate::util::hex(&self.bytes[9..10]),
51 crate::util::hex(&self.bytes[10..16]),
52 ]))
53 .finish()
54 }
55}
56
57impl std::fmt::Display for NodeId {
58 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
59 write!(
60 f,
61 "{}-{}-{}-{}",
62 crate::util::hex(&self.bytes[0..1]),
63 crate::util::hex(&self.bytes[1..9]),
64 crate::util::hex(&self.bytes[9..10]),
65 crate::util::hex(&self.bytes[10..16]),
66 )
67 }
68}
69
70impl NodeId {
71 pub const KIND_INDEXED: u8 = 0x00;
72 pub const KIND_SHA256: u8 = 0x01;
73 pub const KIND_SNOWFLAKE: u8 = 0x02;
74 pub const fn new_indexed(id: u64) -> Self {
75 let mut bytes = [0; 16];
76 bytes[0] = Self::KIND_INDEXED;
77 let index_part = id.to_be_bytes();
78 bytes[1] = index_part[0];
79 bytes[2] = index_part[1];
80 bytes[3] = index_part[2];
81 bytes[4] = index_part[3];
82 bytes[5] = index_part[4];
83 bytes[6] = index_part[5];
84 bytes[7] = index_part[6];
85 bytes[8] = index_part[7];
86 NodeId { bytes }
87 }
88 pub fn sha256(bytes: &[u8]) -> Self {
89 let dg = <sha2::Sha256 as sha2::Digest>::digest(bytes);
90 let mut bytes = [0; 16];
91 bytes[0] = Self::KIND_SHA256;
92 bytes[1..16].copy_from_slice(&dg.as_slice()[0..15]);
93 NodeId { bytes }
94 }
95 pub fn snowflake() -> NodeId {
96 static INSTANCE_ID: std::sync::atomic::AtomicU8 = std::sync::atomic::AtomicU8::new(0);
97 let dg = crate::util::executor_digest();
98 let mut bytes = [0; 16];
99 bytes[0] = Self::KIND_SNOWFLAKE;
100 bytes[1..9].copy_from_slice(&dg.to_be_bytes());
101 bytes[9..10].copy_from_slice(
102 &INSTANCE_ID
103 .fetch_add(1, sync::atomic::Ordering::SeqCst)
104 .to_be_bytes(),
105 );
106 bytes[10..16].copy_from_slice(&(crate::util::timestamp_sec()).to_be_bytes()[2..8]);
107 NodeId { bytes }
108 }
109 pub fn to_base64(&self) -> String {
110 use base64::Engine;
111 base64::engine::general_purpose::URL_SAFE.encode(self.bytes)
112 }
113 pub fn from_base64(s: &str) -> Result<Self, base64::DecodeError> {
114 use base64::Engine;
115 let id = base64::engine::general_purpose::URL_SAFE.decode(s)?;
116 let mut bytes = [0u8; 16];
117 bytes.copy_from_slice(&id);
118 Ok(Self { bytes })
119 }
120}