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 (ReqRedisFtSugadd, "REQ_REDIS_FT_SUGADD"),
235 (ReqRedisFtSugget, "REQ_REDIS_FT_SUGGET"),
236 (ReqRedisFtSugdel, "REQ_REDIS_FT_SUGDEL"),
237 (ReqRedisFtSuglen, "REQ_REDIS_FT_SUGLEN"),
238 (ReqRedisFtUnknown, "REQ_REDIS_FT_UNKNOWN"),
239 (EndIdx, "END_IDX"),
240];
241
242impl MsgType {
243 pub const COUNT: usize = Self::ALL.len();
253
254 #[must_use]
266 pub const fn as_index(self) -> u32 {
267 self as u32
268 }
269
270 #[must_use]
282 pub fn from_index(index: u32) -> Option<MsgType> {
283 Self::ALL.get(index as usize).copied()
284 }
285
286 #[must_use]
296 pub fn name(&self) -> &'static str {
297 Self::NAMES[self.as_index() as usize]
298 }
299
300 #[must_use]
312 pub fn is_request(&self) -> bool {
313 self.name().starts_with("REQ_")
314 }
315
316 #[must_use]
327 pub fn is_response(&self) -> bool {
328 self.name().starts_with("RSP_")
329 }
330}
331
332impl fmt::Display for MsgType {
333 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
334 f.write_str(self.name())
335 }
336}
337
338#[cfg(test)]
339mod tests {
340 use super::*;
341
342 #[test]
343 fn unknown_is_zero() {
344 assert_eq!(MsgType::Unknown.as_index(), 0);
345 assert_eq!(MsgType::Unknown.name(), "UNKNOWN");
346 }
347
348 #[test]
349 fn end_idx_is_last() {
350 assert_eq!(
351 MsgType::EndIdx.as_index() + 1,
352 u32::try_from(MsgType::COUNT).unwrap(),
353 );
354 }
355
356 #[test]
357 fn from_index_round_trip() {
358 let count_u32 = u32::try_from(MsgType::COUNT).unwrap();
359 for i in 0..count_u32 {
360 let ty = MsgType::from_index(i).unwrap();
361 assert_eq!(ty.as_index(), i);
362 }
363 assert!(MsgType::from_index(count_u32).is_none());
364 assert!(MsgType::from_index(u32::MAX).is_none());
365 }
366
367 #[test]
368 fn classification_partition() {
369 let count_u32 = u32::try_from(MsgType::COUNT).unwrap();
370 for i in 0..count_u32 {
371 let ty = MsgType::from_index(i).unwrap();
372 assert!(!(ty.is_request() && ty.is_response()));
374 }
375 assert!(MsgType::ReqMcSet.is_request());
376 assert!(MsgType::RspRedisStatus.is_response());
377 assert!(!MsgType::Sentinel.is_request());
378 assert!(!MsgType::Sentinel.is_response());
379 }
380
381 #[test]
382 fn names_are_unique_uppercase() {
383 let mut seen = std::collections::HashSet::new();
384 for &name in MsgType::NAMES {
385 assert!(name.chars().all(|c| c.is_ascii_uppercase() || c == '_'));
386 assert!(seen.insert(name), "duplicate name: {name}");
387 }
388 }
389}