1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License.  You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, 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.

#![doc(
    html_logo_url = "https://raw.githubusercontent.com/apache/opendal/main/website/static/img/logo.svg"
)]
#![cfg_attr(docsrs, feature(doc_auto_cfg))]

//! Apache OpenDALâ„¢ is an Open Data Access Layer that enables seamless interaction with diverse storage services.
//!
//! OpenDAL's development is guided by its vision of **One Layer, All Storage** and its core principles: **Open Community**, **Solid Foundation**, **Fast Access**, **Object Storage First**, and **Extensible Architecture**. Read the explained vision at [OpenDAL Vision](https://opendal.apache.org/docs/vision).
//!
//! # Quick Start
//!
//! OpenDAL's API entry points are [`Operator`] and [`BlockingOperator`]. All
//! public APIs are accessible through the operator. To utilize OpenDAL, you
//! need to:
//!
//! - [Init a service](#init-a-service)
//! - [Compose layers](#compose-layers)
//! - [Use operator](#use-operator)
//!
//! ## Init a service
//!
//! The first step is to pick a service and init it with a builder. All supported
//! services could be found at [`services`].
//!
//! Let's take [`services::S3`] as an example:
//!
//! ```no_run
//! use opendal::services;
//! use opendal::Operator;
//! use opendal::Result;
//!
//! fn main() -> Result<()> {
//!     // Pick a builder and configure it.
//!     let mut builder = services::S3::default().bucket("test");
//!
//!     // Init an operator
//!     let op = Operator::new(builder)?.finish();
//!     Ok(())
//! }
//! ```
//!
//! ## Compose layers
//!
//! The next setup is to compose layers. Layers are modules that provide extra
//! features for every operation. All builtin layers could be found at [`layers`].
//!
//! Let's use [`layers::LoggingLayer`] as an example; this layer adds logging to
//! every operation that OpenDAL performs.
//!
//! ```no_run
//! use opendal::layers::LoggingLayer;
//! use opendal::services;
//! use opendal::Operator;
//! use opendal::Result;
//!
//! #[tokio::main]
//! async fn main() -> Result<()> {
//!     // Pick a builder and configure it.
//!     let mut builder = services::S3::default().bucket("test");
//!
//!     // Init an operator
//!     let op = Operator::new(builder)?
//!         // Init with logging layer enabled.
//!         .layer(LoggingLayer::default())
//!         .finish();
//!
//!     Ok(())
//! }
//! ```
//!
//! ## Use operator
//!
//! The final step is to use the operator. OpenDAL supports both async [`Operator`]
//! and blocking [`BlockingOperator`]. Please pick the one that fits your use case.
//!
//! Every Operator API follows the same pattern, take `read` as an example:
//!
//! - `read`: Execute a read operation.
//! - `read_with`: Execute a read operation with additional options, like `range` and `if_match`.
//! - `reader`: Create a reader for streaming data, enabling flexible access.
//! - `reader_with`: Create a reader with advanced options.
//!
//! ```no_run
//! use opendal::layers::LoggingLayer;
//! use opendal::services;
//! use opendal::Operator;
//! use opendal::Result;
//!
//! #[tokio::main]
//! async fn main() -> Result<()> {
//!     // Pick a builder and configure it.
//!     let mut builder = services::S3::default().bucket("test");
//!
//!     // Init an operator
//!     let op = Operator::new(builder)?
//!         // Init with logging layer enabled.
//!         .layer(LoggingLayer::default())
//!         .finish();
//!
//!     // Fetch this file's metadata
//!     let meta = op.stat("hello.txt").await?;
//!     let length = meta.content_length();
//!
//!     // Read data from `hello.txt` with range `0..1024`.
//!     let bs = op.read_with("hello.txt").range(0..1024).await?;
//!
//!     Ok(())
//! }
//! ```

// Make sure all our public APIs have docs.
#![warn(missing_docs)]

// Private module with public types, they will be accessed via `opendal::Xxxx`
mod types;
pub use types::*;

// Public modules, they will be accessed like `opendal::layers::Xxxx`
#[cfg(docsrs)]
pub mod docs;
pub mod layers;
pub mod raw;
pub mod services;

#[cfg(test)]
mod tests {
    use std::mem::size_of;

    use super::*;
    /// This is not a real test case.
    ///
    /// We assert our public structs here to make sure we don't introduce
    /// unexpected struct/enum size change.
    #[test]
    fn assert_size() {
        assert_eq!(32, size_of::<Operator>());
        assert_eq!(320, size_of::<Entry>());
        assert_eq!(296, size_of::<Metadata>());
        assert_eq!(1, size_of::<EntryMode>());
        assert_eq!(24, size_of::<Scheme>());
    }

    trait AssertSendSync: Send + Sync {}
    impl AssertSendSync for Entry {}
    impl AssertSendSync for Capability {}
    impl AssertSendSync for Error {}
    impl AssertSendSync for Reader {}
    impl AssertSendSync for Writer {}
    impl AssertSendSync for Lister {}
    impl AssertSendSync for Operator {}
    impl AssertSendSync for BlockingReader {}
    impl AssertSendSync for BlockingWriter {}
    impl AssertSendSync for BlockingLister {}
    impl AssertSendSync for BlockingOperator {}

    /// This is used to make sure our public API implement Send + Sync
    #[test]
    fn test_trait() {
        let _: Box<dyn AssertSendSync> = Box::new(Capability::default());
    }
}