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
// 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.
//! Implementing a service.
//!
//! Every OpenDAL backend implements the raw [`Service`] trait. A service owns
//! protocol-specific request construction and response handling. The operator
//! owns path normalization, option validation, layer composition, and
//! dispatch.
//!
//! Service crates live under `core/services/<name>/`. Their public builder and
//! configuration types construct a typed backend; the backend then implements
//! [`Service`].
//!
//! # Service identity and capabilities
//!
//! [`Service::info`] returns immutable identity such as the scheme, root, and
//! namespace name. Runtime resources do not belong in [`ServiceInfo`];
//! services read them from [`OperationContext`].
//!
//! [`Service::capability`] reports the behavior implemented by that service
//! stack. Set an operation or option capability only when the implementation
//! satisfies the corresponding public contract. Operators reject options whose
//! required capability is absent.
//!
//! # Operation body types
//!
//! [`Service`] uses associated types for operation bodies:
//!
//! ```text
//! type Reader: oio::Read;
//! type Writer: oio::Write;
//! type Lister: oio::List;
//! type Deleter: oio::Delete;
//! type Copier: oio::Copy;
//! ```
//!
//! A backend returns concrete body types so its implementation and typed
//! wrappers do not pay for dynamic dispatch. Use `()` for an unsupported body
//! type and return [`ErrorKind::Unsupported`] from the corresponding operation
//! entry point.
//!
//! OpenDAL erases these types once, at [`ServiceDyn`]. [`Servicer`] is
//! `Arc<dyn ServiceDyn>` and is the handle used by operators and runtime layer
//! composition. A wrapper that receives a [`Servicer`] may forward erased
//! `oio::*` bodies, but a backend should keep its own bodies concrete.
//!
//! # Operation methods
//!
//! Each operation method receives normalized paths, an [`OperationContext`],
//! and operation-specific arguments. The context supplies layer-composed
//! runtime resources such as the HTTP transport and executor. Options such as
//! ranges, versions, conditions, and concurrency remain in the operation
//! arguments.
//!
//! An implementation must:
//!
//! - Map every advertised option to the native request without silently
//! dropping it.
//! - Preserve the operation's public success, error, and atomicity contract.
//! - Return structured OpenDAL errors with the correct [`ErrorKind`] and
//! useful context.
//! - Keep credentials and other secrets out of `Debug` output and errors.
//! - Forward cancellation and cleanup to protocol-specific readers, writers,
//! deleters, and copiers.
//!
//! # Adding or changing a service
//!
//! Keep configuration, request construction, operation bodies, and error
//! parsing at their existing service boundaries. Update the facade feature and
//! service registration when the service must be available through the
//! `opendal` crate.
//!
//! Before advertising new behavior, reproduce it against the actual service
//! and run the matching capability-gated behavior tests. Protocol
//! documentation, emulators, and fabricated responses can explain an
//! implementation, but they do not establish real-service conformance.
//!
//! [`Service`]: crate::raw::Service
//! [`Service::info`]: crate::raw::Service::info
//! [`Service::capability`]: crate::raw::Service::capability
//! [`ServiceInfo`]: crate::raw::ServiceInfo
//! [`ServiceDyn`]: crate::raw::ServiceDyn
//! [`Servicer`]: crate::raw::Servicer
//! [`OperationContext`]: crate::OperationContext
//! [`ErrorKind`]: crate::ErrorKind
//! [`ErrorKind::Unsupported`]: crate::ErrorKind::Unsupported