iam_rs/core/
operator.rs

1use serde::{Deserialize, Serialize};
2
3/// Represents the different types of condition operators available in IAM policies
4#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Hash)]
5#[serde(rename_all = "PascalCase")]
6pub enum Operator {
7    // String condition operators
8    #[serde(rename = "StringEquals")]
9    StringEquals,
10    #[serde(rename = "StringNotEquals")]
11    StringNotEquals,
12    #[serde(rename = "StringEqualsIgnoreCase")]
13    StringEqualsIgnoreCase,
14    #[serde(rename = "StringNotEqualsIgnoreCase")]
15    StringNotEqualsIgnoreCase,
16    #[serde(rename = "StringLike")]
17    StringLike,
18    #[serde(rename = "StringNotLike")]
19    StringNotLike,
20
21    // Multivalued string condition operators
22    #[serde(rename = "ForAllValues:StringEquals")]
23    ForAllValuesStringEquals,
24    #[serde(rename = "ForAllValues:StringEqualsIgnoreCase")]
25    ForAllValuesStringEqualsIgnoreCase,
26    #[serde(rename = "ForAnyValue:StringEquals")]
27    ForAnyValueStringEquals,
28    #[serde(rename = "ForAnyValue:StringEqualsIgnoreCase")]
29    ForAnyValueStringEqualsIgnoreCase,
30    #[serde(rename = "ForAllValues:StringNotEquals")]
31    ForAllValuesStringNotEquals,
32    #[serde(rename = "ForAllValues:StringNotEqualsIgnoreCase")]
33    ForAllValuesStringNotEqualsIgnoreCase,
34    #[serde(rename = "ForAnyValue:StringNotEquals")]
35    ForAnyValueStringNotEquals,
36    #[serde(rename = "ForAnyValue:StringNotEqualsIgnoreCase")]
37    ForAnyValueStringNotEqualsIgnoreCase,
38    #[serde(rename = "ForAllValues:StringLike")]
39    ForAllValuesStringLike,
40    #[serde(rename = "ForAnyValue:StringLike")]
41    ForAnyValueStringLike,
42    #[serde(rename = "ForAllValues:StringNotLike")]
43    ForAllValuesStringNotLike,
44    #[serde(rename = "ForAnyValue:StringNotLike")]
45    ForAnyValueStringNotLike,
46
47    // Numeric condition operators
48    #[serde(rename = "NumericEquals")]
49    NumericEquals,
50    #[serde(rename = "NumericNotEquals")]
51    NumericNotEquals,
52    #[serde(rename = "NumericLessThan")]
53    NumericLessThan,
54    #[serde(rename = "NumericLessThanEquals")]
55    NumericLessThanEquals,
56    #[serde(rename = "NumericGreaterThan")]
57    NumericGreaterThan,
58    #[serde(rename = "NumericGreaterThanEquals")]
59    NumericGreaterThanEquals,
60
61    // Date condition operators
62    #[serde(rename = "DateEquals")]
63    DateEquals,
64    #[serde(rename = "DateNotEquals")]
65    DateNotEquals,
66    #[serde(rename = "DateLessThan")]
67    DateLessThan,
68    #[serde(rename = "DateLessThanEquals")]
69    DateLessThanEquals,
70    #[serde(rename = "DateGreaterThan")]
71    DateGreaterThan,
72    #[serde(rename = "DateGreaterThanEquals")]
73    DateGreaterThanEquals,
74
75    // Boolean condition operators
76    #[serde(rename = "Bool")]
77    Bool,
78    #[serde(rename = "ForAllValues:Bool")]
79    ForAllValuesBool,
80    #[serde(rename = "ForAnyValue:Bool")]
81    ForAnyValueBool,
82
83    // Binary condition operators
84    #[serde(rename = "BinaryEquals")]
85    BinaryEquals,
86
87    // IP address condition operators
88    #[serde(rename = "IpAddress")]
89    IpAddress,
90    #[serde(rename = "NotIpAddress")]
91    NotIpAddress,
92
93    // ARN condition operators
94    #[serde(rename = "ArnEquals")]
95    ArnEquals,
96    #[serde(rename = "ArnLike")]
97    ArnLike,
98    #[serde(rename = "ArnNotEquals")]
99    ArnNotEquals,
100    #[serde(rename = "ArnNotLike")]
101    ArnNotLike,
102
103    // Multivalued ARN condition operators
104    #[serde(rename = "ForAllValues:ArnEquals")]
105    ForAllValuesArnEquals,
106    #[serde(rename = "ForAllValues:ArnLike")]
107    ForAllValuesArnLike,
108    #[serde(rename = "ForAnyValue:ArnEquals")]
109    ForAnyValueArnEquals,
110    #[serde(rename = "ForAnyValue:ArnLike")]
111    ForAnyValueArnLike,
112    #[serde(rename = "ForAllValues:ArnNotEquals")]
113    ForAllValuesArnNotEquals,
114    #[serde(rename = "ForAllValues:ArnNotLike")]
115    ForAllValuesArnNotLike,
116    #[serde(rename = "ForAnyValue:ArnNotEquals")]
117    ForAnyValueArnNotEquals,
118    #[serde(rename = "ForAnyValue:ArnNotLike")]
119    ForAnyValueArnNotLike,
120
121    // Null condition operator
122    #[serde(rename = "Null")]
123    Null,
124
125    // IfExists variants (can be applied to most operators)
126    #[serde(rename = "StringEqualsIfExists")]
127    StringEqualsIfExists,
128    #[serde(rename = "StringNotEqualsIfExists")]
129    StringNotEqualsIfExists,
130    #[serde(rename = "StringEqualsIgnoreCaseIfExists")]
131    StringEqualsIgnoreCaseIfExists,
132    #[serde(rename = "StringNotEqualsIgnoreCaseIfExists")]
133    StringNotEqualsIgnoreCaseIfExists,
134    #[serde(rename = "StringLikeIfExists")]
135    StringLikeIfExists,
136    #[serde(rename = "StringNotLikeIfExists")]
137    StringNotLikeIfExists,
138    #[serde(rename = "NumericEqualsIfExists")]
139    NumericEqualsIfExists,
140    #[serde(rename = "NumericNotEqualsIfExists")]
141    NumericNotEqualsIfExists,
142    #[serde(rename = "NumericLessThanIfExists")]
143    NumericLessThanIfExists,
144    #[serde(rename = "NumericLessThanEqualsIfExists")]
145    NumericLessThanEqualsIfExists,
146    #[serde(rename = "NumericGreaterThanIfExists")]
147    NumericGreaterThanIfExists,
148    #[serde(rename = "NumericGreaterThanEqualsIfExists")]
149    NumericGreaterThanEqualsIfExists,
150    #[serde(rename = "DateEqualsIfExists")]
151    DateEqualsIfExists,
152    #[serde(rename = "DateNotEqualsIfExists")]
153    DateNotEqualsIfExists,
154    #[serde(rename = "DateLessThanIfExists")]
155    DateLessThanIfExists,
156    #[serde(rename = "DateLessThanEqualsIfExists")]
157    DateLessThanEqualsIfExists,
158    #[serde(rename = "DateGreaterThanIfExists")]
159    DateGreaterThanIfExists,
160    #[serde(rename = "DateGreaterThanEqualsIfExists")]
161    DateGreaterThanEqualsIfExists,
162    #[serde(rename = "BoolIfExists")]
163    BoolIfExists,
164    #[serde(rename = "BinaryEqualsIfExists")]
165    BinaryEqualsIfExists,
166    #[serde(rename = "IpAddressIfExists")]
167    IpAddressIfExists,
168    #[serde(rename = "NotIpAddressIfExists")]
169    NotIpAddressIfExists,
170    #[serde(rename = "ArnEqualsIfExists")]
171    ArnEqualsIfExists,
172    #[serde(rename = "ArnLikeIfExists")]
173    ArnLikeIfExists,
174    #[serde(rename = "ArnNotEqualsIfExists")]
175    ArnNotEqualsIfExists,
176    #[serde(rename = "ArnNotLikeIfExists")]
177    ArnNotLikeIfExists,
178}
179
180impl Operator {
181    /// Returns true if this operator is a string-based operator
182    pub fn is_string_operator(&self) -> bool {
183        matches!(
184            self,
185            Operator::StringEquals
186                | Operator::StringNotEquals
187                | Operator::StringEqualsIgnoreCase
188                | Operator::StringNotEqualsIgnoreCase
189                | Operator::StringLike
190                | Operator::StringNotLike
191                | Operator::ForAllValuesStringEquals
192                | Operator::ForAllValuesStringEqualsIgnoreCase
193                | Operator::ForAnyValueStringEquals
194                | Operator::ForAnyValueStringEqualsIgnoreCase
195                | Operator::ForAllValuesStringNotEquals
196                | Operator::ForAllValuesStringNotEqualsIgnoreCase
197                | Operator::ForAnyValueStringNotEquals
198                | Operator::ForAnyValueStringNotEqualsIgnoreCase
199                | Operator::ForAllValuesStringLike
200                | Operator::ForAnyValueStringLike
201                | Operator::ForAllValuesStringNotLike
202                | Operator::ForAnyValueStringNotLike
203                | Operator::StringEqualsIfExists
204                | Operator::StringNotEqualsIfExists
205                | Operator::StringEqualsIgnoreCaseIfExists
206                | Operator::StringNotEqualsIgnoreCaseIfExists
207                | Operator::StringLikeIfExists
208                | Operator::StringNotLikeIfExists
209        )
210    }
211
212    /// Returns true if this operator is a numeric-based operator
213    pub fn is_numeric_operator(&self) -> bool {
214        matches!(
215            self,
216            Operator::NumericEquals
217                | Operator::NumericNotEquals
218                | Operator::NumericLessThan
219                | Operator::NumericLessThanEquals
220                | Operator::NumericGreaterThan
221                | Operator::NumericGreaterThanEquals
222                | Operator::NumericEqualsIfExists
223                | Operator::NumericNotEqualsIfExists
224                | Operator::NumericLessThanIfExists
225                | Operator::NumericLessThanEqualsIfExists
226                | Operator::NumericGreaterThanIfExists
227                | Operator::NumericGreaterThanEqualsIfExists
228        )
229    }
230
231    /// Returns true if this operator is a date-based operator
232    pub fn is_date_operator(&self) -> bool {
233        matches!(
234            self,
235            Operator::DateEquals
236                | Operator::DateNotEquals
237                | Operator::DateLessThan
238                | Operator::DateLessThanEquals
239                | Operator::DateGreaterThan
240                | Operator::DateGreaterThanEquals
241                | Operator::DateEqualsIfExists
242                | Operator::DateNotEqualsIfExists
243                | Operator::DateLessThanIfExists
244                | Operator::DateLessThanEqualsIfExists
245                | Operator::DateGreaterThanIfExists
246                | Operator::DateGreaterThanEqualsIfExists
247        )
248    }
249
250    /// Returns true if this operator is a boolean-based operator
251    pub fn is_boolean_operator(&self) -> bool {
252        matches!(
253            self,
254            Operator::Bool
255                | Operator::ForAllValuesBool
256                | Operator::ForAnyValueBool
257                | Operator::BoolIfExists
258        )
259    }
260
261    /// Returns true if this operator is an ARN-based operator
262    pub fn is_arn_operator(&self) -> bool {
263        matches!(
264            self,
265            Operator::ArnEquals
266                | Operator::ArnLike
267                | Operator::ArnNotEquals
268                | Operator::ArnNotLike
269                | Operator::ForAllValuesArnEquals
270                | Operator::ForAllValuesArnLike
271                | Operator::ForAnyValueArnEquals
272                | Operator::ForAnyValueArnLike
273                | Operator::ForAllValuesArnNotEquals
274                | Operator::ForAllValuesArnNotLike
275                | Operator::ForAnyValueArnNotEquals
276                | Operator::ForAnyValueArnNotLike
277                | Operator::ArnEqualsIfExists
278                | Operator::ArnLikeIfExists
279                | Operator::ArnNotEqualsIfExists
280                | Operator::ArnNotLikeIfExists
281        )
282    }
283
284    /// Returns true if this operator is an IP address-based operator
285    pub fn is_ip_operator(&self) -> bool {
286        matches!(
287            self,
288            Operator::IpAddress
289                | Operator::NotIpAddress
290                | Operator::IpAddressIfExists
291                | Operator::NotIpAddressIfExists
292        )
293    }
294
295    /// Returns true if this operator is a binary-based operator
296    pub fn is_binary_operator(&self) -> bool {
297        matches!(
298            self,
299            Operator::BinaryEquals | Operator::BinaryEqualsIfExists
300        )
301    }
302
303    /// Returns true if this operator supports wildcards
304    pub fn supports_wildcards(&self) -> bool {
305        matches!(
306            self,
307            Operator::StringLike
308                | Operator::StringNotLike
309                | Operator::ForAllValuesStringLike
310                | Operator::ForAnyValueStringLike
311                | Operator::ForAllValuesStringNotLike
312                | Operator::ForAnyValueStringNotLike
313                | Operator::StringLikeIfExists
314                | Operator::StringNotLikeIfExists
315                | Operator::ArnEquals
316                | Operator::ArnLike
317                | Operator::ArnNotEquals
318                | Operator::ArnNotLike
319                | Operator::ForAllValuesArnEquals
320                | Operator::ForAllValuesArnLike
321                | Operator::ForAnyValueArnEquals
322                | Operator::ForAnyValueArnLike
323                | Operator::ForAllValuesArnNotEquals
324                | Operator::ForAllValuesArnNotLike
325                | Operator::ForAnyValueArnNotEquals
326                | Operator::ForAnyValueArnNotLike
327                | Operator::ArnEqualsIfExists
328                | Operator::ArnLikeIfExists
329                | Operator::ArnNotEqualsIfExists
330                | Operator::ArnNotLikeIfExists
331        )
332    }
333
334    /// Returns true if this operator supports policy variables
335    pub fn supports_policy_variables(&self) -> bool {
336        !self.is_numeric_operator()
337            && !self.is_date_operator()
338            && !self.is_binary_operator()
339            && !self.is_ip_operator()
340    }
341
342    /// Returns true if this operator is a multivalued operator (ForAllValues/ForAnyValue)
343    pub fn is_multivalued_operator(&self) -> bool {
344        matches!(
345            self,
346            Operator::ForAllValuesStringEquals
347                | Operator::ForAllValuesStringEqualsIgnoreCase
348                | Operator::ForAnyValueStringEquals
349                | Operator::ForAnyValueStringEqualsIgnoreCase
350                | Operator::ForAllValuesStringNotEquals
351                | Operator::ForAllValuesStringNotEqualsIgnoreCase
352                | Operator::ForAnyValueStringNotEquals
353                | Operator::ForAnyValueStringNotEqualsIgnoreCase
354                | Operator::ForAllValuesStringLike
355                | Operator::ForAnyValueStringLike
356                | Operator::ForAllValuesStringNotLike
357                | Operator::ForAnyValueStringNotLike
358                | Operator::ForAllValuesBool
359                | Operator::ForAnyValueBool
360                | Operator::ForAllValuesArnEquals
361                | Operator::ForAllValuesArnLike
362                | Operator::ForAnyValueArnEquals
363                | Operator::ForAnyValueArnLike
364                | Operator::ForAllValuesArnNotEquals
365                | Operator::ForAllValuesArnNotLike
366                | Operator::ForAnyValueArnNotEquals
367                | Operator::ForAnyValueArnNotLike
368        )
369    }
370
371    /// Returns true if this operator is an "IfExists" variant
372    pub fn is_if_exists_operator(&self) -> bool {
373        matches!(
374            self,
375            Operator::StringEqualsIfExists
376                | Operator::StringNotEqualsIfExists
377                | Operator::StringEqualsIgnoreCaseIfExists
378                | Operator::StringNotEqualsIgnoreCaseIfExists
379                | Operator::StringLikeIfExists
380                | Operator::StringNotLikeIfExists
381                | Operator::NumericEqualsIfExists
382                | Operator::NumericNotEqualsIfExists
383                | Operator::NumericLessThanIfExists
384                | Operator::NumericLessThanEqualsIfExists
385                | Operator::NumericGreaterThanIfExists
386                | Operator::NumericGreaterThanEqualsIfExists
387                | Operator::DateEqualsIfExists
388                | Operator::DateNotEqualsIfExists
389                | Operator::DateLessThanIfExists
390                | Operator::DateLessThanEqualsIfExists
391                | Operator::DateGreaterThanIfExists
392                | Operator::DateGreaterThanEqualsIfExists
393                | Operator::BoolIfExists
394                | Operator::BinaryEqualsIfExists
395                | Operator::IpAddressIfExists
396                | Operator::NotIpAddressIfExists
397                | Operator::ArnEqualsIfExists
398                | Operator::ArnLikeIfExists
399                | Operator::ArnNotEqualsIfExists
400                | Operator::ArnNotLikeIfExists
401        )
402    }
403
404    /// Returns true if this operator is a negated operator (Not*)
405    pub fn is_negated_operator(&self) -> bool {
406        matches!(
407            self,
408            Operator::StringNotEquals
409                | Operator::StringNotEqualsIgnoreCase
410                | Operator::StringNotLike
411                | Operator::ForAllValuesStringNotEquals
412                | Operator::ForAllValuesStringNotEqualsIgnoreCase
413                | Operator::ForAnyValueStringNotEquals
414                | Operator::ForAnyValueStringNotEqualsIgnoreCase
415                | Operator::ForAllValuesStringNotLike
416                | Operator::ForAnyValueStringNotLike
417                | Operator::NumericNotEquals
418                | Operator::DateNotEquals
419                | Operator::NotIpAddress
420                | Operator::ArnNotEquals
421                | Operator::ArnNotLike
422                | Operator::ForAllValuesArnNotEquals
423                | Operator::ForAllValuesArnNotLike
424                | Operator::ForAnyValueArnNotEquals
425                | Operator::ForAnyValueArnNotLike
426                | Operator::StringNotEqualsIfExists
427                | Operator::StringNotEqualsIgnoreCaseIfExists
428                | Operator::StringNotLikeIfExists
429                | Operator::NumericNotEqualsIfExists
430                | Operator::DateNotEqualsIfExists
431                | Operator::NotIpAddressIfExists
432                | Operator::ArnNotEqualsIfExists
433                | Operator::ArnNotLikeIfExists
434        )
435    }
436
437    /// Returns true if this operator supports multiple values (arrays)
438    /// Most operators in AWS IAM can accept arrays, not just ForAllValues/ForAnyValue
439    pub fn supports_multiple_values(&self) -> bool {
440        // Most operators support multiple values except for these specific ones
441        !matches!(
442            self,
443            Operator::Null | Operator::Bool | Operator::BoolIfExists
444        )
445    }
446
447    /// Returns the operator category as a string
448    pub fn category(&self) -> &'static str {
449        if self.is_string_operator() {
450            "String"
451        } else if self.is_numeric_operator() {
452            "Numeric"
453        } else if self.is_date_operator() {
454            "Date"
455        } else if self.is_boolean_operator() {
456            "Boolean"
457        } else if self.is_binary_operator() {
458            "Binary"
459        } else if self.is_ip_operator() {
460            "IP Address"
461        } else if self.is_arn_operator() {
462            "ARN"
463        } else if matches!(self, Operator::Null) {
464            "Null Check"
465        } else {
466            "Unknown"
467        }
468    }
469
470    /// Returns the string representation of the operator for use in JSON
471    pub fn as_str(&self) -> &'static str {
472        match self {
473            Operator::StringEquals => "StringEquals",
474            Operator::StringNotEquals => "StringNotEquals",
475            Operator::StringEqualsIgnoreCase => "StringEqualsIgnoreCase",
476            Operator::StringNotEqualsIgnoreCase => "StringNotEqualsIgnoreCase",
477            Operator::StringLike => "StringLike",
478            Operator::StringNotLike => "StringNotLike",
479            Operator::ForAllValuesStringEquals => "ForAllValues:StringEquals",
480            Operator::ForAllValuesStringEqualsIgnoreCase => "ForAllValues:StringEqualsIgnoreCase",
481            Operator::ForAnyValueStringEquals => "ForAnyValue:StringEquals",
482            Operator::ForAnyValueStringEqualsIgnoreCase => "ForAnyValue:StringEqualsIgnoreCase",
483            Operator::ForAllValuesStringNotEquals => "ForAllValues:StringNotEquals",
484            Operator::ForAllValuesStringNotEqualsIgnoreCase => {
485                "ForAllValues:StringNotEqualsIgnoreCase"
486            }
487            Operator::ForAnyValueStringNotEquals => "ForAnyValue:StringNotEquals",
488            Operator::ForAnyValueStringNotEqualsIgnoreCase => {
489                "ForAnyValue:StringNotEqualsIgnoreCase"
490            }
491            Operator::ForAllValuesStringLike => "ForAllValues:StringLike",
492            Operator::ForAnyValueStringLike => "ForAnyValue:StringLike",
493            Operator::ForAllValuesStringNotLike => "ForAllValues:StringNotLike",
494            Operator::ForAnyValueStringNotLike => "ForAnyValue:StringNotLike",
495            Operator::NumericEquals => "NumericEquals",
496            Operator::NumericNotEquals => "NumericNotEquals",
497            Operator::NumericLessThan => "NumericLessThan",
498            Operator::NumericLessThanEquals => "NumericLessThanEquals",
499            Operator::NumericGreaterThan => "NumericGreaterThan",
500            Operator::NumericGreaterThanEquals => "NumericGreaterThanEquals",
501            Operator::DateEquals => "DateEquals",
502            Operator::DateNotEquals => "DateNotEquals",
503            Operator::DateLessThan => "DateLessThan",
504            Operator::DateLessThanEquals => "DateLessThanEquals",
505            Operator::DateGreaterThan => "DateGreaterThan",
506            Operator::DateGreaterThanEquals => "DateGreaterThanEquals",
507            Operator::Bool => "Bool",
508            Operator::ForAllValuesBool => "ForAllValues:Bool",
509            Operator::ForAnyValueBool => "ForAnyValue:Bool",
510            Operator::BinaryEquals => "BinaryEquals",
511            Operator::IpAddress => "IpAddress",
512            Operator::NotIpAddress => "NotIpAddress",
513            Operator::ArnEquals => "ArnEquals",
514            Operator::ArnLike => "ArnLike",
515            Operator::ArnNotEquals => "ArnNotEquals",
516            Operator::ArnNotLike => "ArnNotLike",
517            Operator::ForAllValuesArnEquals => "ForAllValues:ArnEquals",
518            Operator::ForAllValuesArnLike => "ForAllValues:ArnLike",
519            Operator::ForAnyValueArnEquals => "ForAnyValue:ArnEquals",
520            Operator::ForAnyValueArnLike => "ForAnyValue:ArnLike",
521            Operator::ForAllValuesArnNotEquals => "ForAllValues:ArnNotEquals",
522            Operator::ForAllValuesArnNotLike => "ForAllValues:ArnNotLike",
523            Operator::ForAnyValueArnNotEquals => "ForAnyValue:ArnNotEquals",
524            Operator::ForAnyValueArnNotLike => "ForAnyValue:ArnNotLike",
525            Operator::Null => "Null",
526            Operator::StringEqualsIfExists => "StringEqualsIfExists",
527            Operator::StringNotEqualsIfExists => "StringNotEqualsIfExists",
528            Operator::StringEqualsIgnoreCaseIfExists => "StringEqualsIgnoreCaseIfExists",
529            Operator::StringNotEqualsIgnoreCaseIfExists => "StringNotEqualsIgnoreCaseIfExists",
530            Operator::StringLikeIfExists => "StringLikeIfExists",
531            Operator::StringNotLikeIfExists => "StringNotLikeIfExists",
532            Operator::NumericEqualsIfExists => "NumericEqualsIfExists",
533            Operator::NumericNotEqualsIfExists => "NumericNotEqualsIfExists",
534            Operator::NumericLessThanIfExists => "NumericLessThanIfExists",
535            Operator::NumericLessThanEqualsIfExists => "NumericLessThanEqualsIfExists",
536            Operator::NumericGreaterThanIfExists => "NumericGreaterThanIfExists",
537            Operator::NumericGreaterThanEqualsIfExists => "NumericGreaterThanEqualsIfExists",
538            Operator::DateEqualsIfExists => "DateEqualsIfExists",
539            Operator::DateNotEqualsIfExists => "DateNotEqualsIfExists",
540            Operator::DateLessThanIfExists => "DateLessThanIfExists",
541            Operator::DateLessThanEqualsIfExists => "DateLessThanEqualsIfExists",
542            Operator::DateGreaterThanIfExists => "DateGreaterThanIfExists",
543            Operator::DateGreaterThanEqualsIfExists => "DateGreaterThanEqualsIfExists",
544            Operator::BoolIfExists => "BoolIfExists",
545            Operator::BinaryEqualsIfExists => "BinaryEqualsIfExists",
546            Operator::IpAddressIfExists => "IpAddressIfExists",
547            Operator::NotIpAddressIfExists => "NotIpAddressIfExists",
548            Operator::ArnEqualsIfExists => "ArnEqualsIfExists",
549            Operator::ArnLikeIfExists => "ArnLikeIfExists",
550            Operator::ArnNotEqualsIfExists => "ArnNotEqualsIfExists",
551            Operator::ArnNotLikeIfExists => "ArnNotLikeIfExists",
552        }
553    }
554}
555
556impl std::fmt::Display for Operator {
557    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
558        write!(f, "{}", self.as_str())
559    }
560}
561
562impl std::str::FromStr for Operator {
563    type Err = String;
564
565    fn from_str(s: &str) -> Result<Self, Self::Err> {
566        match s {
567            "StringEquals" => Ok(Operator::StringEquals),
568            "StringNotEquals" => Ok(Operator::StringNotEquals),
569            "StringEqualsIgnoreCase" => Ok(Operator::StringEqualsIgnoreCase),
570            "StringNotEqualsIgnoreCase" => Ok(Operator::StringNotEqualsIgnoreCase),
571            "StringLike" => Ok(Operator::StringLike),
572            "StringNotLike" => Ok(Operator::StringNotLike),
573            "ForAllValues:StringEquals" => Ok(Operator::ForAllValuesStringEquals),
574            "ForAllValues:StringEqualsIgnoreCase" => {
575                Ok(Operator::ForAllValuesStringEqualsIgnoreCase)
576            }
577            "ForAnyValue:StringEquals" => Ok(Operator::ForAnyValueStringEquals),
578            "ForAnyValue:StringEqualsIgnoreCase" => Ok(Operator::ForAnyValueStringEqualsIgnoreCase),
579            "ForAllValues:StringNotEquals" => Ok(Operator::ForAllValuesStringNotEquals),
580            "ForAllValues:StringNotEqualsIgnoreCase" => {
581                Ok(Operator::ForAllValuesStringNotEqualsIgnoreCase)
582            }
583            "ForAnyValue:StringNotEquals" => Ok(Operator::ForAnyValueStringNotEquals),
584            "ForAnyValue:StringNotEqualsIgnoreCase" => {
585                Ok(Operator::ForAnyValueStringNotEqualsIgnoreCase)
586            }
587            "ForAllValues:StringLike" => Ok(Operator::ForAllValuesStringLike),
588            "ForAnyValue:StringLike" => Ok(Operator::ForAnyValueStringLike),
589            "ForAllValues:StringNotLike" => Ok(Operator::ForAllValuesStringNotLike),
590            "ForAnyValue:StringNotLike" => Ok(Operator::ForAnyValueStringNotLike),
591            "NumericEquals" => Ok(Operator::NumericEquals),
592            "NumericNotEquals" => Ok(Operator::NumericNotEquals),
593            "NumericLessThan" => Ok(Operator::NumericLessThan),
594            "NumericLessThanEquals" => Ok(Operator::NumericLessThanEquals),
595            "NumericGreaterThan" => Ok(Operator::NumericGreaterThan),
596            "NumericGreaterThanEquals" => Ok(Operator::NumericGreaterThanEquals),
597            "DateEquals" => Ok(Operator::DateEquals),
598            "DateNotEquals" => Ok(Operator::DateNotEquals),
599            "DateLessThan" => Ok(Operator::DateLessThan),
600            "DateLessThanEquals" => Ok(Operator::DateLessThanEquals),
601            "DateGreaterThan" => Ok(Operator::DateGreaterThan),
602            "DateGreaterThanEquals" => Ok(Operator::DateGreaterThanEquals),
603            "Bool" => Ok(Operator::Bool),
604            "ForAllValues:Bool" => Ok(Operator::ForAllValuesBool),
605            "ForAnyValue:Bool" => Ok(Operator::ForAnyValueBool),
606            "BinaryEquals" => Ok(Operator::BinaryEquals),
607            "IpAddress" => Ok(Operator::IpAddress),
608            "NotIpAddress" => Ok(Operator::NotIpAddress),
609            "ArnEquals" => Ok(Operator::ArnEquals),
610            "ArnLike" => Ok(Operator::ArnLike),
611            "ArnNotEquals" => Ok(Operator::ArnNotEquals),
612            "ArnNotLike" => Ok(Operator::ArnNotLike),
613            "ForAllValues:ArnEquals" => Ok(Operator::ForAllValuesArnEquals),
614            "ForAllValues:ArnLike" => Ok(Operator::ForAllValuesArnLike),
615            "ForAnyValue:ArnEquals" => Ok(Operator::ForAnyValueArnEquals),
616            "ForAnyValue:ArnLike" => Ok(Operator::ForAnyValueArnLike),
617            "ForAllValues:ArnNotEquals" => Ok(Operator::ForAllValuesArnNotEquals),
618            "ForAllValues:ArnNotLike" => Ok(Operator::ForAllValuesArnNotLike),
619            "ForAnyValue:ArnNotEquals" => Ok(Operator::ForAnyValueArnNotEquals),
620            "ForAnyValue:ArnNotLike" => Ok(Operator::ForAnyValueArnNotLike),
621            "Null" => Ok(Operator::Null),
622            "StringEqualsIfExists" => Ok(Operator::StringEqualsIfExists),
623            "StringNotEqualsIfExists" => Ok(Operator::StringNotEqualsIfExists),
624            "StringEqualsIgnoreCaseIfExists" => Ok(Operator::StringEqualsIgnoreCaseIfExists),
625            "StringNotEqualsIgnoreCaseIfExists" => Ok(Operator::StringNotEqualsIgnoreCaseIfExists),
626            "StringLikeIfExists" => Ok(Operator::StringLikeIfExists),
627            "StringNotLikeIfExists" => Ok(Operator::StringNotLikeIfExists),
628            "NumericEqualsIfExists" => Ok(Operator::NumericEqualsIfExists),
629            "NumericNotEqualsIfExists" => Ok(Operator::NumericNotEqualsIfExists),
630            "NumericLessThanIfExists" => Ok(Operator::NumericLessThanIfExists),
631            "NumericLessThanEqualsIfExists" => Ok(Operator::NumericLessThanEqualsIfExists),
632            "NumericGreaterThanIfExists" => Ok(Operator::NumericGreaterThanIfExists),
633            "NumericGreaterThanEqualsIfExists" => Ok(Operator::NumericGreaterThanEqualsIfExists),
634            "DateEqualsIfExists" => Ok(Operator::DateEqualsIfExists),
635            "DateNotEqualsIfExists" => Ok(Operator::DateNotEqualsIfExists),
636            "DateLessThanIfExists" => Ok(Operator::DateLessThanIfExists),
637            "DateLessThanEqualsIfExists" => Ok(Operator::DateLessThanEqualsIfExists),
638            "DateGreaterThanIfExists" => Ok(Operator::DateGreaterThanIfExists),
639            "DateGreaterThanEqualsIfExists" => Ok(Operator::DateGreaterThanEqualsIfExists),
640            "BoolIfExists" => Ok(Operator::BoolIfExists),
641            "BinaryEqualsIfExists" => Ok(Operator::BinaryEqualsIfExists),
642            "IpAddressIfExists" => Ok(Operator::IpAddressIfExists),
643            "NotIpAddressIfExists" => Ok(Operator::NotIpAddressIfExists),
644            "ArnEqualsIfExists" => Ok(Operator::ArnEqualsIfExists),
645            "ArnLikeIfExists" => Ok(Operator::ArnLikeIfExists),
646            "ArnNotEqualsIfExists" => Ok(Operator::ArnNotEqualsIfExists),
647            "ArnNotLikeIfExists" => Ok(Operator::ArnNotLikeIfExists),
648            _ => Err(format!("Unknown operator: {}", s)),
649        }
650    }
651}
652
653#[cfg(test)]
654mod tests {
655    use super::*;
656    use serde_json;
657
658    #[test]
659    fn test_operator_serialization() {
660        let operator = Operator::StringEquals;
661        let json = serde_json::to_string(&operator).unwrap();
662        assert_eq!(json, "\"StringEquals\"");
663
664        let deserialized: Operator = serde_json::from_str(&json).unwrap();
665        assert_eq!(operator, deserialized);
666    }
667
668    #[test]
669    fn test_multivalued_operators() {
670        let operator = Operator::ForAllValuesStringEquals;
671        let json = serde_json::to_string(&operator).unwrap();
672        assert_eq!(json, "\"ForAllValues:StringEquals\"");
673
674        let deserialized: Operator = serde_json::from_str(&json).unwrap();
675        assert_eq!(operator, deserialized);
676    }
677
678    #[test]
679    fn test_operator_categories() {
680        assert!(Operator::StringEquals.is_string_operator());
681        assert!(Operator::NumericEquals.is_numeric_operator());
682        assert!(Operator::DateEquals.is_date_operator());
683        assert!(Operator::Bool.is_boolean_operator());
684        assert!(Operator::ArnEquals.is_arn_operator());
685        assert!(Operator::IpAddress.is_ip_operator());
686        assert!(Operator::BinaryEquals.is_binary_operator());
687    }
688
689    #[test]
690    fn test_operator_features() {
691        assert!(Operator::StringLike.supports_wildcards());
692        assert!(Operator::StringEquals.supports_policy_variables());
693        assert!(!Operator::NumericEquals.supports_policy_variables());
694        assert!(Operator::ForAllValuesStringEquals.is_multivalued_operator());
695        assert!(Operator::StringEqualsIfExists.is_if_exists_operator());
696        assert!(Operator::StringNotEquals.is_negated_operator());
697
698        // Test multiple values support
699        assert!(Operator::StringEquals.supports_multiple_values());
700        assert!(Operator::StringNotEquals.supports_multiple_values());
701        assert!(Operator::NumericEquals.supports_multiple_values());
702        assert!(Operator::DateEquals.supports_multiple_values());
703        assert!(Operator::IpAddress.supports_multiple_values());
704        assert!(Operator::ArnEquals.supports_multiple_values());
705
706        // These should not support multiple values
707        assert!(!Operator::Bool.supports_multiple_values());
708        assert!(!Operator::BoolIfExists.supports_multiple_values());
709        assert!(!Operator::Null.supports_multiple_values());
710    }
711
712    #[test]
713    fn test_operator_category_strings() {
714        assert_eq!(Operator::StringEquals.category(), "String");
715        assert_eq!(Operator::NumericEquals.category(), "Numeric");
716        assert_eq!(Operator::DateEquals.category(), "Date");
717        assert_eq!(Operator::Bool.category(), "Boolean");
718        assert_eq!(Operator::BinaryEquals.category(), "Binary");
719        assert_eq!(Operator::IpAddress.category(), "IP Address");
720        assert_eq!(Operator::ArnEquals.category(), "ARN");
721        assert_eq!(Operator::Null.category(), "Null Check");
722    }
723
724    #[test]
725    fn test_operator_string_conversion() {
726        assert_eq!(Operator::StringEquals.as_str(), "StringEquals");
727        assert_eq!(
728            Operator::ForAllValuesStringEquals.as_str(),
729            "ForAllValues:StringEquals"
730        );
731        assert_eq!(
732            Operator::StringEqualsIfExists.as_str(),
733            "StringEqualsIfExists"
734        );
735    }
736
737    #[test]
738    fn test_operator_from_str() {
739        assert_eq!(
740            "StringEquals".parse::<Operator>().unwrap(),
741            Operator::StringEquals
742        );
743        assert_eq!(
744            "ForAllValues:StringEquals".parse::<Operator>().unwrap(),
745            Operator::ForAllValuesStringEquals
746        );
747        assert_eq!(
748            "StringEqualsIfExists".parse::<Operator>().unwrap(),
749            Operator::StringEqualsIfExists
750        );
751
752        assert!("InvalidOperator".parse::<Operator>().is_err());
753    }
754}