openmina_core/requests/
request_id.rs

1use 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}