252252//!
253253//! # Put Object
254254//!
255- //! Use the [`ObjectStore ::put`] method to atomically write data.
255+ //! Use the [`ObjectStoreExt ::put`] method to atomically write data.
256256//!
257257//! ```ignore-wasm32
258258//! # use object_store::local::LocalFileSystem;
259- //! # use object_store::{ObjectStore, PutPayload};
259+ //! # use object_store::{ObjectStore, ObjectStoreExt, PutPayload};
260260//! # use std::sync::Arc;
261261//! # use object_store::path::Path;
262262//! # fn get_object_store() -> Arc<dyn ObjectStore> {
364364//!
365365//! ```ignore-wasm32
366366//! # use object_store::local::LocalFileSystem;
367- //! # use object_store::{ObjectStore, PutPayloadMut};
367+ //! # use object_store::{ObjectStore, ObjectStoreExt, PutPayloadMut};
368368//! # use std::sync::Arc;
369369//! # use bytes::Bytes;
370370//! # use tokio::io::AsyncWriteExt;
@@ -613,19 +613,24 @@ pub type DynObjectStore = dyn ObjectStore;
613613pub type MultipartId = String ;
614614
615615/// Universal API to multiple object store services.
616+ ///
617+ /// For more convience methods, check [`ObjectStoreExt`].
618+ ///
619+ /// # Contract
620+ /// This trait is meant as a contract between object store implementations
621+ /// (e.g. providers, wrappers) and the `object_store` crate itself and is
622+ /// intended to be the minimum API required for an object store.
623+ ///
624+ /// The [`ObjectStoreExt`] acts as an API/contract between `object_store`
625+ /// and the store users and provides additional methods that may be simpler to use but overlap
626+ /// in functionality with `ObjectStore`
616627#[ async_trait]
617628pub trait ObjectStore : std:: fmt:: Display + Send + Sync + Debug + ' static {
618- /// Save the provided bytes to the specified location
629+ /// Save the provided `payload` to `location` with the given options
619630 ///
620631 /// The operation is guaranteed to be atomic, it will either successfully
621632 /// write the entirety of `payload` to `location`, or fail. No clients
622633 /// should be able to observe a partially written object
623- async fn put ( & self , location : & Path , payload : PutPayload ) -> Result < PutResult > {
624- self . put_opts ( location, payload, PutOptions :: default ( ) )
625- . await
626- }
627-
628- /// Save the provided `payload` to `location` with the given options
629634 async fn put_opts (
630635 & self ,
631636 location : & Path ,
@@ -635,7 +640,7 @@ pub trait ObjectStore: std::fmt::Display + Send + Sync + Debug + 'static {
635640
636641 /// Perform a multipart upload
637642 ///
638- /// Client should prefer [`ObjectStore ::put`] for small payloads, as streaming uploads
643+ /// Client should prefer [`ObjectStoreExt ::put`] for small payloads, as streaming uploads
639644 /// typically require multiple separate requests. See [`MultipartUpload`] for more information
640645 ///
641646 /// For more advanced multipart uploads see [`MultipartStore`](multipart::MultipartStore)
@@ -646,7 +651,7 @@ pub trait ObjectStore: std::fmt::Display + Send + Sync + Debug + 'static {
646651
647652 /// Perform a multipart upload with options
648653 ///
649- /// Client should prefer [`ObjectStore::put `] for small payloads, as streaming uploads
654+ /// Client should prefer [`ObjectStore::put_opts `] for small payloads, as streaming uploads
650655 /// typically require multiple separate requests. See [`MultipartUpload`] for more information
651656 ///
652657 /// For more advanced multipart uploads see [`MultipartStore`](multipart::MultipartStore)
@@ -892,7 +897,7 @@ pub trait ObjectStore: std::fmt::Display + Send + Sync + Debug + 'static {
892897 /// # async fn example() -> Result<(), Box<dyn std::error::Error>> {
893898 /// # let root = tempfile::TempDir::new().unwrap();
894899 /// # let store = LocalFileSystem::new_with_prefix(root.path()).unwrap();
895- /// # use object_store::{ObjectStore, ObjectMeta};
900+ /// # use object_store::{ObjectStore, ObjectStoreExt, ObjectMeta};
896901 /// # use object_store::path::Path;
897902 /// # use futures::{StreamExt, TryStreamExt};
898903 /// #
@@ -1103,10 +1108,6 @@ macro_rules! as_ref_impl {
11031108 ( $type: ty) => {
11041109 #[ async_trait]
11051110 impl ObjectStore for $type {
1106- async fn put( & self , location: & Path , payload: PutPayload ) -> Result <PutResult > {
1107- self . as_ref( ) . put( location, payload) . await
1108- }
1109-
11101111 async fn put_opts(
11111112 & self ,
11121113 location: & Path ,
@@ -1201,6 +1202,31 @@ macro_rules! as_ref_impl {
12011202as_ref_impl ! ( Arc <dyn ObjectStore >) ;
12021203as_ref_impl ! ( Box <dyn ObjectStore >) ;
12031204
1205+ /// Extension trait for [`ObjectStore`] with convinience functions.
1206+ ///
1207+ /// See "contract" section within the [`ObjectStore`] documentation for more reasoning.
1208+ ///
1209+ /// # Implementation
1210+ /// You MUST NOT implement this trait yourself. It is automatically implemented for all [`ObjectStore`] implementations.
1211+ pub trait ObjectStoreExt : ObjectStore {
1212+ /// Save the provided bytes to the specified location
1213+ ///
1214+ /// The operation is guaranteed to be atomic, it will either successfully
1215+ /// write the entirety of `payload` to `location`, or fail. No clients
1216+ /// should be able to observe a partially written object
1217+ fn put ( & self , location : & Path , payload : PutPayload ) -> impl Future < Output = Result < PutResult > > ;
1218+ }
1219+
1220+ impl < T > ObjectStoreExt for T
1221+ where
1222+ T : ObjectStore + ?Sized ,
1223+ {
1224+ async fn put ( & self , location : & Path , payload : PutPayload ) -> Result < PutResult > {
1225+ self . put_opts ( location, payload, PutOptions :: default ( ) )
1226+ . await
1227+ }
1228+ }
1229+
12041230/// Result of a list call that includes objects, prefixes (directories) and a
12051231/// token for the next set of results. Individual result sets may be limited to
12061232/// 1,000 objects based on the underlying object storage's limitations.
0 commit comments