1use serde::{de, Deserialize, Deserializer, Serialize, Serializer};
4use std::fmt;
5
6pub const MAX_ROLE_INDEX: u32 = 9_999;
8pub const MAX_LOOP_COUNT: u32 = 1_000_000;
10pub const MAX_MESSAGE_LEN_BYTES: u32 = 16 * 1024 * 1024;
12pub const MAX_QUEUE_CAPACITY_COUNT: u32 = 65_536;
14pub const MAX_CHANNEL_CAPACITY_BITS: u32 = 1_024;
16pub const MAX_STORE_CAPACITY_COUNT: u32 = 1_000_000;
18
19#[derive(Debug, Clone, PartialEq, Eq)]
20pub struct CountError {
21 pub kind: &'static str,
22 pub value: u64,
23 pub min: u64,
24 pub max: u64,
25}
26
27impl fmt::Display for CountError {
28 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
29 write!(
30 f,
31 "invalid {}: {} (expected {}..={})",
32 self.kind, self.value, self.min, self.max
33 )
34 }
35}
36
37impl std::error::Error for CountError {}
38
39macro_rules! define_count {
40 ($name:ident, $doc:literal, min = $min:expr, max = $max:expr) => {
41 #[doc = $doc]
42 #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
43 pub struct $name(u32);
44
45 impl $name {
46 pub const MIN: u32 = $min;
47 pub const MAX: u32 = $max;
48
49 pub fn new(value: u32) -> Result<Self, CountError> {
55 Self::try_new(value)
56 }
57
58 #[allow(clippy::as_conversions)] pub fn try_new(value: u32) -> Result<Self, CountError> {
65 if !(Self::MIN..=Self::MAX).contains(&value) {
66 return Err(CountError {
67 kind: stringify!($name),
68 value: value as u64,
69 min: Self::MIN as u64,
70 max: Self::MAX as u64,
71 });
72 }
73 Ok(Self(value))
74 }
75
76 #[must_use]
77 pub const fn get(self) -> u32 {
78 self.0
79 }
80
81 #[must_use]
82 #[allow(clippy::as_conversions)] pub const fn as_usize(self) -> usize {
84 self.0 as usize
85 }
86 }
87
88 impl TryFrom<u32> for $name {
89 type Error = CountError;
90
91 fn try_from(value: u32) -> Result<Self, Self::Error> {
92 Self::try_new(value)
93 }
94 }
95
96 impl TryFrom<usize> for $name {
97 type Error = CountError;
98
99 #[allow(clippy::as_conversions)] fn try_from(value: usize) -> Result<Self, Self::Error> {
101 let value_u32 = u32::try_from(value).map_err(|_| CountError {
102 kind: stringify!($name),
103 value: value as u64,
104 min: Self::MIN as u64,
105 max: Self::MAX as u64,
106 })?;
107 Self::try_new(value_u32)
108 }
109 }
110
111 impl From<$name> for u32 {
112 fn from(value: $name) -> Self {
113 value.0
114 }
115 }
116
117 impl fmt::Display for $name {
118 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
119 write!(f, "{}", self.0)
120 }
121 }
122
123 impl Serialize for $name {
124 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
125 where
126 S: Serializer,
127 {
128 serializer.serialize_u32(self.0)
129 }
130 }
131
132 impl<'de> Deserialize<'de> for $name {
133 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
134 where
135 D: Deserializer<'de>,
136 {
137 let value = u32::deserialize(deserializer)?;
138 $name::try_new(value).map_err(de::Error::custom)
139 }
140 }
141 };
142}
143
144define_count!(
145 RoleIndex,
146 "Index for a role instance (0-based).",
147 min = 0,
148 max = MAX_ROLE_INDEX
149);
150define_count!(
151 LoopCount,
152 "Count of loop iterations (bounded).",
153 min = 0,
154 max = MAX_LOOP_COUNT
155);
156define_count!(
157 MessageLenBytes,
158 "On-wire message length in bytes.",
159 min = 0,
160 max = MAX_MESSAGE_LEN_BYTES
161);
162define_count!(
163 QueueCapacity,
164 "Queue capacity (entries).",
165 min = 1,
166 max = MAX_QUEUE_CAPACITY_COUNT
167);
168define_count!(
169 ChannelCapacity,
170 "Channel capacity (bits).",
171 min = 0,
172 max = MAX_CHANNEL_CAPACITY_BITS
173);
174define_count!(
175 StoreCapacity,
176 "Content store capacity (entries).",
177 min = 1,
178 max = MAX_STORE_CAPACITY_COUNT
179);