Page Menu
Home
Phabricator
Search
Configure Global Search
Log In
Files
F3504807
D5679.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
2 KB
Referenced Files
None
Subscribers
None
D5679.diff
View Options
diff --git a/services/blob/src/main.rs b/services/blob/src/main.rs
--- a/services/blob/src/main.rs
+++ b/services/blob/src/main.rs
@@ -1,4 +1,5 @@
pub mod constants;
+pub mod s3;
pub mod service;
pub mod tools;
diff --git a/services/blob/src/s3.rs b/services/blob/src/s3.rs
new file mode 100644
--- /dev/null
+++ b/services/blob/src/s3.rs
@@ -0,0 +1,95 @@
+use anyhow::{anyhow, Result};
+use aws_sdk_s3::model::CompletedPart;
+use aws_sdk_s3::Client as S3Client;
+use std::sync::Arc;
+
+/// A helper structure representing an S3 object path
+#[derive(Clone, Debug)]
+pub struct S3Path {
+ pub bucket_name: String,
+ pub object_name: String,
+}
+
+impl S3Path {
+ /// Constructs an [`S3Path`] from given string
+ /// The path should be in the following format: `[bucket_name]/[object_name]`
+ pub fn from_full_path(full_path: &str) -> Result<Self> {
+ if !full_path.contains('/') {
+ return Err(anyhow!("S3 path should contain the '/' separator"));
+ }
+
+ let mut split = full_path.split('/');
+ Ok(S3Path {
+ bucket_name: split
+ .next()
+ .ok_or(anyhow!("Expected bucket name in path [{}]", full_path))?
+ .to_string(),
+ object_name: split
+ .next()
+ .ok_or(anyhow!("Expected object name in path [{}]", full_path))?
+ .to_string(),
+ })
+ }
+
+ /// Retrieves full S3 path string in the following format: `[bucket_name]/[object_name]`
+ pub fn to_full_path(&self) -> String {
+ format!("{}/{}", self.bucket_name, self.object_name)
+ }
+}
+
+/// Represents a multipart upload session to the AWS S3
+pub struct MultiPartUploadSession {
+ client: Arc<S3Client>,
+ bucket_name: String,
+ object_name: String,
+ upload_id: String,
+ upload_parts: Vec<CompletedPart>,
+}
+
+impl MultiPartUploadSession {
+ /// Starts a new upload session and returns its instance
+ pub async fn start(client: &Arc<S3Client>, s3_path: &S3Path) -> Result<Self> {
+ unimplemented!()
+ }
+
+ /// adds data part to the multipart upload
+ pub async fn add_part(&mut self, part: Vec<u8>) -> Result<()> {
+ unimplemented!()
+ }
+
+ /// finishes the upload
+ pub async fn finish_upload(&self) -> Result<()> {
+ unimplemented!()
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+
+ #[test]
+ fn test_s3path_from_full_path() {
+ let full_path = "my_bucket/some_object";
+ let s3_path = S3Path::from_full_path(full_path);
+ assert!(s3_path.is_ok());
+ let s3_path = s3_path.unwrap();
+ assert_eq!(&s3_path.bucket_name, "my_bucket");
+ assert_eq!(&s3_path.object_name, "some_object");
+ }
+
+ #[test]
+ fn test_s3path_from_invalid_path() {
+ let result = S3Path::from_full_path("invalid_path");
+ assert!(result.is_err())
+ }
+
+ #[test]
+ fn test_s3path_to_full_path() {
+ let s3_path = S3Path {
+ bucket_name: "my_bucket".to_string(),
+ object_name: "some_object".to_string(),
+ };
+ let full_path = s3_path.to_full_path();
+ assert_eq!(full_path, "my_bucket/some_object");
+ }
+}
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sat, Dec 21, 10:32 AM (19 h, 53 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
2687433
Default Alt Text
D5679.diff (2 KB)
Attached To
Mode
D5679: [services][blob] Introduce S3 primitives
Attached
Detach File
Event Timeline
Log In to Comment