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);
- }
-}