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