rocketmq_security_api/
resource_pattern.rs1use serde::Deserialize;
16use serde::Deserializer;
17use serde::Serialize;
18use serde::Serializer;
19
20#[derive(Debug, Copy, Clone, Eq, PartialEq)]
21#[repr(u8)]
22pub enum ResourcePattern {
24 Any = 1,
26 Literal = 2,
28 Prefixed = 3,
30}
31
32impl ResourcePattern {
33 pub fn get_by_name(name: &str) -> Option<Self> {
35 if name.eq_ignore_ascii_case("ANY") {
36 Some(Self::Any)
37 } else if name.eq_ignore_ascii_case("LITERAL") {
38 Some(Self::Literal)
39 } else if name.eq_ignore_ascii_case("PREFIXED") {
40 Some(Self::Prefixed)
41 } else {
42 None
43 }
44 }
45
46 #[inline]
47 pub fn code(self) -> u8 {
49 self as u8
50 }
51
52 #[inline]
53 pub fn name(self) -> &'static str {
55 match self {
56 Self::Any => "ANY",
57 Self::Literal => "LITERAL",
58 Self::Prefixed => "PREFIXED",
59 }
60 }
61}
62
63impl Serialize for ResourcePattern {
64 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
65 where
66 S: Serializer,
67 {
68 serializer.serialize_u8(self.code())
69 }
70}
71
72impl<'de> Deserialize<'de> for ResourcePattern {
73 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
74 where
75 D: Deserializer<'de>,
76 {
77 let v = u8::deserialize(deserializer)?;
78 match v {
79 1 => Ok(ResourcePattern::Any),
80 2 => Ok(ResourcePattern::Literal),
81 3 => Ok(ResourcePattern::Prefixed),
82 _ => Err(serde::de::Error::custom("invalid ResourcePattern code")),
83 }
84 }
85}
86
87#[cfg(test)]
88mod tests {
89 use super::ResourcePattern;
90
91 #[test]
92 fn given_string_any_return_enum_value() {
93 let any = ResourcePattern::get_by_name("ANY");
94 assert_eq!(Some(ResourcePattern::Any), any);
95 }
96
97 #[test]
98 fn given_string_literal_return_enum_value() {
99 let literal = ResourcePattern::get_by_name("LITERAL");
100 assert_eq!(Some(ResourcePattern::Literal), literal);
101 }
102
103 #[test]
104 fn given_string_prefixed_return_enum_value() {
105 let prefixed = ResourcePattern::get_by_name("PREFIXED");
106 assert_eq!(Some(ResourcePattern::Prefixed), prefixed);
107 }
108
109 #[test]
110 fn get_by_name_is_case_insensitive() {
111 assert_eq!(Some(ResourcePattern::Any), ResourcePattern::get_by_name("aNy"));
112 assert_eq!(Some(ResourcePattern::Literal), ResourcePattern::get_by_name("LiTeRaL"));
113 assert_eq!(
114 Some(ResourcePattern::Prefixed),
115 ResourcePattern::get_by_name("pReFixed")
116 );
117 }
118
119 #[test]
120 fn invalid_name_returns_none() {
121 assert!(ResourcePattern::get_by_name("UNKNOWN").is_none());
122 assert!(ResourcePattern::get_by_name("123").is_none());
123 assert!(ResourcePattern::get_by_name("").is_none());
124 }
125
126 #[test]
127 fn name_and_code_methods_are_consistent() {
128 assert_eq!("ANY", ResourcePattern::Any.name());
129 assert_eq!(1, ResourcePattern::Any.code());
130 assert_eq!("LITERAL", ResourcePattern::Literal.name());
131 assert_eq!(2, ResourcePattern::Literal.code());
132 assert_eq!("PREFIXED", ResourcePattern::Prefixed.name());
133 assert_eq!(3, ResourcePattern::Prefixed.code());
134 }
135
136 #[test]
137 fn serde_json_serializes_to_number() {
138 assert_eq!(
139 "1",
140 serde_json::to_string(&ResourcePattern::Any).expect("ResourcePattern::Any must serialize")
141 );
142 assert_eq!(
143 "2",
144 serde_json::to_string(&ResourcePattern::Literal).expect("ResourcePattern::Literal must serialize")
145 );
146 assert_eq!(
147 "3",
148 serde_json::to_string(&ResourcePattern::Prefixed).expect("ResourcePattern::Prefixed must serialize")
149 );
150 }
151
152 #[test]
153 fn serde_json_deserializes_from_number() {
154 let any: ResourcePattern = serde_json::from_str("1").expect("Must deserialize 1");
155 assert_eq!(ResourcePattern::Any, any);
156
157 let literal: ResourcePattern = serde_json::from_str("2").expect("Must deserialize 2");
158 assert_eq!(ResourcePattern::Literal, literal);
159
160 let prefixed: ResourcePattern = serde_json::from_str("3").expect("Must deserialize 3");
161 assert_eq!(ResourcePattern::Prefixed, prefixed);
162 }
163
164 #[test]
165 fn serde_json_deserializes_invalid_fails() {
166 assert!(serde_json::from_str::<ResourcePattern>("0").is_err());
167 assert!(serde_json::from_str::<ResourcePattern>("999").is_err());
168 }
169
170 #[test]
171 fn serde_json_roundtrip_variants() {
172 for &variant in &[
173 ResourcePattern::Any,
174 ResourcePattern::Literal,
175 ResourcePattern::Prefixed,
176 ] {
177 let serialized = serde_json::to_string(&variant)
178 .unwrap_or_else(|e| panic!("Could not serialize ResourcePattern::{:?}: {}", variant.name(), e));
179 let parsed: ResourcePattern = serde_json::from_str(&serialized)
180 .unwrap_or_else(|e| panic!("Could not parse {:?} as ResourcePattern: {}", serialized, e));
181 assert_eq!(variant, parsed);
182 }
183 }
184}