hemmer_provider_generator_parser/
operation_mapper.rs

1//! Operation classification and CRUD mapping
2//!
3//! Maps AWS SDK operation names to CRUD operations.
4
5/// CRUD operation types
6#[derive(Debug, Clone, Copy, PartialEq, Eq)]
7pub enum CrudOperation {
8    Create,
9    Read,
10    Update,
11    Delete,
12}
13
14/// Classifies SDK operations into CRUD operations
15pub struct OperationClassifier;
16
17impl OperationClassifier {
18    /// Classify an operation name into a CRUD operation
19    ///
20    /// # Examples
21    /// ```
22    /// use hemmer_provider_generator_parser::OperationClassifier;
23    /// use hemmer_provider_generator_parser::CrudOperation;
24    ///
25    /// assert_eq!(
26    ///     OperationClassifier::classify("create_bucket"),
27    ///     Some(CrudOperation::Create)
28    /// );
29    /// assert_eq!(
30    ///     OperationClassifier::classify("get_bucket_location"),
31    ///     Some(CrudOperation::Read)
32    /// );
33    /// ```
34    pub fn classify(operation_name: &str) -> Option<CrudOperation> {
35        let lower = operation_name.to_lowercase();
36
37        // Create operations
38        if lower.starts_with("create") || lower.starts_with("put") {
39            // PutObject is create, but PutBucketAcl might be update
40            // For now, treat all put_* as potentially create
41            return Some(CrudOperation::Create);
42        }
43
44        // Read operations
45        if lower.starts_with("get")
46            || lower.starts_with("describe")
47            || lower.starts_with("head")
48            || lower.starts_with("list")
49        {
50            return Some(CrudOperation::Read);
51        }
52
53        // Update operations
54        if lower.starts_with("update") || lower.starts_with("modify") {
55            return Some(CrudOperation::Update);
56        }
57
58        // Delete operations
59        if lower.starts_with("delete") || lower.starts_with("remove") {
60            return Some(CrudOperation::Delete);
61        }
62
63        None
64    }
65
66    /// Extract resource name from operation name
67    ///
68    /// # Examples
69    /// ```
70    /// use hemmer_provider_generator_parser::OperationClassifier;
71    ///
72    /// assert_eq!(
73    ///     OperationClassifier::extract_resource("create_bucket"),
74    ///     "bucket"
75    /// );
76    /// assert_eq!(
77    ///     OperationClassifier::extract_resource("put_bucket_acl"),
78    ///     "bucket"
79    /// );
80    /// ```
81    pub fn extract_resource(operation_name: &str) -> String {
82        let lower = operation_name.to_lowercase();
83
84        // Remove common operation prefixes
85        let without_prefix = lower
86            .strip_prefix("create_")
87            .or_else(|| lower.strip_prefix("get_"))
88            .or_else(|| lower.strip_prefix("put_"))
89            .or_else(|| lower.strip_prefix("describe_"))
90            .or_else(|| lower.strip_prefix("head_"))
91            .or_else(|| lower.strip_prefix("list_"))
92            .or_else(|| lower.strip_prefix("update_"))
93            .or_else(|| lower.strip_prefix("modify_"))
94            .or_else(|| lower.strip_prefix("delete_"))
95            .or_else(|| lower.strip_prefix("remove_"))
96            .unwrap_or(&lower);
97
98        // Take first word as resource name (e.g., "bucket" from "bucket_acl")
99        without_prefix
100            .split('_')
101            .next()
102            .unwrap_or(without_prefix)
103            .to_string()
104    }
105}
106
107#[cfg(test)]
108mod tests {
109    use super::*;
110
111    #[test]
112    fn test_classify_create() {
113        assert_eq!(
114            OperationClassifier::classify("create_bucket"),
115            Some(CrudOperation::Create)
116        );
117        assert_eq!(
118            OperationClassifier::classify("put_object"),
119            Some(CrudOperation::Create)
120        );
121    }
122
123    #[test]
124    fn test_classify_read() {
125        assert_eq!(
126            OperationClassifier::classify("get_bucket_location"),
127            Some(CrudOperation::Read)
128        );
129        assert_eq!(
130            OperationClassifier::classify("describe_instances"),
131            Some(CrudOperation::Read)
132        );
133        assert_eq!(
134            OperationClassifier::classify("head_bucket"),
135            Some(CrudOperation::Read)
136        );
137        assert_eq!(
138            OperationClassifier::classify("list_buckets"),
139            Some(CrudOperation::Read)
140        );
141    }
142
143    #[test]
144    fn test_classify_update() {
145        assert_eq!(
146            OperationClassifier::classify("update_bucket"),
147            Some(CrudOperation::Update)
148        );
149        assert_eq!(
150            OperationClassifier::classify("modify_instance_attribute"),
151            Some(CrudOperation::Update)
152        );
153    }
154
155    #[test]
156    fn test_classify_delete() {
157        assert_eq!(
158            OperationClassifier::classify("delete_bucket"),
159            Some(CrudOperation::Delete)
160        );
161        assert_eq!(
162            OperationClassifier::classify("remove_tags"),
163            Some(CrudOperation::Delete)
164        );
165    }
166
167    #[test]
168    fn test_extract_resource() {
169        assert_eq!(
170            OperationClassifier::extract_resource("create_bucket"),
171            "bucket"
172        );
173        assert_eq!(
174            OperationClassifier::extract_resource("get_bucket_location"),
175            "bucket"
176        );
177        assert_eq!(
178            OperationClassifier::extract_resource("put_object"),
179            "object"
180        );
181        assert_eq!(
182            OperationClassifier::extract_resource("delete_bucket"),
183            "bucket"
184        );
185    }
186}