message_io/network/
resource_id.rs1use std::sync::{
2 atomic::{Ordering, AtomicUsize},
3};
4
5#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
7pub enum ResourceType {
8 Local,
9 Remote,
10}
11
12#[derive(Clone, Copy, PartialEq, Eq, Hash)]
18pub struct ResourceId {
19 id: usize,
20}
21
22impl ResourceId {
23 const ADAPTER_ID_POS: usize = 0;
24 const RESOURCE_TYPE_POS: usize = 7;
25 const BASE_VALUE_POS: usize = 8;
26
27 const ADAPTER_ID_MASK: u8 = 0b01111111; const BASE_VALUE_MASK: usize = 0xFFFFFFFFFFFFFF00_u64 as usize; pub const MAX_BASE_VALUE: usize = (Self::BASE_VALUE_MASK >> Self::BASE_VALUE_POS);
31 pub const MAX_ADAPTER_ID: u8 = (Self::ADAPTER_ID_MASK >> Self::ADAPTER_ID_POS);
32 pub const MAX_ADAPTERS: usize = Self::MAX_ADAPTER_ID as usize + 1;
33
34 fn new(adapter_id: u8, resource_type: ResourceType, base_value: usize) -> Self {
35 debug_assert!(
36 adapter_id <= Self::MAX_ADAPTER_ID,
37 "The adapter_id must be less than {}",
38 Self::MAX_ADAPTER_ID + 1,
39 );
40
41 debug_assert!(
42 base_value <= Self::MAX_BASE_VALUE,
43 "The base_value must be less than {}",
44 Self::MAX_BASE_VALUE + 1,
45 );
46
47 let resource_type = match resource_type {
48 ResourceType::Local => 1 << Self::RESOURCE_TYPE_POS,
49 ResourceType::Remote => 0,
50 };
51
52 Self {
53 id: ((adapter_id as usize) << Self::ADAPTER_ID_POS)
54 | resource_type
55 | (base_value << Self::BASE_VALUE_POS),
56 }
57 }
58
59 pub fn raw(&self) -> usize {
61 self.id
62 }
63
64 pub fn resource_type(&self) -> ResourceType {
66 if self.id & (1 << Self::RESOURCE_TYPE_POS) != 0 {
67 ResourceType::Local
68 }
69 else {
70 ResourceType::Remote
71 }
72 }
73
74 pub fn is_local(&self) -> bool {
76 self.resource_type() == ResourceType::Local
77 }
78
79 pub fn is_remote(&self) -> bool {
81 self.resource_type() == ResourceType::Remote
82 }
83
84 pub fn adapter_id(&self) -> u8 {
88 ((self.id & Self::ADAPTER_ID_MASK as usize) >> Self::ADAPTER_ID_POS) as u8
89 }
90
91 pub fn base_value(&self) -> usize {
93 (self.id & Self::BASE_VALUE_MASK) >> Self::BASE_VALUE_POS
94 }
95}
96
97impl From<usize> for ResourceId {
98 fn from(raw: usize) -> Self {
99 Self { id: raw }
100 }
101}
102
103impl std::fmt::Display for ResourceId {
104 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
105 let resource_type = match self.resource_type() {
106 ResourceType::Local => "L",
107 ResourceType::Remote => "R",
108 };
109 write!(f, "[{}.{}.{}]", self.adapter_id(), resource_type, self.base_value())
110 }
111}
112
113impl std::fmt::Debug for ResourceId {
114 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
115 write!(f, "{self}")
116 }
117}
118
119pub struct ResourceIdGenerator {
121 last: AtomicUsize,
122 adapter_id: u8,
123 resource_type: ResourceType,
124}
125
126impl ResourceIdGenerator {
127 pub fn new(adapter_id: u8, resource_type: ResourceType) -> Self {
128 Self { last: AtomicUsize::new(0), adapter_id, resource_type }
129 }
130
131 pub fn generate(&self) -> ResourceId {
134 let last = self.last.fetch_add(1, Ordering::SeqCst);
135 ResourceId::new(self.adapter_id, self.resource_type, last)
136 }
137}
138
139#[cfg(test)]
140mod tests {
141 use super::*;
142
143 #[test]
144 fn base_value() {
145 let low_base_value = 0;
146
147 let resource_id = ResourceId::new(1, ResourceType::Local, low_base_value);
148 assert_eq!(low_base_value, resource_id.base_value());
149
150 let high_base_value = ResourceId::MAX_BASE_VALUE;
151
152 let resource_id = ResourceId::new(1, ResourceType::Local, high_base_value);
153 assert_eq!(high_base_value, resource_id.base_value());
154 }
155
156 #[test]
157 fn resource_type() {
158 let resource_id = ResourceId::new(0, ResourceType::Local, 0);
159 assert_eq!(ResourceType::Local, resource_id.resource_type());
160 assert_eq!(0, resource_id.adapter_id());
161
162 let resource_id = ResourceId::new(0, ResourceType::Remote, 0);
163 assert_eq!(ResourceType::Remote, resource_id.resource_type());
164 assert_eq!(0, resource_id.adapter_id());
165 }
166
167 #[test]
168 fn adapter_id() {
169 let adapter_id = ResourceId::MAX_ADAPTER_ID;
170
171 let resource_id = ResourceId::new(adapter_id, ResourceType::Local, 0);
172 assert_eq!(adapter_id, resource_id.adapter_id());
173 assert_eq!(ResourceType::Local, resource_id.resource_type());
174
175 let resource_id = ResourceId::new(adapter_id, ResourceType::Remote, 0);
176 assert_eq!(adapter_id, resource_id.adapter_id());
177 assert_eq!(ResourceType::Remote, resource_id.resource_type());
178 }
179}