1use bytes::Bytes;
2use chrono::{DateTime, Utc};
3use parking_lot::RwLock;
4use std::collections::{BTreeMap, HashMap};
5use std::sync::Arc;
6
7#[derive(Debug, Clone)]
9pub struct AclGrant {
10 pub grantee_type: String, pub grantee_id: Option<String>,
12 pub grantee_display_name: Option<String>,
13 pub grantee_uri: Option<String>,
14 pub permission: String, }
16
17#[derive(Debug, Clone)]
18pub struct S3Object {
19 pub key: String,
20 pub data: Bytes,
21 pub content_type: String,
22 pub etag: String,
23 pub size: u64,
24 pub last_modified: DateTime<Utc>,
25 pub metadata: HashMap<String, String>,
26 pub storage_class: String,
27 pub tags: HashMap<String, String>,
28 pub acl_grants: Vec<AclGrant>,
29 pub acl_owner_id: Option<String>,
30 pub parts_count: Option<u32>,
32 pub part_sizes: Option<Vec<(u32, u64)>>,
34 pub sse_algorithm: Option<String>,
36 pub sse_kms_key_id: Option<String>,
38 pub bucket_key_enabled: Option<bool>,
40 pub version_id: Option<String>,
41 pub is_delete_marker: bool,
42 pub content_encoding: Option<String>,
43 pub website_redirect_location: Option<String>,
44 pub restore_ongoing: Option<bool>,
46 pub restore_expiry: Option<String>,
48 pub checksum_algorithm: Option<String>,
50 pub checksum_value: Option<String>,
52 pub lock_mode: Option<String>,
54 pub lock_retain_until: Option<DateTime<Utc>>,
56 pub lock_legal_hold: Option<String>,
58}
59
60#[derive(Debug, Clone)]
62pub struct UploadPart {
63 pub part_number: u32,
64 pub data: Bytes,
65 pub etag: String,
66 pub size: u64,
67 pub last_modified: DateTime<Utc>,
68}
69
70#[derive(Debug, Clone)]
72pub struct MultipartUpload {
73 pub upload_id: String,
74 pub key: String,
75 pub initiated: DateTime<Utc>,
76 pub parts: BTreeMap<u32, UploadPart>,
78 pub metadata: HashMap<String, String>,
80 pub content_type: String,
81 pub storage_class: String,
82 pub sse_algorithm: Option<String>,
83 pub sse_kms_key_id: Option<String>,
84 pub tagging: Option<String>,
85 pub acl_grants: Vec<AclGrant>,
86 pub checksum_algorithm: Option<String>,
87}
88
89#[derive(Debug, Clone)]
90pub struct S3Bucket {
91 pub name: String,
92 pub creation_date: DateTime<Utc>,
93 pub region: String,
94 pub objects: BTreeMap<String, S3Object>,
96 pub tags: HashMap<String, String>,
97 pub acl_grants: Vec<AclGrant>,
98 pub acl_owner_id: String,
99 pub multipart_uploads: HashMap<String, MultipartUpload>,
101 pub versioning: Option<String>,
103 pub object_versions: HashMap<String, Vec<S3Object>>,
105 pub acl: Option<String>,
107 pub encryption_config: Option<String>,
108 pub lifecycle_config: Option<String>,
109 pub policy: Option<String>,
110 pub cors_config: Option<String>,
111 pub notification_config: Option<String>,
112 pub logging_config: Option<String>,
113 pub website_config: Option<String>,
114 pub accelerate_status: Option<String>,
115 pub public_access_block: Option<String>,
116 pub object_lock_config: Option<String>,
117 pub replication_config: Option<String>,
118 pub ownership_controls: Option<String>,
119 pub inventory_configs: HashMap<String, String>,
120 pub eventbridge_enabled: bool,
122}
123
124impl S3Bucket {
125 pub fn new(name: &str, region: &str, owner_id: &str) -> Self {
126 Self {
127 name: name.to_string(),
128 creation_date: Utc::now(),
129 region: region.to_string(),
130 objects: BTreeMap::new(),
131 tags: HashMap::new(),
132 acl_grants: vec![AclGrant {
133 grantee_type: "CanonicalUser".to_string(),
134 grantee_id: Some(owner_id.to_string()),
135 grantee_display_name: Some(owner_id.to_string()),
136 grantee_uri: None,
137 permission: "FULL_CONTROL".to_string(),
138 }],
139 acl_owner_id: owner_id.to_string(),
140 multipart_uploads: HashMap::new(),
141 versioning: None,
142 object_versions: HashMap::new(),
143 acl: None,
144 encryption_config: None,
145 lifecycle_config: None,
146 policy: None,
147 cors_config: None,
148 notification_config: None,
149 logging_config: None,
150 website_config: None,
151 accelerate_status: None,
152 public_access_block: None,
153 object_lock_config: None,
154 replication_config: None,
155 ownership_controls: None,
156 inventory_configs: HashMap::new(),
157 eventbridge_enabled: false,
158 }
159 }
160}
161
162#[derive(Debug, Clone)]
164pub struct S3NotificationEvent {
165 pub bucket: String,
166 pub key: String,
167 pub event_type: String,
168 pub timestamp: DateTime<Utc>,
169}
170
171pub struct S3State {
172 pub account_id: String,
173 pub region: String,
174 pub buckets: HashMap<String, S3Bucket>,
175 pub notification_events: Vec<S3NotificationEvent>,
176}
177
178impl S3State {
179 pub fn new(account_id: &str, region: &str) -> Self {
180 Self {
181 account_id: account_id.to_string(),
182 region: region.to_string(),
183 buckets: HashMap::new(),
184 notification_events: Vec::new(),
185 }
186 }
187
188 pub fn reset(&mut self) {
189 self.buckets.clear();
190 self.notification_events.clear();
191 }
192}
193
194pub type SharedS3State = Arc<RwLock<S3State>>;