Skip to main content

opendal_core/docs/
concepts.rs

1// Licensed to the Apache Software Foundation (ASF) under one
2// or more contributor license agreements.  See the NOTICE file
3// distributed with this work for additional information
4// regarding copyright ownership.  The ASF licenses this file
5// to you under the Apache License, Version 2.0 (the
6// "License"); you may not use this file except in compliance
7// with the License.  You may obtain a copy of the License at
8//
9//   http://www.apache.org/licenses/LICENSE-2.0
10//
11// Unless required by applicable law or agreed to in writing,
12// software distributed under the License is distributed on an
13// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14// KIND, either express or implied.  See the License for the
15// specific language governing permissions and limitations
16// under the License.
17
18//! The core concepts of OpenDAL's Rust API.
19//!
20//! OpenDAL gives applications one storage API across services. Rust
21//! applications use four concepts: a service describes the storage backend, a
22//! builder configures it, an operator exposes operations, and layers add
23//! behavior around those operations.
24//!
25//! For the language-independent model shared by every OpenDAL binding, see the
26//! [OpenDAL concepts guide](https://opendal.apache.org/docs/concepts/).
27//!
28//! # Service and builder
29//!
30//! A **service** is a storage backend such as S3, Google Cloud Storage, a
31//! local filesystem, or an in-memory store. Each service supports a different
32//! set of operations and optional features.
33//!
34//! A [`Builder`] collects one service's configuration and constructs its
35//! implementation. The [`services`][crate::services] module exposes concrete
36//! builders, while [`Operator::new`] turns a builder into a ready-to-use
37//! operator.
38//!
39//! ```text
40//! configuration -> builder -> service -> operator
41//! ```
42//!
43//! ```no_run
44//! # use opendal_core::Result;
45//! use opendal_core::Operator;
46//! use opendal_core::services::Memory;
47//!
48//! # fn test() -> Result<()> {
49//! let builder = Memory::default();
50//! let op = Operator::new(builder)?;
51//! # let _ = op;
52//! # Ok(())
53//! # }
54//! ```
55//!
56//! OpenDAL does not make every service support every operation. Applications
57//! can inspect the operator's effective [`Capability`] before using an
58//! optional operation or option.
59//!
60//! # Operator
61//!
62//! An [`Operator`] is the public handle for one configured service and root.
63//! It normalizes paths, validates options against effective capabilities, runs
64//! the configured layers, and dispatches each operation to the service.
65//!
66//! Operators are cheap to clone, contain no caller-visible lifetime or service
67//! type parameter, and can be shared across threads. A clone refers to the
68//! same composed service stack. Methods that add a layer or replace runtime
69//! resources return a new operator; existing clones and in-flight operations
70//! keep their current stack.
71//!
72//! # Operation
73//!
74//! Operations are storage actions such as `read`, `write`, `stat`, `list`,
75//! `delete`, `copy`, and `rename`. Convenience methods use default options,
76//! while the corresponding `_with` methods expose operation-specific options.
77//!
78//! ```no_run
79//! # use opendal_core::Result;
80//! use opendal_core::Operator;
81//! use opendal_core::services::Memory;
82//!
83//! # async fn test() -> Result<()> {
84//! let op = Operator::new(Memory::default())?;
85//! let bs = op.read("abc").await?;
86//! # let _ = bs;
87//! # Ok(())
88//! # }
89//! ```
90//!
91//! OpenDAL normalizes every path relative to the operator's root. `/`
92//! represents the root, a trailing `/` represents a directory, and any other
93//! normalized path represents a file. Operation documentation defines the
94//! observable behavior and errors. [Specifications][super::specs] define
95//! portable contracts that span multiple operations and services.
96//!
97//! # Layer and operation context
98//!
99//! A [`Layer`][crate::raw::Layer] adds cross-cutting behavior such as retry,
100//! timeout, tracing, or metrics. Layers form an ordered stack around a
101//! service.
102//!
103//! An [`OperationContext`] carries runtime resources such as the HTTP
104//! transport and executor from the operator to the service.
105//! Operation-specific values such as ranges, versions, conditions, and
106//! concurrency remain in that operation's options.
107//!
108//! Adding a layer with [`Operator::layer`] or replacing the base context with
109//! [`Operator::with_context`] rebuilds both the service stack and the composed
110//! context from the same ordered layer list:
111//!
112//! ```text
113//! base service -----+                    +-> composed service --+
114//!                   +-> ordered layers --+                      +-> operation
115//! base context -----+                    +-> composed context --+
116//! ```
117//!
118//! ```no_run
119//! # use opendal_core::Result;
120//! use opendal_core::HttpTransporter;
121//! use opendal_core::OperationContext;
122//! use opendal_core::Operator;
123//! use opendal_core::services::Memory;
124//!
125//! # fn test() -> Result<()> {
126//! let transport = HttpTransporter::default();
127//! let op = Operator::new(Memory::default())?.with_context(
128//!     OperationContext::new().with_http_transport(transport),
129//! );
130//! # let _ = op;
131//! # Ok(())
132//! # }
133//! ```
134//!
135//! Most applications only need the public [`Operator`] API. Service and layer
136//! authors should continue with the [internals][super::internals] guide.
137//!
138//! [`Builder`]: crate::Builder
139//! [`Operator`]: crate::Operator
140//! [`Operator::new`]: crate::Operator::new
141//! [`Operator::layer`]: crate::Operator::layer
142//! [`Operator::with_context`]: crate::Operator::with_context
143//! [`Capability`]: crate::Capability
144//! [`OperationContext`]: crate::OperationContext