Skip to content

Commit

Permalink
docs: Cover all public types and functions (#128)
Browse files Browse the repository at this point in the history
Signed-off-by: Xuanwo <[email protected]>
  • Loading branch information
Xuanwo authored Mar 9, 2022
1 parent 3210016 commit 3721320
Show file tree
Hide file tree
Showing 14 changed files with 248 additions and 12 deletions.
6 changes: 6 additions & 0 deletions src/accessor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,12 @@ use crate::ops::OpStat;
use crate::ops::OpWrite;
use crate::BoxedAsyncReader;

/// Underlying trait of all backends for implementors.
///
/// # Note
///
/// Only service implementor should care about this trait, users need to
/// use [`Operator`][crate::Operator] instead.
#[async_trait]
pub trait Accessor: Send + Sync + Debug {
/// Read data from the underlying storage into input writer.
Expand Down
2 changes: 2 additions & 0 deletions src/credential.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
// See the License for the specific language governing permissions and
// limitations under the License.

//! Different credential types that used to signing requests.
use std::fmt::Debug;
use std::fmt::Display;
use std::fmt::Formatter;
Expand Down
26 changes: 26 additions & 0 deletions src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,32 @@
// See the License for the specific language governing permissions and
// limitations under the License.

//! Errors that returned by OpenDAL
//!
//! # Examples
//!
//! ```
//! use anyhow::Result;
//! use opendal::ObjectMode;
//! use opendal::Operator;
//! use opendal::error::Kind;
//! use opendal::services::fs;
//!
//! #[tokio::main]
//! async fn main() -> Result<()> {
//! let op = Operator::new(fs::Backend::build().root("/tmp").finish().await?);
//!
//! // Get metadata of an object.
//! let meta = op.object("test_file").metadata().await;
//! if let Err(e) = op.object("test_file").metadata().await {
//! if e.kind() == Kind::ObjectNotExist {
//! println!("object not exist")
//! }
//! }
//! Ok(())
//! }
//! ```
use std::collections::HashMap;
use std::io;

Expand Down
53 changes: 53 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,59 @@
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! OpenDAL is the Open Data Access Layer that connect the whole world together.
//!
//! # Example
//!
//! ```
//! use anyhow::Result;
//! use futures::AsyncReadExt;
//! use futures::StreamExt;
//! use opendal::services::fs;
//! use opendal::ObjectMode;
//! use opendal::Operator;
//!
//! #[tokio::main]
//! async fn main() -> Result<()> {
//! let op = Operator::new(fs::Backend::build().root("/tmp").finish().await?);
//!
//! let o = op.object("test_file");
//!
//! // Write data info file;
//! let w = o.writer();
//! let n = w
//! .write_bytes("Hello, World!".to_string().into_bytes())
//! .await?;
//!
//! // Read data from file;
//! let mut r = o.reader();
//! let mut buf = vec![];
//! let n = r.read_to_end(&mut buf).await?;
//!
//! // Read range from file;
//! let mut r = o.range_reader(10, 1);
//! let mut buf = vec![];
//! let n = r.read_to_end(&mut buf).await?;
//!
//! // Get file's Metadata
//! let meta = o.metadata().await?;
//!
//! // List current dir.
//! let mut obs = op.objects("").map(|o| o.expect("list object"));
//! while let Some(o) = obs.next().await {
//! let meta = o.metadata().await?;
//! let path = meta.path();
//! let mode = meta.mode();
//! let length = meta.content_length();
//! }
//!
//! // Delete file.
//! o.delete().await?;
//!
//! Ok(())
//! }
//! ```
mod accessor;
pub use accessor::Accessor;

Expand Down
4 changes: 2 additions & 2 deletions src/object.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ use crate::Accessor;
use crate::Reader;
use crate::Writer;

/// `Object` is a handler for all object related operations.
/// Handler for all object related operations.
#[derive(Clone, Debug)]
pub struct Object {
acc: Arc<dyn Accessor>,
Expand Down Expand Up @@ -215,7 +215,7 @@ impl Display for ObjectMode {

pub type BoxedObjectStream = Box<dyn futures::Stream<Item = Result<Object>> + Unpin + Send>;

/// `ObjectStream` is a handler for listing object under a dir.
/// Handler for listing object under a dir.
pub struct ObjectStream {
acc: Arc<dyn Accessor>,
path: String,
Expand Down
137 changes: 136 additions & 1 deletion src/operator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,30 +19,165 @@ use crate::Layer;
use crate::Object;
use crate::ObjectStream;

/// User-facing APIs for object and object streams.
#[derive(Clone)]
pub struct Operator {
accessor: Arc<dyn Accessor>,
}

impl Operator {
/// Create a new operator.
///
/// # Example
///
/// Read more backend init examples in [examples](https://github.com/datafuselabs/opendal/tree/main/examples).
///
/// ```
/// use std::sync::Arc;
///
/// /// Example for initiating a fs backend.
/// use anyhow::Result;
/// use opendal::services::fs;
/// use opendal::services::fs::Builder;
/// use opendal::Accessor;
/// use opendal::Object;
/// use opendal::Operator;
///
/// #[tokio::main]
/// async fn main() -> Result<()> {
/// // Create fs backend builder.
/// let mut builder: Builder = fs::Backend::build();
/// // Set the root for fs, all operations will happen under this root.
/// //
/// // NOTE: the root must be absolute path.
/// builder.root("/tmp");
/// // Build the `Accessor`.
/// let accessor: Arc<dyn Accessor> = builder.finish().await?;
///
/// // `Accessor` provides the low level APIs, we will use `Operator` normally.
/// let op: Operator = Operator::new(accessor);
///
/// // Create an object handle to start operation on object.
/// let _: Object = op.object("test_file");
///
/// Ok(())
/// }
/// ```
pub fn new(accessor: Arc<dyn Accessor>) -> Self {
Self { accessor }
}

/// Create a new layer.
#[must_use]
pub fn layer(self, layer: impl Layer) -> Self {
Operator {
accessor: layer.layer(self.accessor.clone()),
}
}

pub fn inner(&self) -> Arc<dyn Accessor> {
fn inner(&self) -> Arc<dyn Accessor> {
self.accessor.clone()
}

/// Create a new object handle to take operations.
///
/// # Example
///
/// ```
/// use anyhow::Result;
/// use futures::AsyncReadExt;
/// use opendal::services::fs;
/// use opendal::ObjectMode;
/// use opendal::Operator;
///
/// #[tokio::main]
/// async fn main() -> Result<()> {
/// let op = Operator::new(fs::Backend::build().root("/tmp").finish().await?);
///
/// let o = op.object("test_file");
///
/// // Write data info file;
/// let w = o.writer();
/// let n = w
/// .write_bytes("Hello, World!".to_string().into_bytes())
/// .await?;
/// assert_eq!(n, 13);
///
/// // Read data from file;
/// let mut r = o.reader();
/// let mut buf = vec![];
/// let n = r.read_to_end(&mut buf).await?;
/// assert_eq!(n, 13);
/// assert_eq!(String::from_utf8_lossy(&buf), "Hello, World!");
///
/// // Read range from file;
/// let mut r = o.range_reader(10, 1);
/// let mut buf = vec![];
/// let n = r.read_to_end(&mut buf).await?;
/// assert_eq!(n, 1);
/// assert_eq!(String::from_utf8_lossy(&buf), "l");
///
/// // Get file's Metadata
/// let meta = o.metadata().await?;
/// assert_eq!(meta.content_length(), 13);
///
/// // Delete file.
/// o.delete().await?;
///
/// Ok(())
/// }
/// ```
pub fn object(&self, path: &str) -> Object {
Object::new(self.inner(), path)
}

/// Create a new object stream handle to list objects.
///
/// # Example
///
/// ```
/// use anyhow::Result;
/// use futures::StreamExt;
/// use opendal::ObjectMode;
/// use opendal::ObjectStream;
/// use opendal::Operator;
/// use opendal_test::services::fs;
///
/// #[tokio::main]
/// async fn main() -> Result<()> {
/// // Using opendal internal test framework for example.
/// // Don't use this in production.
/// // Please init your backend via related example instead.
/// let acc = fs::new().await?;
/// if acc.is_none() {
/// return Ok(());
/// }
/// let op = Operator::new(acc.unwrap());
///
/// // Real example starts from here.
///
/// // Start listing a dir.
/// let mut obs: ObjectStream = op.objects("test_dir");
/// // ObjectStream implements `futures::Stream`
/// while let Some(o) = obs.next().await {
/// let mut o = o?;
/// // It's highly possible that OpenDAL already did metadata during list.
/// // Use `Object::metadata_cached()` to get cached metadata at first.
/// let meta = o.metadata_cached().await?;
/// match meta.mode() {
/// ObjectMode::FILE => {
/// println!("Handling file")
/// }
/// ObjectMode::DIR => {
/// println!("Handling dir like start a new list via meta.path()")
/// }
/// ObjectMode::Unknown => continue,
/// }
/// }
///
/// Ok(())
/// }
/// ```
pub fn objects(&self, path: &str) -> ObjectStream {
ObjectStream::new(self.inner(), path)
}
Expand Down
2 changes: 2 additions & 0 deletions src/ops.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
// See the License for the specific language governing permissions and
// limitations under the License.

//! Operations used by [`Accessor`][crate::Accessor]
#[derive(Debug, Clone, Default)]
pub struct OpRead {
pub path: String,
Expand Down
1 change: 1 addition & 0 deletions src/readers/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.

//! Reader related helper tools
mod callback;
pub use callback::CallbackReader;

Expand Down
1 change: 1 addition & 0 deletions src/scheme.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ use anyhow::anyhow;
use super::error::Error;
use crate::error::Kind;

/// Backends that OpenDAL supports
#[derive(Clone, Debug, PartialEq)]
pub enum Scheme {
// TODO: Although we don't have azblob support for now, but we need to add it for compatibility. We will implement azblob support as soon as possible.
Expand Down
2 changes: 2 additions & 0 deletions src/services/fs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
// See the License for the specific language governing permissions and
// limitations under the License.

//! Posix file system support.
use std::collections::HashMap;
use std::fs;
use std::io::SeekFrom;
Expand Down
2 changes: 2 additions & 0 deletions src/services/memory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
// See the License for the specific language governing permissions and
// limitations under the License.

//! In memory backend support.
use std::collections::HashMap;
use std::pin::Pin;
use std::sync::Arc;
Expand Down
13 changes: 7 additions & 6 deletions src/services/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,13 @@
// See the License for the specific language governing permissions and
// limitations under the License.

/// Every mod represents a service.
///
/// In order to implement a service, we need the following things:
///
/// - Builder: responsible for building the service backend.
/// - Backend: the service backend which implements the `Accessor` trait.
//! Providing specific services support.
//!
//! In order to implement a service, we need the following things:
//!
//! - Builder: responsible for building the service backend.
//! - Backend: the service backend which implements the [`Accessor`][crate::Accessor] trait.
pub mod fs;
pub mod memory;
pub mod s3;
9 changes: 6 additions & 3 deletions src/services/s3/backend.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,20 +68,22 @@ static ENDPOINT_TEMPLATES: Lazy<HashMap<&'static str, &'static str>> = Lazy::new
m
});

/// Builder for s3 services
///
/// # TODO
///
/// enable_path_style and enable_signature_v2 need sdk support.
///
/// ref: https://github.com/awslabs/aws-sdk-rust/issues/390
/// ref: <https://github.com/awslabs/aws-sdk-rust/issues/390>
#[derive(Default, Debug, Clone)]
pub struct Builder {
root: Option<String>,

bucket: String,
credential: Option<Credential>,
/// endpoint must be full uri, e.g.
/// - https://s3.amazonaws.com
/// - http://127.0.0.1:3000
/// - <https://s3.amazonaws.com>
/// - <http://127.0.0.1:3000>
///
/// If user inputs endpoint like "s3.amazonaws.com", we will prepend
/// "https://" before it.
Expand Down Expand Up @@ -313,6 +315,7 @@ impl Builder {
}
}

/// Backend for s3 services.
#[derive(Debug, Clone)]
pub struct Backend {
bucket: String,
Expand Down
Loading

0 comments on commit 3721320

Please sign in to comment.