use aws_sdk_s3::primitives::ByteStream;
use tokio::io::AsyncReadExt;
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct S3Uri {
pub bucket: String,
pub key: String,
pub version: Option<String>,
}
impl S3Uri {
pub async fn get_contents(&self) -> Result<String, String> {
get_object_contents(self).await
}
pub async fn put_contents(&self, contents: impl Into<ByteStream>) -> Result<(), String> {
put_object_contents(self, contents).await
}
}
pub async fn get_object_bytes(uri: &S3Uri) -> Result<Vec<u8>, String> {
let client = crate::s3_utils::get_client_for_bucket(&uri.bucket).await?;
let result = client.get_object().bucket(&uri.bucket).key(&uri.key);
let result = match &uri.version {
Some(version) => result.version_id(version),
None => result,
};
let result = result.send().await.map_err(|err| {
err.into_service_error()
.meta()
.message()
.unwrap_or("failed to download s3 object")
.to_string()
})?;
let mut contents = Vec::new();
result
.body
.into_async_read()
.read_to_end(&mut contents)
.await
.map_err(|err| err.to_string())?;
Ok(contents)
}
pub async fn get_object_contents(uri: &S3Uri) -> Result<String, String> {
let bytes = get_object_bytes(uri).await?;
String::from_utf8(bytes).map_err(|err| err.to_string())
}
pub async fn put_object_contents(
uri: &S3Uri,
contents: impl Into<ByteStream>,
) -> Result<(), String> {
let client = crate::s3_utils::get_client_for_bucket(&uri.bucket).await?;
client
.put_object()
.bucket(&uri.bucket)
.key(&uri.key)
.body(contents.into())
.send()
.await
.map_err(|err| {
err.into_service_error()
.meta()
.message()
.unwrap_or("failed to upload s3 object")
.to_string()
})?;
Ok(())
}