1use core::fmt;
14
15macro_rules! define_msg_types {
16 ($( ($variant:ident, $name:literal) ),+ $(,)?) => {
17 #[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
32 #[non_exhaustive]
33 pub enum MsgType {
34 $(
35 #[doc = concat!("`", $name, "`")]
36 $variant,
37 )+
38 }
39
40 impl MsgType {
41 const ALL: &'static [MsgType] = &[ $( MsgType::$variant, )+ ];
42 const NAMES: &'static [&'static str] = &[ $( $name, )+ ];
43 }
44 };
45}
46
47define_msg_types![
48 (Unknown, "UNKNOWN"),
49 (ReqMcGet, "REQ_MC_GET"),
50 (ReqMcGets, "REQ_MC_GETS"),
51 (ReqMcDelete, "REQ_MC_DELETE"),
52 (ReqMcCas, "REQ_MC_CAS"),
53 (ReqMcSet, "REQ_MC_SET"),
54 (ReqMcAdd, "REQ_MC_ADD"),
55 (ReqMcReplace, "REQ_MC_REPLACE"),
56 (ReqMcAppend, "REQ_MC_APPEND"),
57 (ReqMcPrepend, "REQ_MC_PREPEND"),
58 (ReqMcIncr, "REQ_MC_INCR"),
59 (ReqMcDecr, "REQ_MC_DECR"),
60 (ReqMcTouch, "REQ_MC_TOUCH"),
61 (ReqMcQuit, "REQ_MC_QUIT"),
62 (RspMcNum, "RSP_MC_NUM"),
63 (RspMcStored, "RSP_MC_STORED"),
64 (RspMcNotStored, "RSP_MC_NOT_STORED"),
65 (RspMcExists, "RSP_MC_EXISTS"),
66 (RspMcNotFound, "RSP_MC_NOT_FOUND"),
67 (RspMcEnd, "RSP_MC_END"),
68 (RspMcValue, "RSP_MC_VALUE"),
69 (RspMcDeleted, "RSP_MC_DELETED"),
70 (RspMcTouched, "RSP_MC_TOUCHED"),
71 (RspMcError, "RSP_MC_ERROR"),
72 (RspMcClientError, "RSP_MC_CLIENT_ERROR"),
73 (RspMcServerError, "RSP_MC_SERVER_ERROR"),
74 (ReqRedisDel, "REQ_REDIS_DEL"),
75 (ReqRedisExists, "REQ_REDIS_EXISTS"),
76 (ReqRedisExpire, "REQ_REDIS_EXPIRE"),
77 (ReqRedisExpireat, "REQ_REDIS_EXPIREAT"),
78 (ReqRedisPexpire, "REQ_REDIS_PEXPIRE"),
79 (ReqRedisPexpireat, "REQ_REDIS_PEXPIREAT"),
80 (ReqRedisPersist, "REQ_REDIS_PERSIST"),
81 (ReqRedisPttl, "REQ_REDIS_PTTL"),
82 (ReqRedisScan, "REQ_REDIS_SCAN"),
83 (ReqRedisSort, "REQ_REDIS_SORT"),
84 (ReqRedisTtl, "REQ_REDIS_TTL"),
85 (ReqRedisType, "REQ_REDIS_TYPE"),
86 (ReqRedisAppend, "REQ_REDIS_APPEND"),
87 (ReqRedisBitcount, "REQ_REDIS_BITCOUNT"),
88 (ReqRedisBitpos, "REQ_REDIS_BITPOS"),
89 (ReqRedisDecr, "REQ_REDIS_DECR"),
90 (ReqRedisDecrby, "REQ_REDIS_DECRBY"),
91 (ReqRedisDump, "REQ_REDIS_DUMP"),
92 (ReqRedisGet, "REQ_REDIS_GET"),
93 (ReqRedisGetbit, "REQ_REDIS_GETBIT"),
94 (ReqRedisGetrange, "REQ_REDIS_GETRANGE"),
95 (ReqRedisGetset, "REQ_REDIS_GETSET"),
96 (ReqRedisIncr, "REQ_REDIS_INCR"),
97 (ReqRedisIncrby, "REQ_REDIS_INCRBY"),
98 (ReqRedisIncrbyfloat, "REQ_REDIS_INCRBYFLOAT"),
99 (ReqRedisMset, "REQ_REDIS_MSET"),
100 (ReqRedisMget, "REQ_REDIS_MGET"),
101 (ReqRedisPsetex, "REQ_REDIS_PSETEX"),
102 (ReqRedisRestore, "REQ_REDIS_RESTORE"),
103 (ReqRedisSet, "REQ_REDIS_SET"),
104 (ReqRedisSetbit, "REQ_REDIS_SETBIT"),
105 (ReqRedisSetex, "REQ_REDIS_SETEX"),
106 (ReqRedisSetnx, "REQ_REDIS_SETNX"),
107 (ReqRedisSetrange, "REQ_REDIS_SETRANGE"),
108 (ReqRedisStrlen, "REQ_REDIS_STRLEN"),
109 (ReqRedisHdel, "REQ_REDIS_HDEL"),
110 (ReqRedisHexists, "REQ_REDIS_HEXISTS"),
111 (ReqRedisHget, "REQ_REDIS_HGET"),
112 (ReqRedisHgetall, "REQ_REDIS_HGETALL"),
113 (ReqRedisHincrby, "REQ_REDIS_HINCRBY"),
114 (ReqRedisHincrbyfloat, "REQ_REDIS_HINCRBYFLOAT"),
115 (ReqRedisHkeys, "REQ_REDIS_HKEYS"),
116 (ReqRedisHlen, "REQ_REDIS_HLEN"),
117 (ReqRedisHmget, "REQ_REDIS_HMGET"),
118 (ReqRedisHmset, "REQ_REDIS_HMSET"),
119 (ReqRedisHset, "REQ_REDIS_HSET"),
120 (ReqRedisHsetnx, "REQ_REDIS_HSETNX"),
121 (ReqRedisHscan, "REQ_REDIS_HSCAN"),
122 (ReqRedisHvals, "REQ_REDIS_HVALS"),
123 (ReqRedisHstrlen, "REQ_REDIS_HSTRLEN"),
124 (ReqRedisKeys, "REQ_REDIS_KEYS"),
125 (ReqRedisInfo, "REQ_REDIS_INFO"),
126 (ReqRedisLindex, "REQ_REDIS_LINDEX"),
127 (ReqRedisLinsert, "REQ_REDIS_LINSERT"),
128 (ReqRedisLlen, "REQ_REDIS_LLEN"),
129 (ReqRedisLpop, "REQ_REDIS_LPOP"),
130 (ReqRedisLpush, "REQ_REDIS_LPUSH"),
131 (ReqRedisLpushx, "REQ_REDIS_LPUSHX"),
132 (ReqRedisLrange, "REQ_REDIS_LRANGE"),
133 (ReqRedisLrem, "REQ_REDIS_LREM"),
134 (ReqRedisLset, "REQ_REDIS_LSET"),
135 (ReqRedisLtrim, "REQ_REDIS_LTRIM"),
136 (ReqRedisPing, "REQ_REDIS_PING"),
137 (ReqRedisQuit, "REQ_REDIS_QUIT"),
138 (ReqRedisRpop, "REQ_REDIS_RPOP"),
139 (ReqRedisRpoplpush, "REQ_REDIS_RPOPLPUSH"),
140 (ReqRedisRpush, "REQ_REDIS_RPUSH"),
141 (ReqRedisRpushx, "REQ_REDIS_RPUSHX"),
142 (ReqRedisSadd, "REQ_REDIS_SADD"),
143 (ReqRedisScard, "REQ_REDIS_SCARD"),
144 (ReqRedisSdiff, "REQ_REDIS_SDIFF"),
145 (ReqRedisSdiffstore, "REQ_REDIS_SDIFFSTORE"),
146 (ReqRedisSinter, "REQ_REDIS_SINTER"),
147 (ReqRedisSinterstore, "REQ_REDIS_SINTERSTORE"),
148 (ReqRedisSismember, "REQ_REDIS_SISMEMBER"),
149 (ReqRedisSlaveof, "REQ_REDIS_SLAVEOF"),
150 (ReqRedisSmembers, "REQ_REDIS_SMEMBERS"),
151 (ReqRedisSmove, "REQ_REDIS_SMOVE"),
152 (ReqRedisSpop, "REQ_REDIS_SPOP"),
153 (ReqRedisSrandmember, "REQ_REDIS_SRANDMEMBER"),
154 (ReqRedisSrem, "REQ_REDIS_SREM"),
155 (ReqRedisSunion, "REQ_REDIS_SUNION"),
156 (ReqRedisSunionstore, "REQ_REDIS_SUNIONSTORE"),
157 (ReqRedisSscan, "REQ_REDIS_SSCAN"),
158 (ReqRedisZadd, "REQ_REDIS_ZADD"),
159 (ReqRedisZcard, "REQ_REDIS_ZCARD"),
160 (ReqRedisZcount, "REQ_REDIS_ZCOUNT"),
161 (ReqRedisZincrby, "REQ_REDIS_ZINCRBY"),
162 (ReqRedisZinterstore, "REQ_REDIS_ZINTERSTORE"),
163 (ReqRedisZlexcount, "REQ_REDIS_ZLEXCOUNT"),
164 (ReqRedisZrange, "REQ_REDIS_ZRANGE"),
165 (ReqRedisZrangebylex, "REQ_REDIS_ZRANGEBYLEX"),
166 (ReqRedisZrangebyscore, "REQ_REDIS_ZRANGEBYSCORE"),
167 (ReqRedisZrank, "REQ_REDIS_ZRANK"),
168 (ReqRedisZrem, "REQ_REDIS_ZREM"),
169 (ReqRedisZremrangebyrank, "REQ_REDIS_ZREMRANGEBYRANK"),
170 (ReqRedisZremrangebylex, "REQ_REDIS_ZREMRANGEBYLEX"),
171 (ReqRedisZremrangebyscore, "REQ_REDIS_ZREMRANGEBYSCORE"),
172 (ReqRedisZrevrange, "REQ_REDIS_ZREVRANGE"),
173 (ReqRedisZrevrangebylex, "REQ_REDIS_ZREVRANGEBYLEX"),
174 (ReqRedisZrevrangebyscore, "REQ_REDIS_ZREVRANGEBYSCORE"),
175 (ReqRedisZrevrank, "REQ_REDIS_ZREVRANK"),
176 (ReqRedisZscore, "REQ_REDIS_ZSCORE"),
177 (ReqRedisZunionstore, "REQ_REDIS_ZUNIONSTORE"),
178 (ReqRedisZscan, "REQ_REDIS_ZSCAN"),
179 (ReqRedisEval, "REQ_REDIS_EVAL"),
180 (ReqRedisEvalsha, "REQ_REDIS_EVALSHA"),
181 (ReqRedisGeoadd, "REQ_REDIS_GEOADD"),
182 (ReqRedisGeoradius, "REQ_REDIS_GEORADIUS"),
183 (ReqRedisGeodist, "REQ_REDIS_GEODIST"),
184 (ReqRedisGeohash, "REQ_REDIS_GEOHASH"),
185 (ReqRedisGeopos, "REQ_REDIS_GEOPOS"),
186 (ReqRedisGeoradiusbymember, "REQ_REDIS_GEORADIUSBYMEMBER"),
187 (ReqRedisUnlink, "REQ_REDIS_UNLINK"),
188 (ReqRedisJsonset, "REQ_REDIS_JSONSET"),
189 (ReqRedisJsonget, "REQ_REDIS_JSONGET"),
190 (ReqRedisJsondel, "REQ_REDIS_JSONDEL"),
191 (ReqRedisJsontype, "REQ_REDIS_JSONTYPE"),
192 (ReqRedisJsonmget, "REQ_REDIS_JSONMGET"),
193 (ReqRedisJsonarrappend, "REQ_REDIS_JSONARRAPPEND"),
194 (ReqRedisJsonarrinsert, "REQ_REDIS_JSONARRINSERT"),
195 (ReqRedisJsonarrlen, "REQ_REDIS_JSONARRLEN"),
196 (ReqRedisJsonobjkeys, "REQ_REDIS_JSONOBJKEYS"),
197 (ReqRedisJsonobjlen, "REQ_REDIS_JSONOBJLEN"),
198 (ReqRedisPfadd, "REQ_REDIS_PFADD"),
199 (ReqRedisPfcount, "REQ_REDIS_PFCOUNT"),
200 (ReqRedisConfig, "REQ_REDIS_CONFIG"),
201 (ReqRedisScript, "REQ_REDIS_SCRIPT"),
202 (ReqRedisScriptLoad, "REQ_REDIS_SCRIPT_LOAD"),
203 (ReqRedisScriptExists, "REQ_REDIS_SCRIPT_EXISTS"),
204 (ReqRedisScriptFlush, "REQ_REDIS_SCRIPT_FLUSH"),
205 (ReqRedisScriptKill, "REQ_REDIS_SCRIPT_KILL"),
206 (RspRedisStatus, "RSP_REDIS_STATUS"),
207 (RspRedisInteger, "RSP_REDIS_INTEGER"),
208 (RspRedisBulk, "RSP_REDIS_BULK"),
209 (RspRedisMultibulk, "RSP_REDIS_MULTIBULK"),
210 (RspRedisError, "RSP_REDIS_ERROR"),
211 (RspRedisErrorErr, "RSP_REDIS_ERROR_ERR"),
212 (RspRedisErrorOom, "RSP_REDIS_ERROR_OOM"),
213 (RspRedisErrorBusy, "RSP_REDIS_ERROR_BUSY"),
214 (RspRedisErrorNoauth, "RSP_REDIS_ERROR_NOAUTH"),
215 (RspRedisErrorLoading, "RSP_REDIS_ERROR_LOADING"),
216 (RspRedisErrorBusykey, "RSP_REDIS_ERROR_BUSYKEY"),
217 (RspRedisErrorMisconf, "RSP_REDIS_ERROR_MISCONF"),
218 (RspRedisErrorNoscript, "RSP_REDIS_ERROR_NOSCRIPT"),
219 (RspRedisErrorReadonly, "RSP_REDIS_ERROR_READONLY"),
220 (RspRedisErrorWrongtype, "RSP_REDIS_ERROR_WRONGTYPE"),
221 (RspRedisErrorExecabort, "RSP_REDIS_ERROR_EXECABORT"),
222 (RspRedisErrorMasterdown, "RSP_REDIS_ERROR_MASTERDOWN"),
223 (RspRedisErrorNoreplicas, "RSP_REDIS_ERROR_NOREPLICAS"),
224 (HackSettingConnConsistency, "HACK_SETTING_CONN_CONSISTENCY"),
225 (Sentinel, "SENTINEL"),
226 (ReqRedisFtCreate, "REQ_REDIS_FT_CREATE"),
227 (ReqRedisFtSearch, "REQ_REDIS_FT_SEARCH"),
228 (ReqRedisFtInfo, "REQ_REDIS_FT_INFO"),
229 (ReqRedisFtList, "REQ_REDIS_FT_LIST"),
230 (ReqRedisFtDropindex, "REQ_REDIS_FT_DROPINDEX"),
231 (ReqRedisFtRegex, "REQ_REDIS_FT_REGEX"),
232 (ReqRedisFtSugadd, "REQ_REDIS_FT_SUGADD"),
233 (ReqRedisFtSugget, "REQ_REDIS_FT_SUGGET"),
234 (ReqRedisFtSugdel, "REQ_REDIS_FT_SUGDEL"),
235 (ReqRedisFtSuglen, "REQ_REDIS_FT_SUGLEN"),
236 (ReqRedisFtUnknown, "REQ_REDIS_FT_UNKNOWN"),
237 (EndIdx, "END_IDX"),
238];
239
240impl MsgType {
241 pub const COUNT: usize = Self::ALL.len();
251
252 #[must_use]
263 pub const fn as_index(self) -> u32 {
264 self as u32
265 }
266
267 #[must_use]
279 pub fn from_index(index: u32) -> Option<MsgType> {
280 Self::ALL.get(index as usize).copied()
281 }
282
283 #[must_use]
293 pub fn name(&self) -> &'static str {
294 Self::NAMES[self.as_index() as usize]
295 }
296
297 #[must_use]
309 pub fn is_request(&self) -> bool {
310 self.name().starts_with("REQ_")
311 }
312
313 #[must_use]
324 pub fn is_response(&self) -> bool {
325 self.name().starts_with("RSP_")
326 }
327}
328
329impl fmt::Display for MsgType {
330 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
331 f.write_str(self.name())
332 }
333}
334
335#[cfg(test)]
336mod tests {
337 use super::*;
338
339 #[test]
340 fn unknown_is_zero() {
341 assert_eq!(MsgType::Unknown.as_index(), 0);
342 assert_eq!(MsgType::Unknown.name(), "UNKNOWN");
343 }
344
345 #[test]
346 fn end_idx_is_last() {
347 assert_eq!(
348 MsgType::EndIdx.as_index() + 1,
349 u32::try_from(MsgType::COUNT).unwrap(),
350 );
351 }
352
353 #[test]
354 fn from_index_round_trip() {
355 let count_u32 = u32::try_from(MsgType::COUNT).unwrap();
356 for i in 0..count_u32 {
357 let ty = MsgType::from_index(i).unwrap();
358 assert_eq!(ty.as_index(), i);
359 }
360 assert!(MsgType::from_index(count_u32).is_none());
361 assert!(MsgType::from_index(u32::MAX).is_none());
362 }
363
364 #[test]
365 fn classification_partition() {
366 let count_u32 = u32::try_from(MsgType::COUNT).unwrap();
367 for i in 0..count_u32 {
368 let ty = MsgType::from_index(i).unwrap();
369 assert!(!(ty.is_request() && ty.is_response()));
371 }
372 assert!(MsgType::ReqMcSet.is_request());
373 assert!(MsgType::RspRedisStatus.is_response());
374 assert!(!MsgType::Sentinel.is_request());
375 assert!(!MsgType::Sentinel.is_response());
376 }
377
378 #[test]
379 fn names_are_unique_uppercase() {
380 let mut seen = std::collections::HashSet::new();
381 for &name in MsgType::NAMES {
382 assert!(name.chars().all(|c| c.is_ascii_uppercase() || c == '_'));
383 assert!(seen.insert(name), "duplicate name: {name}");
384 }
385 }
386}