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

xuanwo pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/incubator-opendal.git


The following commit(s) were added to refs/heads/main by this push:
     new 4bd89ef5 feat(binding/c): add is_exist to operator (#1892)
4bd89ef5 is described below

commit 4bd89ef527d13c21ebb6ba074d995eb3da55f97f
Author: xyJi <[email protected]>
AuthorDate: Tue Apr 11 08:07:38 2023 +0800

    feat(binding/c): add is_exist to operator (#1892)
    
    feat(bindings/c): add is_exist operation on operator
    
    * Add is_exist operation
    * Update some rustdocs
    
    Signed-off-by: Ji-Xinyou <[email protected]>
---
 bindings/c/include/opendal.h | 53 +++++++++++++++++++++++++++++++++-------
 bindings/c/src/lib.rs        | 58 ++++++++++++++++++++++++++++++++++++++------
 bindings/c/src/result.rs     |  9 +++++++
 bindings/c/src/types.rs      | 38 ++++++++++++++---------------
 4 files changed, 121 insertions(+), 37 deletions(-)

diff --git a/bindings/c/include/opendal.h b/bindings/c/include/opendal.h
index a709c2fc..f4ad4704 100644
--- a/bindings/c/include/opendal.h
+++ b/bindings/c/include/opendal.h
@@ -112,24 +112,22 @@ typedef enum opendal_code {
 typedef struct BlockingOperator BlockingOperator;
 
 /*
- The [`OperatorPtr`] owns a pointer to a [`od::BlockingOperator`].
+ The [`opendal_operator_ptr`] 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
+ The [`opendal_operator_ptr`] 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
+ e.g. you could check by (!ptr) on a [`opendal_operator_ptr`]
  */
 typedef const struct BlockingOperator *opendal_operator_ptr;
 
 /*
- The [`Bytes`] type is a C-compatible substitute for [`Bytes`]
+ The [`opendal_bytes`] type is a C-compatible substitute for [`Vec`]
  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;
@@ -147,6 +145,16 @@ typedef struct opendal_result_read {
   enum opendal_code code;
 } opendal_result_read;
 
+/*
+ The result type for [`opendal_operator_is_exist()`], the field `is_exist`
+ contains whether the path exists, and the field `code` contains the
+ corresponding error code.
+ */
+typedef struct opendal_result_is_exist {
+  bool is_exist;
+  enum opendal_code code;
+} opendal_result_is_exist;
+
 #ifdef __cplusplus
 extern "C" {
 #endif // __cplusplus
@@ -178,7 +186,10 @@ void opendal_operator_free(opendal_operator_ptr op_ptr);
  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
+
+ # Panic
+
+ * If the `path` points to NULL, this function panics
  */
 enum opendal_code opendal_operator_blocking_write(opendal_operator_ptr op_ptr,
                                                   const char *path,
@@ -194,15 +205,39 @@ enum opendal_code 
opendal_operator_blocking_write(opendal_operator_ptr op_ptr,
  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
+
+ # Panic
+
+ * If the `path` points to NULL, this function panics
  */
 struct opendal_result_read opendal_operator_blocking_read(opendal_operator_ptr 
op_ptr,
                                                           const char *path);
 
+/*
+ Check whether the path exists.
+
+ If the operation succeeds, no matter the path exists or not,
+ the error code should be opendal_code::OPENDAL_OK. Otherwise,
+ the field `is_exist` is filled with false, and the error code
+ is set correspondingly.
+
+ # 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.
+
+ # Panic
+
+ * If the `path` points to NULL, this function panics
+ */
+struct opendal_result_is_exist opendal_operator_is_exist(opendal_operator_ptr 
op_ptr,
+                                                         const char *path);
+
 /*
  Frees the heap memory used by the [`opendal_bytes`]
  */
-void opendal_bytes_free(const struct opendal_bytes *vec);
+void opendal_bytes_free(const struct opendal_bytes *self);
 
 #ifdef __cplusplus
 } // extern "C"
diff --git a/bindings/c/src/lib.rs b/bindings/c/src/lib.rs
index 33d4488d..943e4fa0 100644
--- a/bindings/c/src/lib.rs
+++ b/bindings/c/src/lib.rs
@@ -30,7 +30,7 @@ use crate::types::{opendal_bytes, opendal_operator_ptr};
 
 use ::opendal as od;
 use error::opendal_code;
-use result::opendal_result_read;
+use result::{opendal_result_is_exist, opendal_result_read};
 
 /// Returns a result type [`opendal_result_op`], with operator_ptr. If the 
construction succeeds
 /// the error is nullptr, otherwise it contains the error information.
@@ -90,7 +90,10 @@ pub extern "C" fn opendal_operator_free(op_ptr: 
opendal_operator_ptr) {
 /// 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
+///
+/// # Panic
+///
+/// * If the `path` points to NULL, this function panics
 #[no_mangle]
 pub unsafe extern "C" fn opendal_operator_blocking_write(
     op_ptr: opendal_operator_ptr,
@@ -98,7 +101,7 @@ pub unsafe extern "C" fn opendal_operator_blocking_write(
     bytes: opendal_bytes,
 ) -> opendal_code {
     if path.is_null() {
-        return opendal_code::OPENDAL_ERROR;
+        panic!("The path given is pointing at NULL");
     }
 
     let op = op_ptr.get_ref();
@@ -118,17 +121,17 @@ pub unsafe extern "C" fn opendal_operator_blocking_write(
 /// 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
+///
+/// # Panic
+///
+/// * If the `path` points to NULL, this function panics
 #[no_mangle]
 pub unsafe extern "C" fn opendal_operator_blocking_read(
     op_ptr: opendal_operator_ptr,
     path: *const c_char,
 ) -> opendal_result_read {
     if path.is_null() {
-        return opendal_result_read {
-            data: std::ptr::null_mut(),
-            code: opendal_code::OPENDAL_ERROR,
-        };
+        panic!("The path given is pointing at NULL");
     }
 
     let op = op_ptr.get_ref();
@@ -148,3 +151,42 @@ pub unsafe extern "C" fn opendal_operator_blocking_read(
         },
     }
 }
+
+/// Check whether the path exists.
+///
+/// If the operation succeeds, no matter the path exists or not,
+/// the error code should be opendal_code::OPENDAL_OK. Otherwise,
+/// the field `is_exist` is filled with false, and the error code
+/// is set correspondingly.
+///
+/// # 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.
+///
+/// # Panic
+///
+/// * If the `path` points to NULL, this function panics
+#[no_mangle]
+pub unsafe extern "C" fn opendal_operator_is_exist(
+    op_ptr: opendal_operator_ptr,
+    path: *const c_char,
+) -> opendal_result_is_exist {
+    if path.is_null() {
+        panic!("The path given is pointing at NULL");
+    }
+
+    let op = op_ptr.get_ref();
+    let path = unsafe { std::ffi::CStr::from_ptr(path).to_str().unwrap() };
+    match op.is_exist(path) {
+        Ok(e) => opendal_result_is_exist {
+            is_exist: e,
+            code: opendal_code::OPENDAL_OK,
+        },
+        Err(err) => opendal_result_is_exist {
+            is_exist: false,
+            code: opendal_code::from_opendal_error(err),
+        },
+    }
+}
diff --git a/bindings/c/src/result.rs b/bindings/c/src/result.rs
index fe69dd35..69b2c5ba 100644
--- a/bindings/c/src/result.rs
+++ b/bindings/c/src/result.rs
@@ -31,3 +31,12 @@ pub struct opendal_result_read {
     pub data: *mut opendal_bytes,
     pub code: opendal_code,
 }
+
+/// The result type for [`opendal_operator_is_exist()`], the field `is_exist`
+/// contains whether the path exists, and the field `code` contains the
+/// corresponding error code.
+#[repr(C)]
+pub struct opendal_result_is_exist {
+    pub is_exist: bool,
+    pub code: opendal_code,
+}
diff --git a/bindings/c/src/types.rs b/bindings/c/src/types.rs
index f3b40d82..b8752fa0 100644
--- a/bindings/c/src/types.rs
+++ b/bindings/c/src/types.rs
@@ -17,23 +17,23 @@
 
 use ::opendal as od;
 
-/// The [`OperatorPtr`] owns a pointer to a [`od::BlockingOperator`].
+/// The [`opendal_operator_ptr`] 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
+/// The [`opendal_operator_ptr`] 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
+/// e.g. you could check by (!ptr) on a [`opendal_operator_ptr`]
 #[repr(transparent)]
 pub struct opendal_operator_ptr {
     ptr: *const od::BlockingOperator,
 }
 
 impl opendal_operator_ptr {
-    /// Creates an OperatorPtr will nullptr, indicating this [`OperatorPtr`]
+    /// Creates an OperatorPtr will nullptr, indicating this 
[`opendal_operator_ptr`]
     /// is invalid. The `transparent` layout also guarantees that if the
-    /// underlying field `ptr` is a nullptr, the [`OperatorPtr`] has the
+    /// underlying field `ptr` is a nullptr, the [`opendal_operator_ptr`] has 
the
     /// same layout as the nullptr.
     pub(crate) fn null() -> Self {
         Self {
@@ -46,7 +46,7 @@ impl opendal_operator_ptr {
         self.ptr.is_null()
     }
 
-    /// Returns a reference to the underlying [`BlockingOperator`]
+    /// Returns a reference to the underlying [`od::BlockingOperator`]
     pub(crate) fn get_ref(&self) -> &od::BlockingOperator {
         unsafe { &*(self.ptr) }
     }
@@ -74,12 +74,10 @@ impl From<&mut od::BlockingOperator> for 
opendal_operator_ptr {
     }
 }
 
-/// The [`Bytes`] type is a C-compatible substitute for [`Bytes`]
+/// The [`opendal_bytes`] type is a C-compatible substitute for [`Vec`]
 /// 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.
 #[repr(C)]
 pub struct opendal_bytes {
     pub data: *const u8,
@@ -87,13 +85,23 @@ pub struct opendal_bytes {
 }
 
 impl opendal_bytes {
-    /// Construct a [`Vector`] from the Rust [`Vec`] of bytes
+    /// Construct a [`opendal_bytes`] from the Rust [`Vec`] of bytes
     pub(crate) fn from_vec(vec: Vec<u8>) -> Self {
         let data = vec.as_ptr() as *const u8;
         let len = vec.len();
         std::mem::forget(vec); // To avoid deallocation of the vec.
         Self { data, len }
     }
+
+    /// Frees the heap memory used by the [`opendal_bytes`]
+    #[no_mangle]
+    pub extern "C" fn opendal_bytes_free(&self) {
+        unsafe {
+            // this deallocates the vector by reconstructing the vector and 
letting
+            // it be dropped when its out of scope
+            Vec::from_raw_parts(self.data as *mut u8, self.len, self.len);
+        }
+    }
 }
 
 #[allow(clippy::from_over_into)]
@@ -103,13 +111,3 @@ impl Into<bytes::Bytes> for opendal_bytes {
         bytes::Bytes::from_static(slice)
     }
 }
-
-/// Frees the heap memory used by the [`opendal_bytes`]
-#[no_mangle]
-pub extern "C" fn opendal_bytes_free(vec: *const opendal_bytes) {
-    unsafe {
-        // this deallocates the vector by reconstructing the vector and letting
-        // it be dropped when its out of scope
-        Vec::from_raw_parts((*vec).data as *mut u8, (*vec).len, (*vec).len);
-    }
-}

Reply via email to