This is an automated email from the ASF dual-hosted git repository.

tison pushed a commit to branch opt-out-ctor
in repository https://gitbox.apache.org/repos/asf/opendal.git

commit 7472c19b9d4c1ae28b26626dc5eb3cbf75738375
Author: tison <[email protected]>
AuthorDate: Wed Feb 18 21:56:34 2026 +0800

    refactor(core): allow opt-out ctor dependency
    
    Signed-off-by: tison <[email protected]>
---
 core/Cargo.toml                          |  4 ++-
 core/core/src/types/mod.rs               |  1 -
 core/core/src/types/operator/builder.rs  |  2 +-
 core/core/src/types/operator/mod.rs      |  2 +-
 core/core/src/types/operator/registry.rs | 42 +++++++++++++++-----------------
 core/src/lib.rs                          | 13 ++++------
 6 files changed, 29 insertions(+), 35 deletions(-)

diff --git a/core/Cargo.toml b/core/Cargo.toml
index f1a19d950..1cc1e1bd4 100644
--- a/core/Cargo.toml
+++ b/core/Cargo.toml
@@ -117,6 +117,8 @@ layers-tail-cut = ["dep:opendal-layer-tail-cut"]
 layers-throttle = ["dep:opendal-layer-throttle"]
 layers-timeout = ["dep:opendal-layer-timeout"]
 layers-tracing = ["dep:opendal-layer-tracing"]
+# Register services enabled to the OperatorRegistry so that they can be used 
by `Operator::from_uri`.
+register-services = ["dep:ctor"]
 reqwest-rustls-tls = ["opendal-core/reqwest-rustls-tls"]
 services-aliyun-drive = ["dep:opendal-service-aliyun-drive"]
 services-alluxio = ["dep:opendal-service-alluxio"]
@@ -207,7 +209,7 @@ path = "tests/behavior/main.rs"
 required-features = ["tests"]
 
 [dependencies]
-ctor = { workspace = true }
+ctor = { workspace = true , optional = true }
 opendal-core = { path = "core", version = "0.55.0", default-features = false }
 opendal-layer-async-backtrace = { path = "layers/async-backtrace", version = 
"0.55.0", optional = true, default-features = false }
 opendal-layer-await-tree = { path = "layers/await-tree", version = "0.55.0", 
optional = true, default-features = false }
diff --git a/core/core/src/types/mod.rs b/core/core/src/types/mod.rs
index fb168553f..8042804ae 100644
--- a/core/core/src/types/mod.rs
+++ b/core/core/src/types/mod.rs
@@ -43,7 +43,6 @@ mod execute;
 pub use execute::*;
 
 mod operator;
-pub use operator::DEFAULT_OPERATOR_REGISTRY;
 pub use operator::IntoOperatorUri;
 pub use operator::Operator;
 pub use operator::OperatorBuilder;
diff --git a/core/core/src/types/operator/builder.rs 
b/core/core/src/types/operator/builder.rs
index 195006a8b..201f87612 100644
--- a/core/core/src/types/operator/builder.rs
+++ b/core/core/src/types/operator/builder.rs
@@ -142,7 +142,7 @@ impl Operator {
     /// # }
     /// ```
     pub fn from_uri(uri: impl IntoOperatorUri) -> Result<Operator> {
-        crate::DEFAULT_OPERATOR_REGISTRY.load(uri)
+        OperatorRegistry::get().load(uri)
     }
 
     /// Create a new operator via given scheme and iterator of config value in 
dynamic dispatch.
diff --git a/core/core/src/types/operator/mod.rs 
b/core/core/src/types/operator/mod.rs
index 3de1ea7c1..7dba388e5 100644
--- a/core/core/src/types/operator/mod.rs
+++ b/core/core/src/types/operator/mod.rs
@@ -30,7 +30,7 @@ pub use info::OperatorInfo;
 pub mod operator_futures;
 
 mod registry;
-pub use registry::{DEFAULT_OPERATOR_REGISTRY, OperatorFactory, 
OperatorRegistry};
+pub use registry::{OperatorFactory, OperatorRegistry};
 
 mod uri;
 pub use uri::{IntoOperatorUri, OperatorUri};
diff --git a/core/core/src/types/operator/registry.rs 
b/core/core/src/types/operator/registry.rs
index dc10beb5e..d95a681ec 100644
--- a/core/core/src/types/operator/registry.rs
+++ b/core/core/src/types/operator/registry.rs
@@ -15,42 +15,38 @@
 // specific language governing permissions and limitations
 // under the License.
 
-use std::collections::HashMap;
-use std::sync::{LazyLock, Mutex};
-
 use crate::types::builder::{Builder, Configurator};
 use crate::types::{IntoOperatorUri, OperatorUri};
 use crate::{Error, ErrorKind, Operator, Result};
+use std::collections::HashMap;
+use std::sync::{LazyLock, Mutex};
 
 /// Factory signature used to construct [`Operator`] from a URI and extra 
options.
 pub type OperatorFactory = fn(&OperatorUri) -> Result<Operator>;
 
-/// Default registry used by [`Operator::from_uri`].
-///
-/// `memory` is always registered here since it's used pervasively in unit 
tests
-/// and as a zero-dependency backend.
-///
-/// Other optional service registrations are handled by the facade crate 
`opendal`.
-pub static DEFAULT_OPERATOR_REGISTRY: LazyLock<OperatorRegistry> = 
LazyLock::new(|| {
-    let registry = OperatorRegistry::new();
-
-    crate::services::register_memory_service(&registry);
-
-    registry
-});
-
 /// Global registry that maps schemes to [`OperatorFactory`] functions.
-#[derive(Debug, Default)]
+#[derive(Debug)]
 pub struct OperatorRegistry {
     factories: Mutex<HashMap<String, OperatorFactory>>,
 }
 
 impl OperatorRegistry {
-    /// Create a new, empty registry.
-    pub fn new() -> Self {
-        Self {
-            factories: Mutex::new(HashMap::new()),
-        }
+    /// Get the global registry.
+    pub fn get() -> &'static Self {
+        /// The global registry used by [`Operator::from_uri`].
+        ///
+        /// `memory` is always registered here since it's used pervasively in 
unit tests
+        /// and as a zero-dependency backend.
+        ///
+        /// Other optional service registrations are handled by the facade 
crate `opendal`.
+        static OPERATOR_REGISTRY: LazyLock<OperatorRegistry> = 
LazyLock::new(|| {
+            let factories = Mutex::new(HashMap::default());
+            let registry = OperatorRegistry { factories };
+            crate::services::register_memory_service(&registry);
+            registry
+        });
+
+        &OPERATOR_REGISTRY
     }
 
     /// Register a builder for the given scheme.
diff --git a/core/src/lib.rs b/core/src/lib.rs
index 5563bd712..6a58d0def 100644
--- a/core/src/lib.rs
+++ b/core/src/lib.rs
@@ -27,9 +27,7 @@ pub use opendal_core::*;
 #[cfg(feature = "tests")]
 pub extern crate opendal_testkit as tests;
 
-static DEFAULT_REGISTRY_INIT: std::sync::Once = std::sync::Once::new();
-
-/// Initialize [`DEFAULT_OPERATOR_REGISTRY`] with enabled services.
+/// Initialize the global [`OperatorRegistry`] with enabled services.
 ///
 /// This function is safe to call multiple times and will only perform
 /// initialization once.
@@ -41,13 +39,11 @@ static DEFAULT_REGISTRY_INIT: std::sync::Once = 
std::sync::Once::new();
 /// should call this function explicitly before using `Operator::from_uri` or
 /// `Operator::via_iter`.
 pub fn init_default_registry() {
-    DEFAULT_REGISTRY_INIT.call_once(|| {
-        let registry = &opendal_core::DEFAULT_OPERATOR_REGISTRY;
-        init_default_registry_inner(registry);
-    });
+    static DEFAULT_REGISTRY_INIT: std::sync::Once = std::sync::Once::new();
+    DEFAULT_REGISTRY_INIT.call_once(|| 
init_default_registry_inner(OperatorRegistry::get()));
 }
 
-fn init_default_registry_inner(registry: &opendal_core::OperatorRegistry) {
+fn init_default_registry_inner(registry: &OperatorRegistry) {
     opendal_core::services::register_memory_service(registry);
 
     #[cfg(feature = "services-aliyun-drive")]
@@ -234,6 +230,7 @@ fn init_default_registry_inner(registry: 
&opendal_core::OperatorRegistry) {
     opendal_service_redis::register_redis_service(registry);
 }
 
+#[cfg(feature = "register-services")]
 #[ctor::ctor]
 fn register_default_operator_registry() {
     init_default_registry();

Reply via email to