tycho_network/overlay/
overlay_id.rs1use std::borrow::Borrow;
2use std::str::FromStr;
3
4use rand::Rng;
5use tl_proto::{TlRead, TlWrite};
6
7#[derive(Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord, TlRead, TlWrite)]
8#[repr(transparent)]
9pub struct OverlayId(pub [u8; 32]);
10
11impl OverlayId {
12 pub const fn wrap(bytes: &[u8; 32]) -> &Self {
13 unsafe { &*(bytes as *const [u8; 32]).cast::<Self>() }
15 }
16
17 #[inline]
18 pub fn as_bytes(&self) -> &[u8; 32] {
19 &self.0
20 }
21
22 #[inline]
23 pub fn to_bytes(self) -> [u8; 32] {
24 self.0
25 }
26}
27
28impl Borrow<[u8; 32]> for OverlayId {
29 #[inline]
30 fn borrow(&self) -> &[u8; 32] {
31 &self.0
32 }
33}
34
35impl<'a> TlRead<'a> for &'a OverlayId {
36 type Repr = tl_proto::Boxed;
37
38 #[inline]
39 fn read_from(packet: &mut &'a [u8]) -> tl_proto::TlResult<Self> {
40 <_>::read_from(packet).map(OverlayId::wrap)
41 }
42}
43
44impl rand::distr::Distribution<OverlayId> for rand::distr::StandardUniform {
45 #[inline]
46 fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> OverlayId {
47 OverlayId(rand::distr::StandardUniform.sample(rng))
48 }
49}
50
51impl std::fmt::Display for OverlayId {
52 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
53 let len = f.precision().unwrap_or(32);
54 for byte in self.0.iter().take(len) {
55 write!(f, "{byte:02x}")?;
56 }
57 Ok(())
58 }
59}
60
61impl std::fmt::Debug for OverlayId {
62 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
63 write!(f, "OverlayId({self})")
64 }
65}
66
67impl FromStr for OverlayId {
68 type Err = hex::FromHexError;
69
70 fn from_str(s: &str) -> Result<Self, Self::Err> {
71 let mut overlay_id = OverlayId([0; 32]);
72 hex::decode_to_slice(s, &mut overlay_id.0).map(|_| overlay_id)
73 }
74}
75
76impl serde::Serialize for OverlayId {
77 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
78 where
79 S: serde::Serializer,
80 {
81 if serializer.is_human_readable() {
82 serializer.collect_str(self)
83 } else {
84 self.0.serialize(serializer)
85 }
86 }
87}
88
89impl<'de> serde::Deserialize<'de> for OverlayId {
90 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
91 where
92 D: serde::Deserializer<'de>,
93 {
94 if deserializer.is_human_readable() {
95 deserializer.deserialize_str(tycho_util::serde_helpers::StrVisitor::new())
96 } else {
97 <[u8; 32]>::deserialize(deserializer).map(Self)
98 }
99 }
100}
101
102#[cfg(test)]
103mod tests {
104 use super::*;
105
106 #[test]
107 fn serde() {
108 const SOME_ID: &str = "5d09fe251943525a30f471791d5b4fea1298613f52ad2ad6d985fed05eb00533";
109
110 let from_json: OverlayId = serde_json::from_str(&format!("\"{SOME_ID}\"")).unwrap();
111 let from_str = OverlayId::from_str(SOME_ID).unwrap();
112 assert_eq!(from_json, from_str);
113
114 let to_json = serde_json::to_string(&from_json).unwrap();
115 let from_json: OverlayId = serde_json::from_str(&to_json).unwrap();
116 assert_eq!(from_json, from_str);
117 }
118}