openmina_core/requests/
request_id.rs1use std::{fmt, marker::PhantomData};
2
3pub trait RequestIdType {
4 fn request_id_type() -> &'static str;
5}
6
7pub struct RequestId<T> {
8 locator: usize,
9 counter: usize,
10 _phantom_request_type: PhantomData<T>,
11}
12
13impl<T> RequestId<T> {
14 pub(super) fn new(locator: usize, counter: usize) -> Self {
15 Self {
16 locator,
17 counter,
18 _phantom_request_type: Default::default(),
19 }
20 }
21
22 pub fn new_unchecked(locator: usize, counter: usize) -> Self {
23 Self {
24 locator,
25 counter,
26 _phantom_request_type: Default::default(),
27 }
28 }
29
30 pub fn locator(&self) -> usize {
31 self.locator
32 }
33
34 pub fn counter(&self) -> usize {
35 self.counter
36 }
37}
38
39mod serde_impl {
40 use serde::{Deserialize, Serialize};
41
42 use super::RequestIdType;
43
44 #[derive(Serialize, Deserialize)]
45 struct RequestId {
46 locator: usize,
47 counter: usize,
48 }
49
50 impl<T: RequestIdType> Serialize for super::RequestId<T> {
51 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
52 where
53 S: serde::Serializer,
54 {
55 if serializer.is_human_readable() {
56 return Serialize::serialize(&self.to_string(), serializer);
57 }
58 let id = RequestId {
59 locator: self.locator,
60 counter: self.counter,
61 };
62 Serialize::serialize(&id, serializer)
63 }
64 }
65
66 impl<'de, T: RequestIdType> Deserialize<'de> for super::RequestId<T> {
67 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
68 where
69 D: serde::Deserializer<'de>,
70 {
71 if deserializer.is_human_readable() {
72 let s: &str = Deserialize::deserialize(deserializer)?;
73 return s.parse().or(Err(serde::de::Error::custom("invalid id")));
74 }
75 let id = RequestId::deserialize(deserializer)?;
76 Ok(Self {
77 locator: id.locator,
78 counter: id.counter,
79 _phantom_request_type: Default::default(),
80 })
81 }
82 }
83}
84
85impl<T> Eq for RequestId<T> {}
86impl<T> PartialEq for RequestId<T> {
87 fn eq(&self, other: &Self) -> bool {
88 self.cmp(other).is_eq()
89 }
90}
91
92impl<T> Ord for RequestId<T> {
93 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
94 self.counter
95 .cmp(&other.counter)
96 .then(self.locator.cmp(&other.locator))
97 }
98}
99impl<T> PartialOrd for RequestId<T> {
100 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
101 Some(self.cmp(other))
102 }
103}
104
105impl<T> std::hash::Hash for RequestId<T> {
106 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
107 self.counter.hash(state);
108 self.locator.hash(state);
109 }
110}
111
112impl<T> std::str::FromStr for RequestId<T> {
113 type Err = ();
114
115 fn from_str(s: &str) -> Result<Self, Self::Err> {
116 let (locator, counter) = s.split_once('_').ok_or(())?;
117 Ok(Self {
118 locator: locator.parse().or(Err(()))?,
119 counter: counter.parse().or(Err(()))?,
120 _phantom_request_type: Default::default(),
121 })
122 }
123}
124
125impl<T> fmt::Display for RequestId<T> {
126 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
127 write!(f, "{}_{}", self.locator, self.counter)
128 }
129}
130
131impl<T: RequestIdType> fmt::Debug for RequestId<T> {
132 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
133 write!(f, "{}({})", T::request_id_type(), self)
134 }
135}
136
137impl<T> Clone for RequestId<T> {
138 fn clone(&self) -> Self {
139 *self
140 }
141}
142
143impl<T> Copy for RequestId<T> {}
144
145mod measurement {
146 use malloc_size_of::{MallocSizeOf, MallocSizeOfOps};
147
148 use super::RequestId;
149
150 impl<T> MallocSizeOf for RequestId<T> {
151 fn size_of(&self, _ops: &mut MallocSizeOfOps) -> usize {
152 0
153 }
154 }
155}