Xuanwo commented on code in PR #1861:
URL: 
https://github.com/apache/incubator-opendal/pull/1861#discussion_r1159934423


##########
bindings/c/include/opendal.h:
##########
@@ -25,14 +25,229 @@
 #include <stddef.h>
 #include <stdbool.h>
 
+/*
+ The C-compatible error type enum used in c bindings.
+ NOTICE: the type definition of [`ErrorNo`] should be aligned with
+         [`od::ErrorKind`]
+ */
+typedef enum opendal_errno {

Review Comment:
   Adding a new concept seems not a good idea, how about keeping 
`opendal_error_kind`?



##########
bindings/c/src/error.rs:
##########
@@ -0,0 +1,203 @@
+// 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.
+
+use std::ffi::CString;
+use std::os::raw::{c_char, c_void};
+
+use ::opendal as od;
+
+/// The wrapper type for opendal's error, wrapped because of the
+/// orphan rule
+pub(crate) struct OpendalError(pub(crate) od::Error);
+
+/// The C-compatible error type enum used in c bindings.
+/// NOTICE: the type definition of [`ErrorNo`] should be aligned with
+///         [`od::ErrorKind`]
+#[repr(C)]
+pub enum opendal_errno {
+    /// returning it back. For example, s3 returns an internal service error.
+    Unexpected,
+    /// Underlying service doesn't support this operation.
+    Unsupported,
+    /// The config for backend is invalid.
+    ConfigInvalid,
+    /// The given path is not found.
+    NotFound,
+    /// The given path doesn't have enough permission for this operation
+    PermissionDenied,
+    /// The given path is a directory.
+    IsADirectory,
+    /// The given path is not a directory.
+    NotADirectory,
+    /// The given path already exists thus we failed to the specified 
operation on it.
+    AlreadyExists,
+    /// Requests that sent to this path is over the limit, please slow down.
+    RateLimited,
+    /// The given file paths are same.
+    IsSameFile,
+    /// Unknown error, since [`opendal::ErrorKind`] is nonexhaustive
+    UnknownError,
+    /// NullPtr error, meaning that a provided pointer which need to be 
dereferenced is null
+    NullPtr,

Review Comment:
   If we have `opendal_code`, we can isolate binding-related errors to it. 
However, do we truly require a `NullPtr` error? Under what circumstances would 
users check for this error?



##########
bindings/c/include/opendal.h:
##########
@@ -25,14 +25,229 @@
 #include <stddef.h>
 #include <stdbool.h>
 
+/*
+ The C-compatible error type enum used in c bindings.
+ NOTICE: the type definition of [`ErrorNo`] should be aligned with
+         [`od::ErrorKind`]
+ */
+typedef enum opendal_errno {
+  /*
+   returning it back. For example, s3 returns an internal service error.
+   */
+  Unexpected,
+  /*
+   Underlying service doesn't support this operation.
+   */
+  Unsupported,
+  /*
+   The config for backend is invalid.
+   */
+  ConfigInvalid,
+  /*
+   The given path is not found.
+   */
+  NotFound,
+  /*
+   The given path doesn't have enough permission for this operation
+   */
+  PermissionDenied,
+  /*
+   The given path is a directory.
+   */
+  IsADirectory,
+  /*
+   The given path is not a directory.
+   */
+  NotADirectory,
+  /*
+   The given path already exists thus we failed to the specified operation on 
it.
+   */
+  AlreadyExists,
+  /*
+   Requests that sent to this path is over the limit, please slow down.
+   */
+  RateLimited,
+  /*
+   The given file paths are same.
+   */
+  IsSameFile,
+  /*
+   Unknown error, since [`opendal::ErrorKind`] is nonexhaustive
+   */
+  UnknownError,
+  /*
+   NullPtr error, meaning that a provided pointer which need to be 
dereferenced is null
+   */
+  NullPtr,

Review Comment:
   Why we need this error?



##########
bindings/c/include/opendal.h:
##########
@@ -25,14 +25,229 @@
 #include <stddef.h>
 #include <stdbool.h>
 
+/*
+ The C-compatible error type enum used in c bindings.
+ NOTICE: the type definition of [`ErrorNo`] should be aligned with
+         [`od::ErrorKind`]
+ */
+typedef enum opendal_errno {
+  /*
+   returning it back. For example, s3 returns an internal service error.
+   */
+  Unexpected,
+  /*
+   Underlying service doesn't support this operation.
+   */
+  Unsupported,
+  /*
+   The config for backend is invalid.
+   */
+  ConfigInvalid,
+  /*
+   The given path is not found.
+   */
+  NotFound,
+  /*
+   The given path doesn't have enough permission for this operation
+   */
+  PermissionDenied,
+  /*
+   The given path is a directory.
+   */
+  IsADirectory,
+  /*
+   The given path is not a directory.
+   */
+  NotADirectory,
+  /*
+   The given path already exists thus we failed to the specified operation on 
it.
+   */
+  AlreadyExists,
+  /*
+   Requests that sent to this path is over the limit, please slow down.
+   */
+  RateLimited,
+  /*
+   The given file paths are same.
+   */
+  IsSameFile,
+  /*
+   Unknown error, since [`opendal::ErrorKind`] is nonexhaustive
+   */
+  UnknownError,
+  /*
+   NullPtr error, meaning that a provided pointer which need to be 
dereferenced is null
+   */
+  NullPtr,
+} opendal_errno;
+
+/*
+ The C-compatible error status for opendal::Error.
+ NOTICE: the type definition of [`ErrorNo`] should be aligned with
+         [`od::ErrorStatus`]
+ */
+typedef enum opendal_error_status {
+  /*
+   Permanent means without external changes, the error never changes.
+
+   For example, underlying services returns a not found error.
+
+   Users SHOULD never retry this operation.
+   */
+  Permanent,
+  /*
+   Temporary means this error is returned for temporary.
+
+   For example, underlying services is rate limited or unavailable for 
temporary.
+
+   Users CAN retry the operation to resolve it.
+   */
+  Temporary,
+  /*
+   Persistent means this error used to be temporary but still failed after 
retry.
+
+   For example, underlying services kept returning network errors.
+
+   Users MAY retry this operation but it's highly possible to error again.
+   */
+  Persistent,
+} opendal_error_status;
+
+/*
+ The [`OperatorPtr`] owns a pointer to a [`od::BlockingOperator`].
+ It is also the key struct that OpenDAL's APIs access the real
+ operator's memory. The use of OperatorPtr is zero cost, it
+ only returns a reference of the underlying Operator.
+
+ The [`OperatorPtr`] also has a transparent layout, allowing you
+ to check its validity by native boolean operator.
+ e.g. you could check by (!ptr) on a opendal_operator_ptr type
+ */
+typedef const void *opendal_operator_ptr;
+
+/*
+ The error type returned of all opendal APIs in the C code
+ */
+typedef struct opendal_error {
+  /*
+   The error number of the actual error
+   */
+  enum opendal_errno errno;
+  /*
+   The error status of the error, please see opendal_error_status
+   for more details
+   */
+  enum opendal_error_status error_status;
+  /*
+   The error_msg consumes an area of heap memory, please call
+   [`opendal_free_error`] on the error to free the memory
+   */
+  const char *error_msg;
+} opendal_error;
+
+/*
+ The Rust-like Result type of opendal C binding, it contains
+ a opendal_operator_ptr and a pointer to an error type.
+ Note that if `error` is not null, the error consumes heap memory
+ remember to free it by using [`opendal_free_error`]
+ */
+typedef struct opendal_result_op {
+  opendal_operator_ptr op_ptr;
+  struct opendal_error *error;
+} opendal_result_op;
+
+/*
+ The Rust-like Result type of opendal C binding, it contains
+ whether the write operation succeeds and a pointer to an error type.
+ Note that if `error` is not null, the error consumes heap memory
+ remember to free it by using [`opendal_free_error`]
+ */
+typedef struct opendal_result_write {
+  bool success;
+  struct opendal_error *error;
+} opendal_result_write;
+
+/*
+ The [`Bytes`] type is a C-compatible substitute for [`Bytes`]
+ in Rust, it will not be deallocated automatically like what
+ has been done in Rust. Instead, you have to call [`opendal_free_bytes`]
+ to free the heap memory to avoid memory leak.
+ The field `data` should not be modified since it might causes
+ the reallocation of the Vector.
+ */
+typedef struct opendal_bytes {
+  const uint8_t *data;
+  uintptr_t len;
+} opendal_bytes;
+
+/*
+ The Rust-like Result type of opendal C binding, it contains
+ the data that the read operation returns and a pointer to an error type.
+ If the read operation failed, the `data` fields should be a nullptr.
+ Note that if `error` is not null, the error consumes heap memory
+ remember to free it by using [`opendal_free_error`]
+ */
+typedef struct opendal_result_read {
+  struct opendal_bytes *data;
+  struct opendal_error *error;
+} opendal_result_read;
+
 #ifdef __cplusplus
 extern "C" {
 #endif // __cplusplus
 
 /*
- Hello, OpenDAL!
+ Returns a result type [`opendal_result_op`], with operator_ptr. If the 
construction succeeds
+ the error is nullptr, otherwise it contains the error information.
+
+ # Safety
+
+ It is [safe] under two cases below
+ * The memory pointed to by `scheme` must contain a valid nul terminator at 
the end of
+   the string.
+ * The `scheme` points to NULL, this function simply returns you a null 
opendal_operator_ptr
+ */
+struct opendal_result_op opendal_new_operator(const char *scheme);
+
+/*
+ Write the data into the path blockingly by operator, returns whether the 
write succeeds
+ with error type
+
+ # Safety
+
+ It is [safe] under two cases below
+ * The memory pointed to by `path` must contain a valid nul terminator at the 
end of
+   the string.
+ * The `path` points to NULL, this function simply returns you false
+ */
+struct opendal_result_write 
opendal_operator_blocking_write(opendal_operator_ptr op_ptr,
+                                                            const char *path,
+                                                            struct 
opendal_bytes bytes);
+
+/*
+ Read the data out from path into a [`Bytes`] blockingly by operator, returns
+ a result with error type
+
+ # Safety
+
+ It is [safe] under two cases below
+ * The memory pointed to by `path` must contain a valid nul terminator at the 
end of
+   the string.
+ * The `path` points to NULL, this function simply returns you a nullptr
+ */
+struct opendal_result_read opendal_operator_blocking_read(opendal_operator_ptr 
op_ptr,
+                                                          const char *path);
+
+/*
+ Free the [`CError`] type's heap memory, it is safe to be called
+ on a nullptr
+ */
+void opendal_free_error(struct opendal_error *self);

Review Comment:
   How about we stick with the naming convention of `opendal_<noun>_<verb>`? It 
seems more straightforward and easier to understand.



##########
bindings/c/src/error.rs:
##########
@@ -0,0 +1,203 @@
+// 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.
+
+use std::ffi::CString;
+use std::os::raw::{c_char, c_void};
+
+use ::opendal as od;
+
+/// The wrapper type for opendal's error, wrapped because of the
+/// orphan rule
+pub(crate) struct OpendalError(pub(crate) od::Error);
+
+/// The C-compatible error type enum used in c bindings.
+/// NOTICE: the type definition of [`ErrorNo`] should be aligned with
+///         [`od::ErrorKind`]
+#[repr(C)]
+pub enum opendal_errno {
+    /// returning it back. For example, s3 returns an internal service error.
+    Unexpected,
+    /// Underlying service doesn't support this operation.
+    Unsupported,
+    /// The config for backend is invalid.
+    ConfigInvalid,
+    /// The given path is not found.
+    NotFound,
+    /// The given path doesn't have enough permission for this operation
+    PermissionDenied,
+    /// The given path is a directory.
+    IsADirectory,
+    /// The given path is not a directory.
+    NotADirectory,
+    /// The given path already exists thus we failed to the specified 
operation on it.
+    AlreadyExists,
+    /// Requests that sent to this path is over the limit, please slow down.
+    RateLimited,
+    /// The given file paths are same.
+    IsSameFile,
+    /// Unknown error, since [`opendal::ErrorKind`] is nonexhaustive
+    UnknownError,
+    /// NullPtr error, meaning that a provided pointer which need to be 
dereferenced is null
+    NullPtr,
+}
+
+/// The C-compatible error status for opendal::Error.
+/// NOTICE: the type definition of [`ErrorNo`] should be aligned with
+///         [`od::ErrorStatus`]
+#[repr(C)]
+pub enum opendal_error_status {

Review Comment:
   Please remove this to keep simple.



##########
bindings/c/include/opendal.h:
##########
@@ -25,14 +25,229 @@
 #include <stddef.h>
 #include <stdbool.h>
 
+/*
+ The C-compatible error type enum used in c bindings.
+ NOTICE: the type definition of [`ErrorNo`] should be aligned with
+         [`od::ErrorKind`]
+ */
+typedef enum opendal_errno {
+  /*
+   returning it back. For example, s3 returns an internal service error.
+   */
+  Unexpected,
+  /*
+   Underlying service doesn't support this operation.
+   */
+  Unsupported,
+  /*
+   The config for backend is invalid.
+   */
+  ConfigInvalid,
+  /*
+   The given path is not found.
+   */
+  NotFound,
+  /*
+   The given path doesn't have enough permission for this operation
+   */
+  PermissionDenied,
+  /*
+   The given path is a directory.
+   */
+  IsADirectory,
+  /*
+   The given path is not a directory.
+   */
+  NotADirectory,
+  /*
+   The given path already exists thus we failed to the specified operation on 
it.
+   */
+  AlreadyExists,
+  /*
+   Requests that sent to this path is over the limit, please slow down.
+   */
+  RateLimited,
+  /*
+   The given file paths are same.
+   */
+  IsSameFile,
+  /*
+   Unknown error, since [`opendal::ErrorKind`] is nonexhaustive
+   */
+  UnknownError,
+  /*
+   NullPtr error, meaning that a provided pointer which need to be 
dereferenced is null
+   */
+  NullPtr,
+} opendal_errno;
+
+/*
+ The C-compatible error status for opendal::Error.
+ NOTICE: the type definition of [`ErrorNo`] should be aligned with
+         [`od::ErrorStatus`]
+ */
+typedef enum opendal_error_status {
+  /*
+   Permanent means without external changes, the error never changes.
+
+   For example, underlying services returns a not found error.
+
+   Users SHOULD never retry this operation.
+   */
+  Permanent,
+  /*
+   Temporary means this error is returned for temporary.
+
+   For example, underlying services is rate limited or unavailable for 
temporary.
+
+   Users CAN retry the operation to resolve it.
+   */
+  Temporary,
+  /*
+   Persistent means this error used to be temporary but still failed after 
retry.
+
+   For example, underlying services kept returning network errors.
+
+   Users MAY retry this operation but it's highly possible to error again.
+   */
+  Persistent,
+} opendal_error_status;
+
+/*
+ The [`OperatorPtr`] owns a pointer to a [`od::BlockingOperator`].
+ It is also the key struct that OpenDAL's APIs access the real
+ operator's memory. The use of OperatorPtr is zero cost, it
+ only returns a reference of the underlying Operator.
+
+ The [`OperatorPtr`] also has a transparent layout, allowing you
+ to check its validity by native boolean operator.
+ e.g. you could check by (!ptr) on a opendal_operator_ptr type
+ */
+typedef const void *opendal_operator_ptr;
+
+/*
+ The error type returned of all opendal APIs in the C code
+ */
+typedef struct opendal_error {
+  /*
+   The error number of the actual error
+   */
+  enum opendal_errno errno;
+  /*
+   The error status of the error, please see opendal_error_status
+   for more details
+   */
+  enum opendal_error_status error_status;
+  /*
+   The error_msg consumes an area of heap memory, please call
+   [`opendal_free_error`] on the error to free the memory
+   */
+  const char *error_msg;

Review Comment:
   I don't like abbriation. How about expend to error_messge?
   
   By the way, can we name field as `kind` and `message` instead of `errno` and 
`error_msg`?



##########
bindings/c/include/opendal.h:
##########
@@ -25,14 +25,229 @@
 #include <stddef.h>
 #include <stdbool.h>
 
+/*
+ The C-compatible error type enum used in c bindings.
+ NOTICE: the type definition of [`ErrorNo`] should be aligned with
+         [`od::ErrorKind`]
+ */
+typedef enum opendal_errno {
+  /*
+   returning it back. For example, s3 returns an internal service error.
+   */
+  Unexpected,
+  /*
+   Underlying service doesn't support this operation.
+   */
+  Unsupported,
+  /*
+   The config for backend is invalid.
+   */
+  ConfigInvalid,
+  /*
+   The given path is not found.
+   */
+  NotFound,
+  /*
+   The given path doesn't have enough permission for this operation
+   */
+  PermissionDenied,
+  /*
+   The given path is a directory.
+   */
+  IsADirectory,
+  /*
+   The given path is not a directory.
+   */
+  NotADirectory,
+  /*
+   The given path already exists thus we failed to the specified operation on 
it.
+   */
+  AlreadyExists,
+  /*
+   Requests that sent to this path is over the limit, please slow down.
+   */
+  RateLimited,
+  /*
+   The given file paths are same.
+   */
+  IsSameFile,
+  /*
+   Unknown error, since [`opendal::ErrorKind`] is nonexhaustive
+   */
+  UnknownError,
+  /*
+   NullPtr error, meaning that a provided pointer which need to be 
dereferenced is null
+   */
+  NullPtr,
+} opendal_errno;
+
+/*
+ The C-compatible error status for opendal::Error.
+ NOTICE: the type definition of [`ErrorNo`] should be aligned with
+         [`od::ErrorStatus`]
+ */
+typedef enum opendal_error_status {
+  /*
+   Permanent means without external changes, the error never changes.
+
+   For example, underlying services returns a not found error.
+
+   Users SHOULD never retry this operation.
+   */
+  Permanent,
+  /*
+   Temporary means this error is returned for temporary.
+
+   For example, underlying services is rate limited or unavailable for 
temporary.
+
+   Users CAN retry the operation to resolve it.
+   */
+  Temporary,
+  /*
+   Persistent means this error used to be temporary but still failed after 
retry.
+
+   For example, underlying services kept returning network errors.
+
+   Users MAY retry this operation but it's highly possible to error again.
+   */
+  Persistent,
+} opendal_error_status;
+
+/*
+ The [`OperatorPtr`] owns a pointer to a [`od::BlockingOperator`].
+ It is also the key struct that OpenDAL's APIs access the real
+ operator's memory. The use of OperatorPtr is zero cost, it
+ only returns a reference of the underlying Operator.
+
+ The [`OperatorPtr`] also has a transparent layout, allowing you
+ to check its validity by native boolean operator.
+ e.g. you could check by (!ptr) on a opendal_operator_ptr type
+ */
+typedef const void *opendal_operator_ptr;
+
+/*
+ The error type returned of all opendal APIs in the C code
+ */
+typedef struct opendal_error {
+  /*
+   The error number of the actual error
+   */
+  enum opendal_errno errno;
+  /*
+   The error status of the error, please see opendal_error_status
+   for more details
+   */
+  enum opendal_error_status error_status;

Review Comment:
   We don't need to expose this to bindings. At least not for now.



##########
bindings/c/include/opendal.h:
##########
@@ -25,14 +25,229 @@
 #include <stddef.h>
 #include <stdbool.h>
 
+/*
+ The C-compatible error type enum used in c bindings.
+ NOTICE: the type definition of [`ErrorNo`] should be aligned with
+         [`od::ErrorKind`]
+ */
+typedef enum opendal_errno {
+  /*
+   returning it back. For example, s3 returns an internal service error.
+   */
+  Unexpected,
+  /*
+   Underlying service doesn't support this operation.
+   */
+  Unsupported,
+  /*
+   The config for backend is invalid.
+   */
+  ConfigInvalid,
+  /*
+   The given path is not found.
+   */
+  NotFound,
+  /*
+   The given path doesn't have enough permission for this operation
+   */
+  PermissionDenied,
+  /*
+   The given path is a directory.
+   */
+  IsADirectory,
+  /*
+   The given path is not a directory.
+   */
+  NotADirectory,
+  /*
+   The given path already exists thus we failed to the specified operation on 
it.
+   */
+  AlreadyExists,
+  /*
+   Requests that sent to this path is over the limit, please slow down.
+   */
+  RateLimited,
+  /*
+   The given file paths are same.
+   */
+  IsSameFile,
+  /*
+   Unknown error, since [`opendal::ErrorKind`] is nonexhaustive
+   */
+  UnknownError,
+  /*
+   NullPtr error, meaning that a provided pointer which need to be 
dereferenced is null
+   */
+  NullPtr,
+} opendal_errno;
+
+/*
+ The C-compatible error status for opendal::Error.
+ NOTICE: the type definition of [`ErrorNo`] should be aligned with
+         [`od::ErrorStatus`]
+ */
+typedef enum opendal_error_status {
+  /*
+   Permanent means without external changes, the error never changes.
+
+   For example, underlying services returns a not found error.
+
+   Users SHOULD never retry this operation.
+   */
+  Permanent,
+  /*
+   Temporary means this error is returned for temporary.
+
+   For example, underlying services is rate limited or unavailable for 
temporary.
+
+   Users CAN retry the operation to resolve it.
+   */
+  Temporary,
+  /*
+   Persistent means this error used to be temporary but still failed after 
retry.
+
+   For example, underlying services kept returning network errors.
+
+   Users MAY retry this operation but it's highly possible to error again.
+   */
+  Persistent,
+} opendal_error_status;
+
+/*
+ The [`OperatorPtr`] owns a pointer to a [`od::BlockingOperator`].
+ It is also the key struct that OpenDAL's APIs access the real
+ operator's memory. The use of OperatorPtr is zero cost, it
+ only returns a reference of the underlying Operator.
+
+ The [`OperatorPtr`] also has a transparent layout, allowing you
+ to check its validity by native boolean operator.
+ e.g. you could check by (!ptr) on a opendal_operator_ptr type
+ */
+typedef const void *opendal_operator_ptr;
+
+/*
+ The error type returned of all opendal APIs in the C code
+ */
+typedef struct opendal_error {
+  /*
+   The error number of the actual error
+   */
+  enum opendal_errno errno;
+  /*
+   The error status of the error, please see opendal_error_status
+   for more details
+   */
+  enum opendal_error_status error_status;
+  /*
+   The error_msg consumes an area of heap memory, please call
+   [`opendal_free_error`] on the error to free the memory
+   */
+  const char *error_msg;
+} opendal_error;
+
+/*
+ The Rust-like Result type of opendal C binding, it contains
+ a opendal_operator_ptr and a pointer to an error type.
+ Note that if `error` is not null, the error consumes heap memory
+ remember to free it by using [`opendal_free_error`]
+ */
+typedef struct opendal_result_op {
+  opendal_operator_ptr op_ptr;
+  struct opendal_error *error;
+} opendal_result_op;
+
+/*
+ The Rust-like Result type of opendal C binding, it contains
+ whether the write operation succeeds and a pointer to an error type.
+ Note that if `error` is not null, the error consumes heap memory
+ remember to free it by using [`opendal_free_error`]
+ */
+typedef struct opendal_result_write {
+  bool success;
+  struct opendal_error *error;
+} opendal_result_write;
+
+/*
+ The [`Bytes`] type is a C-compatible substitute for [`Bytes`]
+ in Rust, it will not be deallocated automatically like what
+ has been done in Rust. Instead, you have to call [`opendal_free_bytes`]
+ to free the heap memory to avoid memory leak.
+ The field `data` should not be modified since it might causes
+ the reallocation of the Vector.
+ */
+typedef struct opendal_bytes {
+  const uint8_t *data;
+  uintptr_t len;
+} opendal_bytes;
+
+/*
+ The Rust-like Result type of opendal C binding, it contains
+ the data that the read operation returns and a pointer to an error type.
+ If the read operation failed, the `data` fields should be a nullptr.
+ Note that if `error` is not null, the error consumes heap memory
+ remember to free it by using [`opendal_free_error`]
+ */
+typedef struct opendal_result_read {
+  struct opendal_bytes *data;
+  struct opendal_error *error;
+} opendal_result_read;
+
 #ifdef __cplusplus
 extern "C" {
 #endif // __cplusplus
 
 /*
- Hello, OpenDAL!
+ Returns a result type [`opendal_result_op`], with operator_ptr. If the 
construction succeeds
+ the error is nullptr, otherwise it contains the error information.
+
+ # Safety
+
+ It is [safe] under two cases below
+ * The memory pointed to by `scheme` must contain a valid nul terminator at 
the end of
+   the string.
+ * The `scheme` points to NULL, this function simply returns you a null 
opendal_operator_ptr
+ */
+struct opendal_result_op opendal_new_operator(const char *scheme);

Review Comment:
   I don't like the idea of adding `result` for every operation.How about 
providing API like this:
   
   ```c
   struct opendal_operator *opendal_operator_new(const char *scheme);
   struct opendal_code *opendal_operator_build(struct opendal_operator *op);
   ```
   
   Maybe we can add `opendal_code` like `hyper` does?



##########
bindings/c/src/error.rs:
##########
@@ -0,0 +1,203 @@
+// 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.
+
+use std::ffi::CString;
+use std::os::raw::{c_char, c_void};
+
+use ::opendal as od;
+
+/// The wrapper type for opendal's error, wrapped because of the
+/// orphan rule
+pub(crate) struct OpendalError(pub(crate) od::Error);
+
+/// The C-compatible error type enum used in c bindings.
+/// NOTICE: the type definition of [`ErrorNo`] should be aligned with
+///         [`od::ErrorKind`]
+#[repr(C)]
+pub enum opendal_errno {
+    /// returning it back. For example, s3 returns an internal service error.
+    Unexpected,
+    /// Underlying service doesn't support this operation.
+    Unsupported,
+    /// The config for backend is invalid.
+    ConfigInvalid,
+    /// The given path is not found.
+    NotFound,
+    /// The given path doesn't have enough permission for this operation
+    PermissionDenied,
+    /// The given path is a directory.
+    IsADirectory,
+    /// The given path is not a directory.
+    NotADirectory,
+    /// The given path already exists thus we failed to the specified 
operation on it.
+    AlreadyExists,
+    /// Requests that sent to this path is over the limit, please slow down.
+    RateLimited,
+    /// The given file paths are same.
+    IsSameFile,
+    /// Unknown error, since [`opendal::ErrorKind`] is nonexhaustive
+    UnknownError,
+    /// NullPtr error, meaning that a provided pointer which need to be 
dereferenced is null
+    NullPtr,
+}
+
+/// The C-compatible error status for opendal::Error.
+/// NOTICE: the type definition of [`ErrorNo`] should be aligned with
+///         [`od::ErrorStatus`]
+#[repr(C)]
+pub enum opendal_error_status {
+    /// Permanent means without external changes, the error never changes.
+    ///
+    /// For example, underlying services returns a not found error.
+    ///
+    /// Users SHOULD never retry this operation.
+    Permanent,
+    /// Temporary means this error is returned for temporary.
+    ///
+    /// For example, underlying services is rate limited or unavailable for 
temporary.
+    ///
+    /// Users CAN retry the operation to resolve it.
+    Temporary,
+    /// Persistent means this error used to be temporary but still failed 
after retry.
+    ///
+    /// For example, underlying services kept returning network errors.
+    ///
+    /// Users MAY retry this operation but it's highly possible to error again.
+    Persistent,
+}
+
+impl OpendalError {
+    /// Convert the [`od::ErrorKind`] of [`od::Error`] to our own
+    /// C-compatible type
+    pub(crate) fn errno(&self) -> opendal_errno {
+        let e = &self.0;
+        match e.kind() {
+            od::ErrorKind::Unexpected => opendal_errno::Unexpected,
+            od::ErrorKind::Unsupported => opendal_errno::Unsupported,
+            od::ErrorKind::ConfigInvalid => opendal_errno::ConfigInvalid,
+            od::ErrorKind::NotFound => opendal_errno::NotFound,
+            od::ErrorKind::PermissionDenied => opendal_errno::PermissionDenied,
+            od::ErrorKind::IsADirectory => opendal_errno::IsADirectory,
+            od::ErrorKind::NotADirectory => opendal_errno::NotADirectory,
+            od::ErrorKind::AlreadyExists => opendal_errno::AlreadyExists,
+            od::ErrorKind::RateLimited => opendal_errno::RateLimited,
+            od::ErrorKind::IsSameFile => opendal_errno::IsSameFile,
+            _ => opendal_errno::UnknownError,

Review Comment:
   I don't think we need unknown_error.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to