1use crate::error::S3Error;
2use crate::{Bucket, Region};
3
4#[allow(dead_code)]
6#[derive(Clone, Debug)]
7enum CannedBucketAcl {
8 Private,
9 PublicRead,
10 PublicReadWrite,
11 AuthenticatedRead,
12}
13
14use http::header::HeaderName;
15use http::HeaderMap;
16use std::fmt;
17
18impl fmt::Display for CannedBucketAcl {
19 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
20 match self {
21 CannedBucketAcl::Private => write!(f, "private"),
22 CannedBucketAcl::PublicRead => write!(f, "public-read"),
23 CannedBucketAcl::PublicReadWrite => write!(f, "public-read-write"),
24 CannedBucketAcl::AuthenticatedRead => write!(f, "authenticated-read"),
25 }
26 }
27}
28
29#[allow(dead_code)]
31#[derive(Clone, Debug)]
32enum BucketAcl {
33 Id { id: String },
34 Uri { uri: String },
35 Email { email: String },
36}
37
38impl fmt::Display for BucketAcl {
39 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
40 match self {
41 BucketAcl::Id { id } => write!(f, "id=\"{}\"", id),
42 BucketAcl::Uri { uri } => write!(f, "uri=\"{}\"", uri),
43 BucketAcl::Email { email } => write!(f, "email=\"{}\"", email),
44 }
45 }
46}
47
48#[derive(Clone, Debug)]
49pub struct BucketConfiguration {
50 acl: CannedBucketAcl,
51 object_lock_enabled: bool,
52 grant_full_control: Option<Vec<BucketAcl>>,
53 grant_read: Option<Vec<BucketAcl>>,
54 grant_read_acp: Option<Vec<BucketAcl>>,
55 grant_write: Option<Vec<BucketAcl>>,
56 grant_write_acp: Option<Vec<BucketAcl>>,
57 location_constraint: Option<Region>,
58}
59
60impl Default for BucketConfiguration {
61 fn default() -> Self {
62 BucketConfiguration::private()
63 }
64}
65
66fn acl_list(acl: &[BucketAcl]) -> String {
67 acl.iter()
68 .map(|x| x.to_string())
69 .collect::<Vec<String>>()
70 .join(",")
71}
72
73impl BucketConfiguration {
74 pub fn public() -> Self {
75 BucketConfiguration {
76 acl: CannedBucketAcl::PublicReadWrite,
77 object_lock_enabled: false,
78 grant_full_control: None,
79 grant_read: None,
80 grant_read_acp: None,
81 grant_write: None,
82 grant_write_acp: None,
83 location_constraint: None,
84 }
85 }
86
87 pub fn private() -> Self {
88 BucketConfiguration {
89 acl: CannedBucketAcl::Private,
90 object_lock_enabled: false,
91 grant_full_control: None,
92 grant_read: None,
93 grant_read_acp: None,
94 grant_write: None,
95 grant_write_acp: None,
96 location_constraint: None,
97 }
98 }
99
100 pub fn set_region(&mut self, region: Region) {
101 self.set_location_constraint(region)
102 }
103
104 pub fn set_location_constraint(&mut self, region: Region) {
105 self.location_constraint = Some(region)
106 }
107
108 pub fn location_constraint_payload(&self) -> Option<String> {
109 if let Some(ref location_constraint) = self.location_constraint {
110 if location_constraint == &Region::UsEast1 {
111 return None;
112 }
113 Some(format!(
114 "<CreateBucketConfiguration><LocationConstraint>{}</LocationConstraint></CreateBucketConfiguration>",
115 location_constraint
116 ))
117 } else {
118 None
119 }
120 }
121
122 pub fn add_headers(&self, headers: &mut HeaderMap) -> Result<(), S3Error> {
123 headers.insert(
124 HeaderName::from_static("x-amz-acl"),
125 self.acl.to_string().parse()?,
126 );
127 if self.object_lock_enabled {
128 headers.insert(
129 HeaderName::from_static("x-amz-bucket-object-lock-enabled"),
130 "Enabled".to_string().parse()?,
131 );
132 }
133 if let Some(ref value) = self.grant_full_control {
134 headers.insert(
135 HeaderName::from_static("x-amz-grant-full-control"),
136 acl_list(value).parse()?,
137 );
138 }
139 if let Some(ref value) = self.grant_read {
140 headers.insert(
141 HeaderName::from_static("x-amz-grant-read"),
142 acl_list(value).parse()?,
143 );
144 }
145 if let Some(ref value) = self.grant_read_acp {
146 headers.insert(
147 HeaderName::from_static("x-amz-grant-read-acp"),
148 acl_list(value).parse()?,
149 );
150 }
151 if let Some(ref value) = self.grant_write {
152 headers.insert(
153 HeaderName::from_static("x-amz-grant-write"),
154 acl_list(value).parse()?,
155 );
156 }
157 if let Some(ref value) = self.grant_write_acp {
158 headers.insert(
159 HeaderName::from_static("x-amz-grant-write-acp"),
160 acl_list(value).parse()?,
161 );
162 }
163 Ok(())
164 }
165}
166
167#[allow(dead_code)]
168pub struct CreateBucketResponse {
169 pub bucket: Bucket,
170 pub response_text: String,
171 pub response_code: u16,
172}
173
174impl CreateBucketResponse {
175 pub fn success(&self) -> bool {
176 self.response_code == 200
177 }
178}