Skip to content

Commit

Permalink
feat(bindings/c): add opendal_operator_exists and mark is_exist depre…
Browse files Browse the repository at this point in the history
…cated (#5199)
  • Loading branch information
PragmaTwice authored Oct 18, 2024
1 parent 09fb972 commit b5b7132
Show file tree
Hide file tree
Showing 6 changed files with 148 additions and 5 deletions.
3 changes: 3 additions & 0 deletions bindings/c/cbindgen.toml
Original file line number Diff line number Diff line change
Expand Up @@ -48,3 +48,6 @@ sys_includes = ["stdint.h", "stddef.h", "stdbool.h"]
[parse]
include = ["opendal"]
parse_deps = true

[fn]
deprecated_with_note = "__attribute__((deprecated({})))"
64 changes: 64 additions & 0 deletions bindings/c/include/opendal.h
Original file line number Diff line number Diff line change
Expand Up @@ -361,6 +361,27 @@ typedef struct opendal_result_is_exist {
struct opendal_error *error;
} opendal_result_is_exist;

/**
* \brief The result type returned by opendal_operator_exists().
*
* The result type for opendal_operator_exists(), the field `exists`
* contains whether the path exists, and the field `error` contains the
* corresponding error. If successful, the `error` field is null.
*
* \note If the opendal_operator_exists() fails, the `exists` field
* will be set to false.
*/
typedef struct opendal_result_exists {
/**
* Whether the path exists
*/
bool exists;
/**
* The error, if ok, it is null
*/
struct opendal_error *error;
} opendal_result_exists;

/**
* \brief The result type returned by opendal_operator_stat().
*
Expand Down Expand Up @@ -1025,9 +1046,52 @@ struct opendal_error *opendal_operator_delete(const struct opendal_operator *op,
*
* * If the `path` points to NULL, this function panics, i.e. exits with information
*/
__attribute__((deprecated("Use opendal_operator_exists() instead.")))
struct opendal_result_is_exist opendal_operator_is_exist(const struct opendal_operator *op,
const char *path);

/**
* \brief Check whether the path exists.
*
* If the operation succeeds, no matter the path exists or not,
* the error should be a nullptr. Otherwise, the field `exists`
* is filled with false, and the error is set
*
* @param op The opendal_operator created previously
* @param path The path you want to check existence
* @see opendal_operator
* @see opendal_result_exists
* @see opendal_error
* @return Returns opendal_result_exists, the `exists` field contains whether the path exists.
* However, it the operation fails, the `exists` will contain false and the error will be set.
*
* # Example
*
* ```C
* // .. you previously wrote some data to path "/mytest/obj"
* opendal_result_exists e = opendal_operator_exists(op, "/mytest/obj");
* assert(e.error == NULL);
* assert(e.exists);
*
* // but you previously did **not** write any data to path "/yourtest/obj"
* opendal_result_exists e = opendal_operator_exists(op, "/yourtest/obj");
* assert(e.error == NULL);
* assert(!e.exists);
* ```
*
* # Safety
*
* It is **safe** under the 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, i.e. exits with information
*/
struct opendal_result_exists opendal_operator_exists(const struct opendal_operator *op,
const char *path);

/**
* \brief Stat the path, return its metadata.
*
Expand Down
1 change: 1 addition & 0 deletions bindings/c/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ pub use operator::opendal_operator;
mod operator_info;

mod result;
pub use result::opendal_result_exists;
pub use result::opendal_result_is_exist;
pub use result::opendal_result_list;
pub use result::opendal_result_lister_next;
Expand Down
61 changes: 60 additions & 1 deletion bindings/c/src/operator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -519,6 +519,7 @@ pub unsafe extern "C" fn opendal_operator_delete(
///
/// * If the `path` points to NULL, this function panics, i.e. exits with information
#[no_mangle]
#[deprecated(note = "Use opendal_operator_exists() instead.")]
pub unsafe extern "C" fn opendal_operator_is_exist(
op: &opendal_operator,
path: *const c_char,
Expand All @@ -527,7 +528,7 @@ pub unsafe extern "C" fn opendal_operator_is_exist(
let path = std::ffi::CStr::from_ptr(path)
.to_str()
.expect("malformed path");
match op.deref().is_exist(path) {
match op.deref().exists(path) {
Ok(e) => opendal_result_is_exist {
is_exist: e,
error: std::ptr::null_mut(),
Expand All @@ -539,6 +540,64 @@ pub unsafe extern "C" fn opendal_operator_is_exist(
}
}

/// \brief Check whether the path exists.
///
/// If the operation succeeds, no matter the path exists or not,
/// the error should be a nullptr. Otherwise, the field `exists`
/// is filled with false, and the error is set
///
/// @param op The opendal_operator created previously
/// @param path The path you want to check existence
/// @see opendal_operator
/// @see opendal_result_exists
/// @see opendal_error
/// @return Returns opendal_result_exists, the `exists` field contains whether the path exists.
/// However, it the operation fails, the `exists` will contain false and the error will be set.
///
/// # Example
///
/// ```C
/// // .. you previously wrote some data to path "/mytest/obj"
/// opendal_result_exists e = opendal_operator_exists(op, "/mytest/obj");
/// assert(e.error == NULL);
/// assert(e.exists);
///
/// // but you previously did **not** write any data to path "/yourtest/obj"
/// opendal_result_exists e = opendal_operator_exists(op, "/yourtest/obj");
/// assert(e.error == NULL);
/// assert(!e.exists);
/// ```
///
/// # Safety
///
/// It is **safe** under the 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, i.e. exits with information
#[no_mangle]
pub unsafe extern "C" fn opendal_operator_exists(
op: &opendal_operator,
path: *const c_char,
) -> opendal_result_exists {
assert!(!path.is_null());
let path = std::ffi::CStr::from_ptr(path)
.to_str()
.expect("malformed path");
match op.deref().exists(path) {
Ok(e) => opendal_result_exists {
exists: e,
error: std::ptr::null_mut(),
},
Err(e) => opendal_result_exists {
exists: false,
error: opendal_error::new(e),
},
}
}

/// \brief Stat the path, return its metadata.
///
/// Error is NULL if successful, otherwise it contains the error code and error message.
Expand Down
16 changes: 16 additions & 0 deletions bindings/c/src/result.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,22 @@ pub struct opendal_result_is_exist {
pub error: *mut opendal_error,
}

/// \brief The result type returned by opendal_operator_exists().
///
/// The result type for opendal_operator_exists(), the field `exists`
/// contains whether the path exists, and the field `error` contains the
/// corresponding error. If successful, the `error` field is null.
///
/// \note If the opendal_operator_exists() fails, the `exists` field
/// will be set to false.
#[repr(C)]
pub struct opendal_result_exists {
/// Whether the path exists
pub exists: bool,
/// The error, if ok, it is null
pub error: *mut opendal_error,
}

/// \brief The result type returned by opendal_operator_stat().
///
/// The result type for opendal_operator_stat(), the field `meta` contains the metadata
Expand Down
8 changes: 4 additions & 4 deletions bindings/c/tests/bdd.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -65,9 +65,9 @@ TEST_F(OpendalBddTest, FeatureTest)
EXPECT_EQ(error, nullptr);

// The blocking file "test" should exist
opendal_result_is_exist e = opendal_operator_is_exist(this->p, this->path.c_str());
opendal_result_exists e = opendal_operator_exists(this->p, this->path.c_str());
EXPECT_EQ(e.error, nullptr);
EXPECT_TRUE(e.is_exist);
EXPECT_TRUE(e.exists);

// The blocking file "test" entry mode must be file
opendal_result_stat s = opendal_operator_stat(this->p, this->path.c_str());
Expand All @@ -93,9 +93,9 @@ TEST_F(OpendalBddTest, FeatureTest)
// The blocking file should be deleted
error = opendal_operator_delete(this->p, this->path.c_str());
EXPECT_EQ(error, nullptr);
e = opendal_operator_is_exist(this->p, this->path.c_str());
e = opendal_operator_exists(this->p, this->path.c_str());
EXPECT_EQ(e.error, nullptr);
EXPECT_FALSE(e.is_exist);
EXPECT_FALSE(e.exists);

opendal_result_operator_writer writer = opendal_operator_writer(this->p, this->path.c_str());
EXPECT_EQ(writer.error, nullptr);
Expand Down

0 comments on commit b5b7132

Please sign in to comment.