Loading codegen/src/aws_proxy.rs +6 −2 Original line number Diff line number Diff line Loading @@ -15,6 +15,7 @@ pub fn codegen(ops: &Operations, rust_types: &RustTypes, g: &mut Codegen) { "use crate::conv::{try_from_aws, try_into_aws};", "", "use s3s::S3;", "use s3s::S3Request;", "use s3s::S3Result;", "", "use tracing::debug;", Loading @@ -29,9 +30,12 @@ pub fn codegen(ops: &Operations, rust_types: &RustTypes, g: &mut Codegen) { let s3s_input = f!("s3s::dto::{}", op.input); let s3s_output = f!("s3s::dto::{}", op.output); g.ln("#[tracing::instrument(skip(self, input))]"); g.ln(f!("async fn {method_name}(&self, input: {s3s_input}) -> S3Result<{s3s_output}> {{")); g.ln("#[tracing::instrument(skip(self, req))]"); g.ln(f!( "async fn {method_name}(&self, req: S3Request<{s3s_input}>) -> S3Result<{s3s_output}> {{" )); g.ln("let input = req.input;"); g.ln("debug!(?input);"); if op.smithy_input == "Unit" { Loading codegen/src/ops.rs +4 −3 Original line number Diff line number Diff line Loading @@ -337,7 +337,7 @@ fn codegen_op_http_de(op: &Operation, rust_types: &RustTypes, g: &mut Codegen) { if op.name == "PutObject" { // POST object g.ln("if let Some(m) = req.extensions.remove::<http::Multipart>() {"); g.ln("if let Some(m) = req.s3ext.multipart.take() {"); g.ln(" return Self::deserialize_http_multipart(req, m);"); g.ln("}"); g.lf(); Loading Loading @@ -507,7 +507,7 @@ fn codegen_op_http_de_multipart(op: &Operation, rust_types: &RustTypes, g: &mut "let bucket = http::unwrap_bucket(req);", "let key = http::parse_field_value(&m, \"key\")?.ok_or_else(|| invalid_request!(\"missing key\"))?;", "", "let vec_stream = req.extensions.remove::<crate::stream::VecByteStream>().expect(\"missing vec stream\");", "let vec_stream = req.s3ext.vec_stream.take().expect(\"missing vec stream\");", "", "let content_length = i64::try_from(vec_stream.exact_remaining_length()).map_err(|e|s3_error!(e, InvalidArgument, \"content-length overflow\"))?;", "", Loading Loading @@ -600,7 +600,8 @@ fn codegen_op_http_call(op: &Operation, g: &mut Codegen) { let method = op.name.to_snake_case(); g.ln("let input = Self::deserialize_http(req)?;"); g.ln(f!("let result = s3.{method}(input).await;")); g.ln("let req = super::build_s3_request(input, req);"); g.ln(f!("let result = s3.{method}(req).await;")); g.ln("let res = match result {"); g.ln("Ok(output) => Self::serialize_http(output)?,"); Loading codegen/src/s3_trait.rs +4 −1 Original line number Diff line number Diff line Loading @@ -11,6 +11,7 @@ pub fn codegen(ops: &Operations, g: &mut Codegen) { "", "use crate::dto::*;", "use crate::error::S3Result;", "use crate::request::S3Request;", "", "/// An async trait which represents the S3 API", "#[async_trait::async_trait]", Loading @@ -20,9 +21,11 @@ pub fn codegen(ops: &Operations, g: &mut Codegen) { for op in ops.values() { let method_name = op.name.to_snake_case(); let input = &op.input; let output = &op.output; codegen_doc(op.doc.as_deref(), g); g.ln(f!("async fn {method_name}(&self, _input: {}) -> S3Result<{}> {{", op.input, op.output)); g.ln(f!("async fn {method_name}(&self, _req: S3Request<{input}>) -> S3Result<{output}> {{")); g.ln(f!("Err(s3_error!(NotImplemented, \"{} is not implemented yet\"))", op.name)); g.ln("}"); g.lf(); Loading crates/s3s-aws/src/proxy/generated.rs +319 −186 File changed.Preview size limit exceeded, changes collapsed. Show changes crates/s3s-fs/src/s3.rs +35 −19 Original line number Diff line number Diff line Loading @@ -3,6 +3,7 @@ use crate::utils::*; use s3s::dto::*; use s3s::s3_error; use s3s::S3Request; use s3s::S3Result; use s3s::S3; Loading @@ -27,7 +28,8 @@ use tracing::debug; #[async_trait::async_trait] impl S3 for FileSystem { #[tracing::instrument] async fn create_bucket(&self, input: CreateBucketInput) -> S3Result<CreateBucketOutput> { async fn create_bucket(&self, req: S3Request<CreateBucketInput>) -> S3Result<CreateBucketOutput> { let input = req.input; let path = self.get_bucket_path(&input.bucket)?; if path.exists() { Loading @@ -41,7 +43,8 @@ impl S3 for FileSystem { } #[tracing::instrument] async fn copy_object(&self, input: CopyObjectInput) -> S3Result<CopyObjectOutput> { async fn copy_object(&self, req: S3Request<CopyObjectInput>) -> S3Result<CopyObjectOutput> { let input = req.input; let (bucket, key) = match input.copy_source { CopySource::AccessPoint { .. } => return Err(s3_error!(NotImplemented)), CopySource::Bucket { ref bucket, ref key, .. } => (bucket, key), Loading Loading @@ -83,14 +86,16 @@ impl S3 for FileSystem { } #[tracing::instrument] async fn delete_bucket(&self, input: DeleteBucketInput) -> S3Result<DeleteBucketOutput> { async fn delete_bucket(&self, req: S3Request<DeleteBucketInput>) -> S3Result<DeleteBucketOutput> { let input = req.input; let path = self.get_bucket_path(&input.bucket)?; try_!(fs::remove_dir_all(path).await); Ok(DeleteBucketOutput {}) } #[tracing::instrument] async fn delete_object(&self, input: DeleteObjectInput) -> S3Result<DeleteObjectOutput> { async fn delete_object(&self, req: S3Request<DeleteObjectInput>) -> S3Result<DeleteObjectOutput> { let input = req.input; let path = self.get_object_path(&input.bucket, &input.key)?; if input.key.ends_with('/') { let mut dir = try_!(fs::read_dir(&path).await); Loading @@ -106,7 +111,8 @@ impl S3 for FileSystem { } #[tracing::instrument] async fn delete_objects(&self, input: DeleteObjectsInput) -> S3Result<DeleteObjectsOutput> { async fn delete_objects(&self, req: S3Request<DeleteObjectsInput>) -> S3Result<DeleteObjectsOutput> { let input = req.input; let mut objects: Vec<(PathBuf, String)> = Vec::new(); for object in input.delete.objects { let path = self.get_object_path(&input.bucket, &object.key)?; Loading Loading @@ -135,7 +141,8 @@ impl S3 for FileSystem { } #[tracing::instrument] async fn get_bucket_location(&self, input: GetBucketLocationInput) -> S3Result<GetBucketLocationOutput> { async fn get_bucket_location(&self, req: S3Request<GetBucketLocationInput>) -> S3Result<GetBucketLocationOutput> { let input = req.input; let path = self.get_bucket_path(&input.bucket)?; if !path.exists() { Loading @@ -147,7 +154,8 @@ impl S3 for FileSystem { } #[tracing::instrument] async fn get_object(&self, input: GetObjectInput) -> S3Result<GetObjectOutput> { async fn get_object(&self, req: S3Request<GetObjectInput>) -> S3Result<GetObjectOutput> { let input = req.input; let object_path = self.get_object_path(&input.bucket, &input.key)?; let mut file = fs::File::open(&object_path).await.map_err(|e| s3_error!(e, NoSuchKey))?; Loading Loading @@ -208,7 +216,8 @@ impl S3 for FileSystem { } #[tracing::instrument] async fn head_bucket(&self, input: HeadBucketInput) -> S3Result<HeadBucketOutput> { async fn head_bucket(&self, req: S3Request<HeadBucketInput>) -> S3Result<HeadBucketOutput> { let input = req.input; let path = self.get_bucket_path(&input.bucket)?; if !path.exists() { Loading @@ -219,7 +228,8 @@ impl S3 for FileSystem { } #[tracing::instrument] async fn head_object(&self, input: HeadObjectInput) -> S3Result<HeadObjectOutput> { async fn head_object(&self, req: S3Request<HeadObjectInput>) -> S3Result<HeadObjectOutput> { let input = req.input; let path = self.get_object_path(&input.bucket, &input.key)?; if !path.exists() { Loading @@ -246,7 +256,7 @@ impl S3 for FileSystem { } #[tracing::instrument] async fn list_buckets(&self, _: ListBucketsInput) -> S3Result<ListBucketsOutput> { async fn list_buckets(&self, _: S3Request<ListBucketsInput>) -> S3Result<ListBucketsOutput> { let mut buckets: Vec<Bucket> = Vec::new(); let mut iter = try_!(fs::read_dir(&self.root).await); while let Some(entry) = try_!(iter.next_entry().await) { Loading Loading @@ -279,8 +289,8 @@ impl S3 for FileSystem { } #[tracing::instrument] async fn list_objects(&self, input: ListObjectsInput) -> S3Result<ListObjectsOutput> { let v2 = self.list_objects_v2(input.into()).await?; async fn list_objects(&self, req: S3Request<ListObjectsInput>) -> S3Result<ListObjectsOutput> { let v2 = self.list_objects_v2(req.map_input(Into::into)).await?; let output = ListObjectsOutput { contents: v2.contents, Loading @@ -295,7 +305,8 @@ impl S3 for FileSystem { } #[tracing::instrument] async fn list_objects_v2(&self, input: ListObjectsV2Input) -> S3Result<ListObjectsV2Output> { async fn list_objects_v2(&self, req: S3Request<ListObjectsV2Input>) -> S3Result<ListObjectsV2Output> { let input = req.input; let path = self.get_bucket_path(&input.bucket)?; if path.exists().not() { Loading Loading @@ -360,7 +371,8 @@ impl S3 for FileSystem { } #[tracing::instrument] async fn put_object(&self, input: PutObjectInput) -> S3Result<PutObjectOutput> { async fn put_object(&self, req: S3Request<PutObjectInput>) -> S3Result<PutObjectOutput> { let input = req.input; if let Some(ref storage_class) = input.storage_class { let is_valid = ["STANDARD", "REDUCED_REDUNDANCY"].contains(&storage_class.as_str()); if !is_valid { Loading Loading @@ -417,7 +429,8 @@ impl S3 for FileSystem { } #[tracing::instrument] async fn create_multipart_upload(&self, input: CreateMultipartUploadInput) -> S3Result<CreateMultipartUploadOutput> { async fn create_multipart_upload(&self, req: S3Request<CreateMultipartUploadInput>) -> S3Result<CreateMultipartUploadOutput> { let input = req.input; let upload_id = uuid::Uuid::new_v4().to_string(); let output = CreateMultipartUploadOutput { Loading @@ -431,13 +444,13 @@ impl S3 for FileSystem { } #[tracing::instrument] async fn upload_part(&self, input: UploadPartInput) -> S3Result<UploadPartOutput> { async fn upload_part(&self, req: S3Request<UploadPartInput>) -> S3Result<UploadPartOutput> { let UploadPartInput { body, upload_id, part_number, .. } = input; } = req.input; let body = body.ok_or_else(|| s3_error!(IncompleteBody))?; Loading Loading @@ -467,14 +480,17 @@ impl S3 for FileSystem { } #[tracing::instrument] async fn complete_multipart_upload(&self, input: CompleteMultipartUploadInput) -> S3Result<CompleteMultipartUploadOutput> { async fn complete_multipart_upload( &self, req: S3Request<CompleteMultipartUploadInput>, ) -> S3Result<CompleteMultipartUploadOutput> { let CompleteMultipartUploadInput { multipart_upload, bucket, key, upload_id, .. } = input; } = req.input; let Some(multipart_upload) = multipart_upload else { return Err(s3_error!(InvalidPart)) }; Loading Loading
codegen/src/aws_proxy.rs +6 −2 Original line number Diff line number Diff line Loading @@ -15,6 +15,7 @@ pub fn codegen(ops: &Operations, rust_types: &RustTypes, g: &mut Codegen) { "use crate::conv::{try_from_aws, try_into_aws};", "", "use s3s::S3;", "use s3s::S3Request;", "use s3s::S3Result;", "", "use tracing::debug;", Loading @@ -29,9 +30,12 @@ pub fn codegen(ops: &Operations, rust_types: &RustTypes, g: &mut Codegen) { let s3s_input = f!("s3s::dto::{}", op.input); let s3s_output = f!("s3s::dto::{}", op.output); g.ln("#[tracing::instrument(skip(self, input))]"); g.ln(f!("async fn {method_name}(&self, input: {s3s_input}) -> S3Result<{s3s_output}> {{")); g.ln("#[tracing::instrument(skip(self, req))]"); g.ln(f!( "async fn {method_name}(&self, req: S3Request<{s3s_input}>) -> S3Result<{s3s_output}> {{" )); g.ln("let input = req.input;"); g.ln("debug!(?input);"); if op.smithy_input == "Unit" { Loading
codegen/src/ops.rs +4 −3 Original line number Diff line number Diff line Loading @@ -337,7 +337,7 @@ fn codegen_op_http_de(op: &Operation, rust_types: &RustTypes, g: &mut Codegen) { if op.name == "PutObject" { // POST object g.ln("if let Some(m) = req.extensions.remove::<http::Multipart>() {"); g.ln("if let Some(m) = req.s3ext.multipart.take() {"); g.ln(" return Self::deserialize_http_multipart(req, m);"); g.ln("}"); g.lf(); Loading Loading @@ -507,7 +507,7 @@ fn codegen_op_http_de_multipart(op: &Operation, rust_types: &RustTypes, g: &mut "let bucket = http::unwrap_bucket(req);", "let key = http::parse_field_value(&m, \"key\")?.ok_or_else(|| invalid_request!(\"missing key\"))?;", "", "let vec_stream = req.extensions.remove::<crate::stream::VecByteStream>().expect(\"missing vec stream\");", "let vec_stream = req.s3ext.vec_stream.take().expect(\"missing vec stream\");", "", "let content_length = i64::try_from(vec_stream.exact_remaining_length()).map_err(|e|s3_error!(e, InvalidArgument, \"content-length overflow\"))?;", "", Loading Loading @@ -600,7 +600,8 @@ fn codegen_op_http_call(op: &Operation, g: &mut Codegen) { let method = op.name.to_snake_case(); g.ln("let input = Self::deserialize_http(req)?;"); g.ln(f!("let result = s3.{method}(input).await;")); g.ln("let req = super::build_s3_request(input, req);"); g.ln(f!("let result = s3.{method}(req).await;")); g.ln("let res = match result {"); g.ln("Ok(output) => Self::serialize_http(output)?,"); Loading
codegen/src/s3_trait.rs +4 −1 Original line number Diff line number Diff line Loading @@ -11,6 +11,7 @@ pub fn codegen(ops: &Operations, g: &mut Codegen) { "", "use crate::dto::*;", "use crate::error::S3Result;", "use crate::request::S3Request;", "", "/// An async trait which represents the S3 API", "#[async_trait::async_trait]", Loading @@ -20,9 +21,11 @@ pub fn codegen(ops: &Operations, g: &mut Codegen) { for op in ops.values() { let method_name = op.name.to_snake_case(); let input = &op.input; let output = &op.output; codegen_doc(op.doc.as_deref(), g); g.ln(f!("async fn {method_name}(&self, _input: {}) -> S3Result<{}> {{", op.input, op.output)); g.ln(f!("async fn {method_name}(&self, _req: S3Request<{input}>) -> S3Result<{output}> {{")); g.ln(f!("Err(s3_error!(NotImplemented, \"{} is not implemented yet\"))", op.name)); g.ln("}"); g.lf(); Loading
crates/s3s-aws/src/proxy/generated.rs +319 −186 File changed.Preview size limit exceeded, changes collapsed. Show changes
crates/s3s-fs/src/s3.rs +35 −19 Original line number Diff line number Diff line Loading @@ -3,6 +3,7 @@ use crate::utils::*; use s3s::dto::*; use s3s::s3_error; use s3s::S3Request; use s3s::S3Result; use s3s::S3; Loading @@ -27,7 +28,8 @@ use tracing::debug; #[async_trait::async_trait] impl S3 for FileSystem { #[tracing::instrument] async fn create_bucket(&self, input: CreateBucketInput) -> S3Result<CreateBucketOutput> { async fn create_bucket(&self, req: S3Request<CreateBucketInput>) -> S3Result<CreateBucketOutput> { let input = req.input; let path = self.get_bucket_path(&input.bucket)?; if path.exists() { Loading @@ -41,7 +43,8 @@ impl S3 for FileSystem { } #[tracing::instrument] async fn copy_object(&self, input: CopyObjectInput) -> S3Result<CopyObjectOutput> { async fn copy_object(&self, req: S3Request<CopyObjectInput>) -> S3Result<CopyObjectOutput> { let input = req.input; let (bucket, key) = match input.copy_source { CopySource::AccessPoint { .. } => return Err(s3_error!(NotImplemented)), CopySource::Bucket { ref bucket, ref key, .. } => (bucket, key), Loading Loading @@ -83,14 +86,16 @@ impl S3 for FileSystem { } #[tracing::instrument] async fn delete_bucket(&self, input: DeleteBucketInput) -> S3Result<DeleteBucketOutput> { async fn delete_bucket(&self, req: S3Request<DeleteBucketInput>) -> S3Result<DeleteBucketOutput> { let input = req.input; let path = self.get_bucket_path(&input.bucket)?; try_!(fs::remove_dir_all(path).await); Ok(DeleteBucketOutput {}) } #[tracing::instrument] async fn delete_object(&self, input: DeleteObjectInput) -> S3Result<DeleteObjectOutput> { async fn delete_object(&self, req: S3Request<DeleteObjectInput>) -> S3Result<DeleteObjectOutput> { let input = req.input; let path = self.get_object_path(&input.bucket, &input.key)?; if input.key.ends_with('/') { let mut dir = try_!(fs::read_dir(&path).await); Loading @@ -106,7 +111,8 @@ impl S3 for FileSystem { } #[tracing::instrument] async fn delete_objects(&self, input: DeleteObjectsInput) -> S3Result<DeleteObjectsOutput> { async fn delete_objects(&self, req: S3Request<DeleteObjectsInput>) -> S3Result<DeleteObjectsOutput> { let input = req.input; let mut objects: Vec<(PathBuf, String)> = Vec::new(); for object in input.delete.objects { let path = self.get_object_path(&input.bucket, &object.key)?; Loading Loading @@ -135,7 +141,8 @@ impl S3 for FileSystem { } #[tracing::instrument] async fn get_bucket_location(&self, input: GetBucketLocationInput) -> S3Result<GetBucketLocationOutput> { async fn get_bucket_location(&self, req: S3Request<GetBucketLocationInput>) -> S3Result<GetBucketLocationOutput> { let input = req.input; let path = self.get_bucket_path(&input.bucket)?; if !path.exists() { Loading @@ -147,7 +154,8 @@ impl S3 for FileSystem { } #[tracing::instrument] async fn get_object(&self, input: GetObjectInput) -> S3Result<GetObjectOutput> { async fn get_object(&self, req: S3Request<GetObjectInput>) -> S3Result<GetObjectOutput> { let input = req.input; let object_path = self.get_object_path(&input.bucket, &input.key)?; let mut file = fs::File::open(&object_path).await.map_err(|e| s3_error!(e, NoSuchKey))?; Loading Loading @@ -208,7 +216,8 @@ impl S3 for FileSystem { } #[tracing::instrument] async fn head_bucket(&self, input: HeadBucketInput) -> S3Result<HeadBucketOutput> { async fn head_bucket(&self, req: S3Request<HeadBucketInput>) -> S3Result<HeadBucketOutput> { let input = req.input; let path = self.get_bucket_path(&input.bucket)?; if !path.exists() { Loading @@ -219,7 +228,8 @@ impl S3 for FileSystem { } #[tracing::instrument] async fn head_object(&self, input: HeadObjectInput) -> S3Result<HeadObjectOutput> { async fn head_object(&self, req: S3Request<HeadObjectInput>) -> S3Result<HeadObjectOutput> { let input = req.input; let path = self.get_object_path(&input.bucket, &input.key)?; if !path.exists() { Loading @@ -246,7 +256,7 @@ impl S3 for FileSystem { } #[tracing::instrument] async fn list_buckets(&self, _: ListBucketsInput) -> S3Result<ListBucketsOutput> { async fn list_buckets(&self, _: S3Request<ListBucketsInput>) -> S3Result<ListBucketsOutput> { let mut buckets: Vec<Bucket> = Vec::new(); let mut iter = try_!(fs::read_dir(&self.root).await); while let Some(entry) = try_!(iter.next_entry().await) { Loading Loading @@ -279,8 +289,8 @@ impl S3 for FileSystem { } #[tracing::instrument] async fn list_objects(&self, input: ListObjectsInput) -> S3Result<ListObjectsOutput> { let v2 = self.list_objects_v2(input.into()).await?; async fn list_objects(&self, req: S3Request<ListObjectsInput>) -> S3Result<ListObjectsOutput> { let v2 = self.list_objects_v2(req.map_input(Into::into)).await?; let output = ListObjectsOutput { contents: v2.contents, Loading @@ -295,7 +305,8 @@ impl S3 for FileSystem { } #[tracing::instrument] async fn list_objects_v2(&self, input: ListObjectsV2Input) -> S3Result<ListObjectsV2Output> { async fn list_objects_v2(&self, req: S3Request<ListObjectsV2Input>) -> S3Result<ListObjectsV2Output> { let input = req.input; let path = self.get_bucket_path(&input.bucket)?; if path.exists().not() { Loading Loading @@ -360,7 +371,8 @@ impl S3 for FileSystem { } #[tracing::instrument] async fn put_object(&self, input: PutObjectInput) -> S3Result<PutObjectOutput> { async fn put_object(&self, req: S3Request<PutObjectInput>) -> S3Result<PutObjectOutput> { let input = req.input; if let Some(ref storage_class) = input.storage_class { let is_valid = ["STANDARD", "REDUCED_REDUNDANCY"].contains(&storage_class.as_str()); if !is_valid { Loading Loading @@ -417,7 +429,8 @@ impl S3 for FileSystem { } #[tracing::instrument] async fn create_multipart_upload(&self, input: CreateMultipartUploadInput) -> S3Result<CreateMultipartUploadOutput> { async fn create_multipart_upload(&self, req: S3Request<CreateMultipartUploadInput>) -> S3Result<CreateMultipartUploadOutput> { let input = req.input; let upload_id = uuid::Uuid::new_v4().to_string(); let output = CreateMultipartUploadOutput { Loading @@ -431,13 +444,13 @@ impl S3 for FileSystem { } #[tracing::instrument] async fn upload_part(&self, input: UploadPartInput) -> S3Result<UploadPartOutput> { async fn upload_part(&self, req: S3Request<UploadPartInput>) -> S3Result<UploadPartOutput> { let UploadPartInput { body, upload_id, part_number, .. } = input; } = req.input; let body = body.ok_or_else(|| s3_error!(IncompleteBody))?; Loading Loading @@ -467,14 +480,17 @@ impl S3 for FileSystem { } #[tracing::instrument] async fn complete_multipart_upload(&self, input: CompleteMultipartUploadInput) -> S3Result<CompleteMultipartUploadOutput> { async fn complete_multipart_upload( &self, req: S3Request<CompleteMultipartUploadInput>, ) -> S3Result<CompleteMultipartUploadOutput> { let CompleteMultipartUploadInput { multipart_upload, bucket, key, upload_id, .. } = input; } = req.input; let Some(multipart_upload) = multipart_upload else { return Err(s3_error!(InvalidPart)) }; Loading