You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@opendal.apache.org by ti...@apache.org on 2024/10/06 08:58:45 UTC
(opendal) branch main updated: refactor: more consistent C binding pattern (#5162)
This is an automated email from the ASF dual-hosted git repository.
tison pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/opendal.git
The following commit(s) were added to refs/heads/main by this push:
new d74bf7c2c5 refactor: more consistent C binding pattern (#5162)
d74bf7c2c5 is described below
commit d74bf7c2c5a9a011029c62ba1f381ae684fc4f57
Author: tison <wa...@gmail.com>
AuthorDate: Sun Oct 6 16:58:39 2024 +0800
refactor: more consistent C binding pattern (#5162)
Signed-off-by: tison <wa...@gmail.com>
---
bindings/c/include/opendal.h | 88 +++++---------
bindings/c/src/entry.rs | 6 +-
bindings/c/src/error.rs | 19 +--
bindings/c/src/lister.rs | 10 +-
bindings/c/src/metadata.rs | 4 +-
bindings/c/src/operator.rs | 255 +++++++++++++++++-----------------------
bindings/c/src/operator_info.rs | 12 +-
bindings/c/src/reader.rs | 17 ++-
bindings/c/src/types.rs | 25 ++--
bindings/c/src/writer.rs | 12 +-
10 files changed, 192 insertions(+), 256 deletions(-)
diff --git a/bindings/c/include/opendal.h b/bindings/c/include/opendal.h
index 05854c93e1..2df3447d23 100644
--- a/bindings/c/include/opendal.h
+++ b/bindings/c/include/opendal.h
@@ -81,60 +81,6 @@ typedef enum opendal_code {
OPENDAL_RANGE_NOT_SATISFIED,
} opendal_code;
-/**
- * BlockingOperator is the entry for all public blocking APIs.
- *
- * Read [`concepts`][docs::concepts] for know more about [`Operator`].
- *
- * # Examples
- *
- * ## Init backends
- *
- * Read more backend init examples in [`services`]
- *
- * ```rust,no_run
- * # use anyhow::Result;
- * use opendal::services::Fs;
- * use opendal::BlockingOperator;
- * use opendal::Operator;
- *
- * fn main() -> Result<()> {
- * // Create fs backend builder.
- * let builder = Fs::default().root("/tmp");
- *
- * // Build an `BlockingOperator` to start operating the storage.
- * let _: BlockingOperator = Operator::new(builder)?.finish().blocking();
- *
- * Ok(())
- * }
- * ```
- *
- * ## Init backends with blocking layer
- *
- * Some services like s3, gcs doesn't have native blocking supports, we can use [`layers::BlockingLayer`]
- * to wrap the async operator to make it blocking.
- * # use anyhow::Result;
- * use opendal::layers::BlockingLayer;
- * use opendal::services::S3;
- * use opendal::BlockingOperator;
- * use opendal::Operator;
- *
- * async fn test() -> Result<()> {
- * // Create fs backend builder.
- * let mut builder = S3::default().bucket("test").region("us-east-1");
- *
- * // Build an `BlockingOperator` with blocking layer to start operating the storage.
- * let _: BlockingOperator = Operator::new(builder)?
- * .layer(BlockingLayer::create()?)
- * .finish()
- * .blocking();
- *
- * Ok(())
- * }
- * ```
- */
-typedef struct BlockingOperator BlockingOperator;
-
/**
* \brief opendal_bytes carries raw-bytes with its length
*
@@ -188,6 +134,10 @@ typedef struct opendal_error {
* @see opendal_list_entry_name()
*/
typedef struct opendal_entry {
+ /**
+ * The pointer to the opendal::Entry in the Rust code.
+ * Only touch this on judging whether it is NULL.
+ */
void *inner;
} opendal_entry;
@@ -219,6 +169,10 @@ typedef struct opendal_result_lister_next {
* @see opendal_operator_list()
*/
typedef struct opendal_lister {
+ /**
+ * The pointer to the opendal::BlockingLister in the Rust code.
+ * Only touch this on judging whether it is NULL.
+ */
void *inner;
} opendal_lister;
@@ -259,7 +213,7 @@ typedef struct opendal_operator {
* The pointer to the opendal::BlockingOperator in the Rust code.
* Only touch this on judging whether it is NULL.
*/
- const struct BlockingOperator *ptr;
+ const void *inner;
} opendal_operator;
/**
@@ -297,7 +251,7 @@ typedef struct opendal_result_operator_new {
*/
typedef struct opendal_operator_options {
/**
- * The pointer to the Rust HashMap<String, String>
+ * The pointer to the HashMap<String, String> in the Rust code.
* Only touch this on judging whether it is NULL.
*/
void *inner;
@@ -329,6 +283,10 @@ typedef struct opendal_result_read {
* a opendal::BlockingReader, which is inside the Rust core code.
*/
typedef struct opendal_reader {
+ /**
+ * The pointer to the opendal::StdReader in the Rust code.
+ * Only touch this on judging whether it is NULL.
+ */
void *inner;
} opendal_reader;
@@ -355,6 +313,10 @@ typedef struct opendal_result_operator_reader {
* an opendal::BlockingWriter, which is inside the Rust core code.
*/
typedef struct opendal_writer {
+ /**
+ * The pointer to the opendal::BlockingWriter in the Rust code.
+ * Only touch this on judging whether it is NULL.
+ */
void *inner;
} opendal_writer;
@@ -436,6 +398,10 @@ typedef struct opendal_result_list {
* of operator.
*/
typedef struct opendal_operator_info {
+ /**
+ * The pointer to the opendal::OperatorInfo in the Rust code.
+ * Only touch this on judging whether it is NULL.
+ */
void *inner;
} opendal_operator_info;
@@ -658,7 +624,7 @@ void opendal_error_free(struct opendal_error *ptr);
* For examples, please see the comment section of opendal_operator_list()
* @see opendal_operator_list()
*/
-struct opendal_result_lister_next opendal_lister_next(const struct opendal_lister *self);
+struct opendal_result_lister_next opendal_lister_next(struct opendal_lister *self);
/**
* \brief Free the heap-allocated metadata used by opendal_lister
@@ -752,7 +718,7 @@ int64_t opendal_metadata_last_modified_ms(const struct opendal_metadata *self);
* opendal_operator_free(op);
* ```
*/
-void opendal_operator_free(const struct opendal_operator *op);
+void opendal_operator_free(const struct opendal_operator *ptr);
/**
* \brief Construct an operator based on `scheme` and `options`
@@ -1343,7 +1309,7 @@ struct opendal_capability opendal_operator_info_get_native_capability(const stru
/**
* \brief Frees the heap memory used by the opendal_bytes
*/
-void opendal_bytes_free(struct opendal_bytes *bs);
+void opendal_bytes_free(struct opendal_bytes *ptr);
/**
* \brief Construct a heap-allocated opendal_operator_options
@@ -1411,7 +1377,7 @@ void opendal_entry_free(struct opendal_entry *ptr);
/**
* \brief Read data from the reader.
*/
-struct opendal_result_reader_read opendal_reader_read(const struct opendal_reader *self,
+struct opendal_result_reader_read opendal_reader_read(struct opendal_reader *self,
uint8_t *buf,
uintptr_t len);
@@ -1423,7 +1389,7 @@ void opendal_reader_free(struct opendal_reader *ptr);
/**
* \brief Write data to the writer.
*/
-struct opendal_result_writer_write opendal_writer_write(const struct opendal_writer *self,
+struct opendal_result_writer_write opendal_writer_write(struct opendal_writer *self,
struct opendal_bytes bytes);
/**
diff --git a/bindings/c/src/entry.rs b/bindings/c/src/entry.rs
index f4c62792e0..f31fa77547 100644
--- a/bindings/c/src/entry.rs
+++ b/bindings/c/src/entry.rs
@@ -28,6 +28,8 @@ use ::opendal as core;
/// @see opendal_list_entry_name()
#[repr(C)]
pub struct opendal_entry {
+ /// The pointer to the opendal::Entry in the Rust code.
+ /// Only touch this on judging whether it is NULL.
inner: *mut c_void,
}
@@ -77,8 +79,8 @@ impl opendal_entry {
#[no_mangle]
pub unsafe extern "C" fn opendal_entry_free(ptr: *mut opendal_entry) {
if !ptr.is_null() {
- let _ = Box::from_raw((*ptr).inner as *mut core::Entry);
- let _ = Box::from_raw(ptr);
+ drop(Box::from_raw((*ptr).inner as *mut core::Entry));
+ drop(Box::from_raw(ptr));
}
}
}
diff --git a/bindings/c/src/error.rs b/bindings/c/src/error.rs
index ac6cb6b552..d1c6155ee7 100644
--- a/bindings/c/src/error.rs
+++ b/bindings/c/src/error.rs
@@ -68,7 +68,9 @@ impl From<core::ErrorKind> for opendal_code {
core::ErrorKind::RangeNotSatisfied => opendal_code::OPENDAL_RANGE_NOT_SATISFIED,
// if this is triggered, check the [`core`] crate and add a
// new error code accordingly
- _ => panic!("The newly added ErrorKind in core crate is not handled in C bindings"),
+ _ => unimplemented!(
+ "The newly added ErrorKind in core crate is not handled in C bindings"
+ ),
}
}
}
@@ -112,16 +114,19 @@ impl opendal_error {
#[no_mangle]
pub unsafe extern "C" fn opendal_error_free(ptr: *mut opendal_error) {
if !ptr.is_null() {
- let message_ptr = &(*ptr).message as *const opendal_bytes as *mut opendal_bytes;
+ let message_ptr = &(*ptr).message;
+ let message_ptr = message_ptr as *const opendal_bytes as *mut opendal_bytes;
if !message_ptr.is_null() {
- let data_mut = unsafe { (*message_ptr).data as *mut u8 };
- let _ = unsafe {
- Vec::from_raw_parts(data_mut, (*message_ptr).len, (*message_ptr).len)
- };
+ let data_mut = (*message_ptr).data as *mut u8;
+ drop(Vec::from_raw_parts(
+ data_mut,
+ (*message_ptr).len,
+ (*message_ptr).len,
+ ));
}
// free the pointer
- let _ = unsafe { Box::from_raw(ptr) };
+ drop(Box::from_raw(ptr))
}
}
}
diff --git a/bindings/c/src/lister.rs b/bindings/c/src/lister.rs
index 3376a011dd..b6a2a0e778 100644
--- a/bindings/c/src/lister.rs
+++ b/bindings/c/src/lister.rs
@@ -29,11 +29,13 @@ use super::*;
/// @see opendal_operator_list()
#[repr(C)]
pub struct opendal_lister {
+ /// The pointer to the opendal::BlockingLister in the Rust code.
+ /// Only touch this on judging whether it is NULL.
inner: *mut c_void,
}
impl opendal_lister {
- fn deref_mut(&self) -> &mut core::BlockingLister {
+ fn deref_mut(&mut self) -> &mut core::BlockingLister {
// Safety: the inner should never be null once constructed
// The use-after-free is undefined behavior
unsafe { &mut *(self.inner as *mut core::BlockingLister) }
@@ -55,7 +57,7 @@ impl opendal_lister {
/// For examples, please see the comment section of opendal_operator_list()
/// @see opendal_operator_list()
#[no_mangle]
- pub unsafe extern "C" fn opendal_lister_next(&self) -> opendal_result_lister_next {
+ pub unsafe extern "C" fn opendal_lister_next(&mut self) -> opendal_result_lister_next {
let e = self.deref_mut().next();
if e.is_none() {
return opendal_result_lister_next {
@@ -83,8 +85,8 @@ impl opendal_lister {
#[no_mangle]
pub unsafe extern "C" fn opendal_lister_free(ptr: *mut opendal_lister) {
if !ptr.is_null() {
- let _ = Box::from_raw((*ptr).inner as *mut core::BlockingLister);
- let _ = Box::from_raw(ptr);
+ drop(Box::from_raw((*ptr).inner as *mut core::BlockingLister));
+ drop(Box::from_raw(ptr));
}
}
}
diff --git a/bindings/c/src/metadata.rs b/bindings/c/src/metadata.rs
index 60a3c42a3f..394e337c0e 100644
--- a/bindings/c/src/metadata.rs
+++ b/bindings/c/src/metadata.rs
@@ -55,8 +55,8 @@ impl opendal_metadata {
#[no_mangle]
pub unsafe extern "C" fn opendal_metadata_free(ptr: *mut opendal_metadata) {
if !ptr.is_null() {
- let _ = Box::from_raw((*ptr).inner as *mut core::Metadata);
- let _ = Box::from_raw(ptr);
+ drop(Box::from_raw((*ptr).inner as *mut core::Metadata));
+ drop(Box::from_raw(ptr));
}
}
diff --git a/bindings/c/src/operator.rs b/bindings/c/src/operator.rs
index b3e070af3e..04df68ec45 100644
--- a/bindings/c/src/operator.rs
+++ b/bindings/c/src/operator.rs
@@ -16,6 +16,7 @@
// under the License.
use std::collections::HashMap;
+use std::ffi::c_void;
use std::os::raw::c_char;
use std::str::FromStr;
@@ -46,7 +47,15 @@ static RUNTIME: Lazy<tokio::runtime::Runtime> = Lazy::new(|| {
pub struct opendal_operator {
/// The pointer to the opendal::BlockingOperator in the Rust code.
/// Only touch this on judging whether it is NULL.
- ptr: *const core::BlockingOperator,
+ inner: *const c_void,
+}
+
+impl opendal_operator {
+ pub(crate) fn deref(&self) -> &core::BlockingOperator {
+ // Safety: the inner should never be null once constructed
+ // The use-after-free is undefined behavior
+ unsafe { &*(self.inner as *mut core::BlockingOperator) }
+ }
}
impl opendal_operator {
@@ -66,35 +75,11 @@ impl opendal_operator {
/// opendal_operator_free(op);
/// ```
#[no_mangle]
- pub unsafe extern "C" fn opendal_operator_free(op: *const opendal_operator) {
- let _ = unsafe { Box::from_raw((*op).ptr as *mut core::BlockingOperator) };
- let _ = unsafe { Box::from_raw(op as *mut opendal_operator) };
- }
-}
-
-/// Returns a reference to the underlying [`od::BlockingOperator`]
-///
-/// # Safety
-///
-/// The ptr is a raw pointer to the underlying [`od::BlockingOperator`].
-/// It will only free when opendal_operator_free has been called.
-impl AsRef<core::BlockingOperator> for opendal_operator {
- fn as_ref(&self) -> &core::BlockingOperator {
- unsafe { &*(self.ptr) }
- }
-}
-
-#[allow(clippy::from_over_into)]
-impl From<*const core::BlockingOperator> for opendal_operator {
- fn from(value: *const core::BlockingOperator) -> Self {
- Self { ptr: value }
- }
-}
-
-#[allow(clippy::from_over_into)]
-impl From<*mut core::BlockingOperator> for opendal_operator {
- fn from(value: *mut core::BlockingOperator) -> Self {
- Self { ptr: value }
+ pub unsafe extern "C" fn opendal_operator_free(ptr: *const opendal_operator) {
+ if !ptr.is_null() {
+ drop(Box::from_raw((*ptr).inner as *mut core::BlockingOperator));
+ drop(Box::from_raw(ptr as *mut opendal_operator));
+ }
}
}
@@ -158,12 +143,11 @@ pub unsafe extern "C" fn opendal_operator_new(
scheme: *const c_char,
options: *const opendal_operator_options,
) -> opendal_result_operator_new {
- if scheme.is_null() {
- panic!("The scheme given is pointing at NULL");
- }
-
- let scheme_str = unsafe { std::ffi::CStr::from_ptr(scheme).to_str().unwrap() };
- let scheme = match core::Scheme::from_str(scheme_str) {
+ assert!(!scheme.is_null());
+ let scheme = std::ffi::CStr::from_ptr(scheme)
+ .to_str()
+ .expect("malformed scheme");
+ let scheme = match core::Scheme::from_str(scheme) {
Ok(s) => s,
Err(e) => {
return opendal_result_operator_new {
@@ -181,13 +165,12 @@ pub unsafe extern "C" fn opendal_operator_new(
}
match build_operator(scheme, map) {
- Ok(op) => {
- let op = opendal_operator::from(Box::into_raw(Box::new(op.blocking())));
- opendal_result_operator_new {
- op: Box::into_raw(Box::new(op)),
- error: std::ptr::null_mut(),
- }
- }
+ Ok(op) => opendal_result_operator_new {
+ op: Box::into_raw(Box::new(opendal_operator {
+ inner: Box::into_raw(Box::new(op.blocking())) as _,
+ })),
+ error: std::ptr::null_mut(),
+ },
Err(e) => opendal_result_operator_new {
op: std::ptr::null_mut(),
error: opendal_error::new(e),
@@ -241,17 +224,15 @@ pub unsafe extern "C" fn opendal_operator_new(
/// * If the `path` points to NULL, this function panics, i.e. exits with information
#[no_mangle]
pub unsafe extern "C" fn opendal_operator_write(
- op: *const opendal_operator,
+ op: &opendal_operator,
path: *const c_char,
bytes: opendal_bytes,
) -> *mut opendal_error {
- if path.is_null() {
- panic!("The path given is pointing at NULL");
- }
-
- let op = (*op).as_ref();
- let path = unsafe { std::ffi::CStr::from_ptr(path).to_str().unwrap() };
- match op.write(path, bytes) {
+ assert!(!path.is_null());
+ let path = std::ffi::CStr::from_ptr(path)
+ .to_str()
+ .expect("malformed path");
+ match op.deref().write(path, bytes) {
Ok(_) => std::ptr::null_mut(),
Err(e) => opendal_error::new(e),
}
@@ -297,17 +278,14 @@ pub unsafe extern "C" fn opendal_operator_write(
/// * If the `path` points to NULL, this function panics, i.e. exits with information
#[no_mangle]
pub unsafe extern "C" fn opendal_operator_read(
- op: *const opendal_operator,
+ op: &opendal_operator,
path: *const c_char,
) -> opendal_result_read {
- if path.is_null() {
- panic!("The path given is pointing at NULL");
- }
-
- let op = (*op).as_ref();
- let path = unsafe { std::ffi::CStr::from_ptr(path).to_str().unwrap() };
- let data = op.read(path);
- match data {
+ assert!(!path.is_null());
+ let path = std::ffi::CStr::from_ptr(path)
+ .to_str()
+ .expect("malformed path");
+ match op.deref().read(path) {
Ok(d) => {
let v = Box::new(opendal_bytes::new(d));
opendal_result_read {
@@ -360,16 +338,14 @@ pub unsafe extern "C" fn opendal_operator_read(
/// * If the `path` points to NULL, this function panics, i.e. exits with information
#[no_mangle]
pub unsafe extern "C" fn opendal_operator_reader(
- op: *const opendal_operator,
+ op: &opendal_operator,
path: *const c_char,
) -> opendal_result_operator_reader {
- if path.is_null() {
- panic!("The path given is pointing at NULL");
- }
- let op = (*op).as_ref();
-
- let path = unsafe { std::ffi::CStr::from_ptr(path).to_str().unwrap() };
- let reader = match op.reader(path) {
+ assert!(!path.is_null());
+ let path = std::ffi::CStr::from_ptr(path)
+ .to_str()
+ .expect("malformed path");
+ let reader = match op.deref().reader(path) {
Ok(reader) => reader,
Err(err) => {
return opendal_result_operator_reader {
@@ -429,16 +405,14 @@ pub unsafe extern "C" fn opendal_operator_reader(
/// * If the `path` points to NULL, this function panics, i.e. exits with information
#[no_mangle]
pub unsafe extern "C" fn opendal_operator_writer(
- op: *const opendal_operator,
+ op: &opendal_operator,
path: *const c_char,
) -> opendal_result_operator_writer {
- if path.is_null() {
- panic!("The path given is pointing at NULL");
- }
- let op = (*op).as_ref();
-
- let path = unsafe { std::ffi::CStr::from_ptr(path).to_str().unwrap() };
- let writer = match op.writer(path) {
+ assert!(!path.is_null());
+ let path = std::ffi::CStr::from_ptr(path)
+ .to_str()
+ .expect("malformed path");
+ let writer = match op.deref().writer(path) {
Ok(writer) => writer,
Err(err) => {
return opendal_result_operator_writer {
@@ -496,16 +470,14 @@ pub unsafe extern "C" fn opendal_operator_writer(
/// * If the `path` points to NULL, this function panics, i.e. exits with information
#[no_mangle]
pub unsafe extern "C" fn opendal_operator_delete(
- op: *const opendal_operator,
+ op: &opendal_operator,
path: *const c_char,
) -> *mut opendal_error {
- if path.is_null() {
- panic!("The path given is pointing at NULL");
- }
-
- let op = (*op).as_ref();
- let path = unsafe { std::ffi::CStr::from_ptr(path).to_str().unwrap() };
- match op.delete(path) {
+ assert!(!path.is_null());
+ let path = std::ffi::CStr::from_ptr(path)
+ .to_str()
+ .expect("malformed path");
+ match op.deref().delete(path) {
Ok(_) => std::ptr::null_mut(),
Err(e) => opendal_error::new(e),
}
@@ -550,16 +522,14 @@ pub unsafe extern "C" fn opendal_operator_delete(
/// * If the `path` points to NULL, this function panics, i.e. exits with information
#[no_mangle]
pub unsafe extern "C" fn opendal_operator_is_exist(
- op: *const opendal_operator,
+ op: &opendal_operator,
path: *const c_char,
) -> opendal_result_is_exist {
- if path.is_null() {
- panic!("The path given is pointing at NULL");
- }
-
- let op = (*op).as_ref();
- let path = unsafe { std::ffi::CStr::from_ptr(path).to_str().unwrap() };
- match op.is_exist(path) {
+ assert!(!path.is_null());
+ let path = std::ffi::CStr::from_ptr(path)
+ .to_str()
+ .expect("malformed path");
+ match op.deref().is_exist(path) {
Ok(e) => opendal_result_is_exist {
is_exist: e,
error: std::ptr::null_mut(),
@@ -609,16 +579,14 @@ pub unsafe extern "C" fn opendal_operator_is_exist(
/// * If the `path` points to NULL, this function panics, i.e. exits with information
#[no_mangle]
pub unsafe extern "C" fn opendal_operator_stat(
- op: *const opendal_operator,
+ op: &opendal_operator,
path: *const c_char,
) -> opendal_result_stat {
- if path.is_null() {
- panic!("The path given is pointing at NULL");
- }
-
- let op = (*op).as_ref();
- let path = unsafe { std::ffi::CStr::from_ptr(path).to_str().unwrap() };
- match op.stat(path) {
+ assert!(!path.is_null());
+ let path = std::ffi::CStr::from_ptr(path)
+ .to_str()
+ .expect("malformed path");
+ match op.deref().stat(path) {
Ok(m) => opendal_result_stat {
meta: Box::into_raw(Box::new(opendal_metadata::new(m))),
error: std::ptr::null_mut(),
@@ -680,16 +648,14 @@ pub unsafe extern "C" fn opendal_operator_stat(
/// * If the `path` points to NULL, this function panics, i.e. exits with information
#[no_mangle]
pub unsafe extern "C" fn opendal_operator_list(
- op: *const opendal_operator,
+ op: &opendal_operator,
path: *const c_char,
) -> opendal_result_list {
- if path.is_null() {
- panic!("The path given is pointing at NULL");
- }
-
- let op = (*op).as_ref();
- let path = unsafe { std::ffi::CStr::from_ptr(path).to_str().unwrap() };
- match op.lister(path) {
+ assert!(!path.is_null());
+ let path = std::ffi::CStr::from_ptr(path)
+ .to_str()
+ .expect("malformed path");
+ match op.deref().lister(path) {
Ok(lister) => opendal_result_list {
lister: Box::into_raw(Box::new(opendal_lister::new(lister))),
error: std::ptr::null_mut(),
@@ -736,18 +702,17 @@ pub unsafe extern "C" fn opendal_operator_list(
/// * If the `path` points to NULL, this function panics, i.e. exits with information
#[no_mangle]
pub unsafe extern "C" fn opendal_operator_create_dir(
- op: *const opendal_operator,
+ op: &opendal_operator,
path: *const c_char,
) -> *mut opendal_error {
- if path.is_null() {
- panic!("The path given is pointing at NULL");
- }
-
- let op = (*op).as_ref();
- let path = unsafe { std::ffi::CStr::from_ptr(path).to_str().unwrap() };
- match op.create_dir(path) {
- Ok(_) => std::ptr::null_mut(),
- Err(e) => opendal_error::new(e),
+ assert!(!path.is_null());
+ let path = std::ffi::CStr::from_ptr(path)
+ .to_str()
+ .expect("malformed path");
+ if let Err(err) = op.deref().create_dir(path) {
+ opendal_error::new(err)
+ } else {
+ std::ptr::null_mut()
}
}
@@ -794,23 +759,22 @@ pub unsafe extern "C" fn opendal_operator_create_dir(
/// * If the `src` or `dest` points to NULL, this function panics, i.e. exits with information
#[no_mangle]
pub unsafe extern "C" fn opendal_operator_rename(
- op: *const opendal_operator,
+ op: &opendal_operator,
src: *const c_char,
dest: *const c_char,
) -> *mut opendal_error {
- if src.is_null() {
- panic!("The source path given is pointing at NULL");
- }
- if dest.is_null() {
- panic!("The destination path given is pointing at NULL");
- }
-
- let op = (*op).as_ref();
- let src = unsafe { std::ffi::CStr::from_ptr(src).to_str().unwrap() };
- let dest = unsafe { std::ffi::CStr::from_ptr(dest).to_str().unwrap() };
- match op.rename(src, dest) {
- Ok(_) => std::ptr::null_mut(),
- Err(e) => opendal_error::new(e),
+ assert!(!src.is_null());
+ assert!(!dest.is_null());
+ let src = std::ffi::CStr::from_ptr(src)
+ .to_str()
+ .expect("malformed src");
+ let dest = std::ffi::CStr::from_ptr(dest)
+ .to_str()
+ .expect("malformed dest");
+ if let Err(err) = op.deref().rename(src, dest) {
+ opendal_error::new(err)
+ } else {
+ std::ptr::null_mut()
}
}
@@ -857,22 +821,21 @@ pub unsafe extern "C" fn opendal_operator_rename(
/// * If the `src` or `dest` points to NULL, this function panics, i.e. exits with information
#[no_mangle]
pub unsafe extern "C" fn opendal_operator_copy(
- op: *const opendal_operator,
+ op: &opendal_operator,
src: *const c_char,
dest: *const c_char,
) -> *mut opendal_error {
- if src.is_null() {
- panic!("The source path given is pointing at NULL");
- }
- if dest.is_null() {
- panic!("The destination path given is pointing at NULL");
- }
-
- let op = (*op).as_ref();
- let src = unsafe { std::ffi::CStr::from_ptr(src).to_str().unwrap() };
- let dest = unsafe { std::ffi::CStr::from_ptr(dest).to_str().unwrap() };
- match op.copy(src, dest) {
- Ok(_) => std::ptr::null_mut(),
- Err(e) => opendal_error::new(e),
+ assert!(!src.is_null());
+ assert!(!dest.is_null());
+ let src = std::ffi::CStr::from_ptr(src)
+ .to_str()
+ .expect("malformed src");
+ let dest = std::ffi::CStr::from_ptr(dest)
+ .to_str()
+ .expect("malformed dest");
+ if let Err(err) = op.deref().copy(src, dest) {
+ opendal_error::new(err)
+ } else {
+ std::ptr::null_mut()
}
}
diff --git a/bindings/c/src/operator_info.rs b/bindings/c/src/operator_info.rs
index 36efe0c8b4..4e42962a78 100644
--- a/bindings/c/src/operator_info.rs
+++ b/bindings/c/src/operator_info.rs
@@ -26,6 +26,8 @@ use crate::opendal_operator;
/// of operator.
#[repr(C)]
pub struct opendal_operator_info {
+ /// The pointer to the opendal::OperatorInfo in the Rust code.
+ /// Only touch this on judging whether it is NULL.
inner: *mut c_void,
}
@@ -161,10 +163,8 @@ impl opendal_operator_info {
/// opendal_operator_info_free(info);
/// ```
#[no_mangle]
- pub unsafe extern "C" fn opendal_operator_info_new(op: *const opendal_operator) -> *mut Self {
- let op = (*op).as_ref();
- let info = op.info();
-
+ pub unsafe extern "C" fn opendal_operator_info_new(op: &opendal_operator) -> *mut Self {
+ let info = op.deref().info();
Box::into_raw(Box::new(Self {
inner: Box::into_raw(Box::new(info)) as _,
}))
@@ -174,8 +174,8 @@ impl opendal_operator_info {
#[no_mangle]
pub unsafe extern "C" fn opendal_operator_info_free(ptr: *mut Self) {
if !ptr.is_null() {
- let _ = Box::from_raw((*ptr).inner as *mut core::OperatorInfo);
- let _ = Box::from_raw(ptr);
+ drop(Box::from_raw((*ptr).inner as *mut core::OperatorInfo));
+ drop(Box::from_raw(ptr));
}
}
diff --git a/bindings/c/src/reader.rs b/bindings/c/src/reader.rs
index 5d15fcba0a..1c34658e1c 100644
--- a/bindings/c/src/reader.rs
+++ b/bindings/c/src/reader.rs
@@ -28,11 +28,13 @@ use super::*;
/// a opendal::BlockingReader, which is inside the Rust core code.
#[repr(C)]
pub struct opendal_reader {
+ /// The pointer to the opendal::StdReader in the Rust code.
+ /// Only touch this on judging whether it is NULL.
inner: *mut c_void,
}
impl opendal_reader {
- fn deref_mut(&self) -> &mut core::StdReader {
+ fn deref_mut(&mut self) -> &mut core::StdReader {
// Safety: the inner should never be null once constructed
// The use-after-free is undefined behavior
unsafe { &mut *(self.inner as *mut core::StdReader) }
@@ -49,15 +51,12 @@ impl opendal_reader {
/// \brief Read data from the reader.
#[no_mangle]
pub unsafe extern "C" fn opendal_reader_read(
- &self,
+ &mut self,
buf: *mut u8,
len: usize,
) -> opendal_result_reader_read {
- if buf.is_null() {
- panic!("buf is NULL");
- }
-
- let buf = unsafe { std::slice::from_raw_parts_mut(buf, len) };
+ assert!(!buf.is_null());
+ let buf = std::slice::from_raw_parts_mut(buf, len);
match self.deref_mut().read(buf) {
Ok(n) => opendal_result_reader_read {
size: n,
@@ -77,8 +76,8 @@ impl opendal_reader {
#[no_mangle]
pub unsafe extern "C" fn opendal_reader_free(ptr: *mut opendal_reader) {
if !ptr.is_null() {
- let _ = Box::from_raw((*ptr).inner as *mut core::StdReader);
- let _ = Box::from_raw(ptr);
+ drop(Box::from_raw((*ptr).inner as *mut core::StdReader));
+ drop(Box::from_raw(ptr));
}
}
}
diff --git a/bindings/c/src/types.rs b/bindings/c/src/types.rs
index 932f63b627..051724a671 100644
--- a/bindings/c/src/types.rs
+++ b/bindings/c/src/types.rs
@@ -48,21 +48,18 @@ impl opendal_bytes {
/// \brief Frees the heap memory used by the opendal_bytes
#[no_mangle]
- pub unsafe extern "C" fn opendal_bytes_free(bs: *mut opendal_bytes) {
- if !bs.is_null() {
- let data_mut = unsafe { (*bs).data as *mut u8 };
- // free the vector
- let _ = unsafe { Vec::from_raw_parts(data_mut, (*bs).len, (*bs).len) };
- // free the pointer
- let _ = unsafe { Box::from_raw(bs) };
+ pub unsafe extern "C" fn opendal_bytes_free(ptr: *mut opendal_bytes) {
+ if !ptr.is_null() {
+ let data_mut = (*ptr).data as *mut u8;
+ drop(Vec::from_raw_parts(data_mut, (*ptr).len, (*ptr).len));
+ drop(Box::from_raw(ptr));
}
}
}
-#[allow(clippy::from_over_into)]
-impl Into<Buffer> for opendal_bytes {
- fn into(self) -> Buffer {
- let slice = unsafe { std::slice::from_raw_parts(self.data, self.len) };
+impl From<opendal_bytes> for Buffer {
+ fn from(v: opendal_bytes) -> Self {
+ let slice = unsafe { std::slice::from_raw_parts(v.data, v.len) };
Buffer::from(bytes::Bytes::copy_from_slice(slice))
}
}
@@ -77,7 +74,7 @@ impl Into<Buffer> for opendal_bytes {
/// @see opendal_operator_options_set This function allow you to set the options
#[repr(C)]
pub struct opendal_operator_options {
- /// The pointer to the Rust HashMap<String, String>
+ /// The pointer to the HashMap<String, String> in the Rust code.
/// Only touch this on judging whether it is NULL.
inner: *mut c_void,
}
@@ -150,8 +147,8 @@ impl opendal_operator_options {
#[no_mangle]
pub unsafe extern "C" fn opendal_operator_options_free(ptr: *mut opendal_operator_options) {
if !ptr.is_null() {
- let _ = Box::from_raw((*ptr).inner as *mut HashMap<String, String>);
- let _ = Box::from_raw(ptr);
+ drop(Box::from_raw((*ptr).inner as *mut HashMap<String, String>));
+ drop(Box::from_raw(ptr));
}
}
}
diff --git a/bindings/c/src/writer.rs b/bindings/c/src/writer.rs
index 36cc578790..67ac7d53f4 100644
--- a/bindings/c/src/writer.rs
+++ b/bindings/c/src/writer.rs
@@ -25,11 +25,13 @@ use super::*;
/// an opendal::BlockingWriter, which is inside the Rust core code.
#[repr(C)]
pub struct opendal_writer {
+ /// The pointer to the opendal::BlockingWriter in the Rust code.
+ /// Only touch this on judging whether it is NULL.
inner: *mut c_void,
}
impl opendal_writer {
- fn deref_mut(&self) -> &mut core::BlockingWriter {
+ fn deref_mut(&mut self) -> &mut core::BlockingWriter {
// Safety: the inner should never be null once constructed
// The use-after-free is undefined behavior
unsafe { &mut *(self.inner as *mut core::BlockingWriter) }
@@ -46,7 +48,7 @@ impl opendal_writer {
/// \brief Write data to the writer.
#[no_mangle]
pub unsafe extern "C" fn opendal_writer_write(
- &self,
+ &mut self,
bytes: opendal_bytes,
) -> opendal_result_writer_write {
let size = bytes.len;
@@ -70,9 +72,9 @@ impl opendal_writer {
#[no_mangle]
pub unsafe extern "C" fn opendal_writer_free(ptr: *mut opendal_writer) {
if !ptr.is_null() {
- let _ = (&*ptr).deref_mut().close();
- let _ = unsafe { Box::from_raw((*ptr).inner as *mut core::BlockingWriter) };
- let _ = unsafe { Box::from_raw(ptr) };
+ let _ = (*ptr).deref_mut().close();
+ drop(Box::from_raw((*ptr).inner as *mut core::BlockingWriter));
+ drop(Box::from_raw(ptr));
}
}
}