| // 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::collections::HashMap; |
| use std::ffi::c_void; |
| use std::os::raw::c_char; |
| use std::sync::LazyLock; |
| |
| use ::opendal as core; |
| |
| use super::*; |
| |
| static RUNTIME: LazyLock<tokio::runtime::Runtime> = LazyLock::new(|| { |
| tokio::runtime::Builder::new_multi_thread() |
| .enable_all() |
| .build() |
| .unwrap() |
| }); |
| |
| /// \brief Used to access almost all OpenDAL APIs. It represents an |
| /// operator that provides the unified interfaces provided by OpenDAL. |
| /// |
| /// @see opendal_operator_new This function construct the operator |
| /// @see opendal_operator_free This function frees the heap memory of the operator |
| /// |
| /// \note The opendal_operator actually owns a pointer to |
| /// an opendal::blocking::Operator, which is inside the Rust core code. |
| /// |
| /// \remark You may use the field `ptr` to check whether this is a NULL |
| /// operator. |
| #[repr(C)] |
| pub struct opendal_operator { |
| /// The pointer to the opendal::blocking::Operator in the Rust code. |
| /// Only touch this on judging whether it is NULL. |
| inner: *mut c_void, |
| } |
| |
| impl opendal_operator { |
| pub(crate) fn deref(&self) -> &core::blocking::Operator { |
| // Safety: the inner should never be null once constructed |
| // The use-after-free is undefined behavior |
| unsafe { &*(self.inner as *mut core::blocking::Operator) } |
| } |
| } |
| |
| impl opendal_operator { |
| /// \brief Free the heap-allocated operator pointed by opendal_operator. |
| /// |
| /// Please only use this for a pointer pointing at a valid opendal_operator. |
| /// Calling this function on NULL does nothing, but calling this function on pointers |
| /// of other type will lead to segfault. |
| /// |
| /// # Example |
| /// |
| /// ```C |
| /// opendal_operator *op = opendal_operator_new("fs", NULL); |
| /// // ... use this op, maybe some reads and writes |
| /// |
| /// // free this operator |
| /// opendal_operator_free(op); |
| /// ``` |
| #[unsafe(no_mangle)] |
| pub unsafe extern "C" fn opendal_operator_free(ptr: *const opendal_operator) { |
| unsafe { |
| if !ptr.is_null() { |
| drop(Box::from_raw((*ptr).inner as *mut core::blocking::Operator)); |
| drop(Box::from_raw(ptr as *mut opendal_operator)); |
| } |
| } |
| } |
| } |
| |
| fn build_operator( |
| schema: &str, |
| map: HashMap<String, String>, |
| ) -> core::Result<core::blocking::Operator> { |
| core::init_default_registry(); |
| |
| let op = core::Operator::via_iter(schema, map)?.layer(core::layers::RetryLayer::new()); |
| |
| let runtime = |
| tokio::runtime::Handle::try_current().unwrap_or_else(|_| RUNTIME.handle().clone()); |
| let _guard = runtime.enter(); |
| let op = core::blocking::Operator::new(op)?; |
| Ok(op) |
| } |
| |
| /// \brief Construct an operator based on `scheme` and `options` |
| /// |
| /// Uses an array of key-value pairs to initialize the operator based on provided `scheme` |
| /// and `options`. For each scheme, i.e. Backend, different options could be set, you may |
| /// reference the [documentation](https://opendal.apache.org/docs/category/services/) for |
| /// each service, especially for the **Configuration Part**. |
| /// |
| /// @param scheme the service scheme you want to specify, e.g. "fs", "s3" |
| /// @param options the pointer to the options for this operator, it could be NULL, which means no |
| /// option is set |
| /// @see opendal_operator_options |
| /// @return A valid opendal_result_operator_new setup with the `scheme` and `options` is the construction |
| /// succeeds. On success the operator field is a valid pointer to a newly allocated opendal_operator, |
| /// and the error field is NULL. Otherwise, the operator field is a NULL pointer and the error field. |
| /// |
| /// # Example |
| /// |
| /// Following is an example. |
| /// ```C |
| /// // Allocate a new options |
| /// opendal_operator_options *options = opendal_operator_options_new(); |
| /// // Set the options you need |
| /// opendal_operator_options_set(options, "root", "/myroot"); |
| /// |
| /// // Construct the operator based on the options and scheme |
| /// opendal_result_operator_new result = opendal_operator_new("memory", options); |
| /// opendal_operator* op = result.op; |
| /// |
| /// // you could free the options right away since the options is not used afterwards |
| /// opendal_operator_options_free(options); |
| /// |
| /// // ... your operations |
| /// ``` |
| /// |
| /// # Safety |
| /// |
| /// The only unsafe case is passing an invalid c string pointer to the `scheme` argument. |
| #[no_mangle] |
| pub unsafe extern "C" fn opendal_operator_new( |
| scheme: *const c_char, |
| options: *const opendal_operator_options, |
| ) -> opendal_result_operator_new { |
| assert!(!scheme.is_null()); |
| let scheme = std::ffi::CStr::from_ptr(scheme) |
| .to_str() |
| .expect("malformed scheme"); |
| |
| let mut map = HashMap::<String, String>::default(); |
| if !options.is_null() { |
| for (k, v) in (*options).deref() { |
| map.insert(k.to_string(), v.to_string()); |
| } |
| } |
| |
| match build_operator(scheme, map) { |
| Ok(op) => opendal_result_operator_new { |
| op: Box::into_raw(Box::new(opendal_operator { |
| inner: Box::into_raw(Box::new(op)) as _, |
| })), |
| error: std::ptr::null_mut(), |
| }, |
| Err(e) => opendal_result_operator_new { |
| op: std::ptr::null_mut(), |
| error: opendal_error::new(e), |
| }, |
| } |
| } |
| |
| /// \brief Blocking write raw bytes to `path`. |
| /// |
| /// Write the `bytes` into the `path` blocking by `op_ptr`. |
| /// Error is NULL if successful, otherwise it contains the error code and error message. |
| /// |
| /// \note It is important to notice that the `bytes` that is passes in will be consumed by this |
| /// function. Therefore, you should not use the `bytes` after this function returns. |
| /// |
| /// @param op The opendal_operator created previously |
| /// @param path The designated path you want to write your bytes in |
| /// @param bytes The opendal_byte typed bytes to be written |
| /// @see opendal_operator |
| /// @see opendal_bytes |
| /// @see opendal_error |
| /// @return NULL if succeeds, otherwise it contains the error code and error message. |
| /// |
| /// # Example |
| /// |
| /// Following is an example |
| /// ```C |
| /// //...prepare your opendal_operator, named op for example |
| /// |
| /// // prepare your data |
| /// char* data = "Hello, World!"; |
| /// opendal_bytes bytes = opendal_bytes { .data = (uint8_t*)data, .len = 13 }; |
| /// |
| /// // now you can write! |
| /// opendal_error *err = opendal_operator_write(op, "/testpath", bytes); |
| /// |
| /// // Assert that this succeeds |
| /// assert(err == NULL); |
| /// ``` |
| /// |
| /// # 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. |
| /// * The `bytes` provided has valid byte in the `data` field and the `len` field is set |
| /// correctly. |
| /// |
| /// # Panic |
| /// |
| /// * 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: &opendal_operator, |
| path: *const c_char, |
| bytes: &opendal_bytes, |
| ) -> *mut opendal_error { |
| 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), |
| } |
| } |
| |
| /// \brief Blocking read the data from `path`. |
| /// |
| /// Read the data out from `path` blocking by operator. |
| /// |
| /// @param op The opendal_operator created previously |
| /// @param path The path you want to read the data out |
| /// @see opendal_operator |
| /// @see opendal_result_read |
| /// @see opendal_error |
| /// @return Returns opendal_result_read, the `data` field is a pointer to a newly allocated |
| /// opendal_bytes, the `error` field contains the error. If the `error` is not NULL, then |
| /// the operation failed and the `data` field is a nullptr. |
| /// |
| /// \note If the read operation succeeds, the returned opendal_bytes is newly allocated on heap. |
| /// After your usage of that, please call opendal_bytes_free() to free the space. |
| /// |
| /// # Example |
| /// |
| /// Following is an example |
| /// ```C |
| /// // ... you have write "Hello, World!" to path "/testpath" |
| /// |
| /// opendal_result_read r = opendal_operator_read(op, "testpath"); |
| /// assert(r.error == NULL); |
| /// |
| /// opendal_bytes bytes = r.data; |
| /// assert(bytes.len == 13); |
| /// opendal_bytes_free(&bytes); |
| /// ``` |
| /// |
| /// # 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_read( |
| op: &opendal_operator, |
| path: *const c_char, |
| ) -> opendal_result_read { |
| assert!(!path.is_null()); |
| let path = std::ffi::CStr::from_ptr(path) |
| .to_str() |
| .expect("malformed path"); |
| match op.deref().read(path) { |
| Ok(b) => opendal_result_read { |
| data: opendal_bytes::new(b), |
| error: std::ptr::null_mut(), |
| }, |
| Err(e) => opendal_result_read { |
| data: opendal_bytes::empty(), |
| error: opendal_error::new(e), |
| }, |
| } |
| } |
| |
| /// \brief Blocking read the data from `path`. |
| /// |
| /// Read the data out from `path` blocking by operator, returns |
| /// an opendal_result_read with error code. |
| /// |
| /// @param op The opendal_operator created previously |
| /// @param path The path you want to read the data out |
| /// @see opendal_operator |
| /// @see opendal_result_read |
| /// @see opendal_code |
| /// @return Returns opendal_code |
| /// |
| /// \note If the read operation succeeds, the returned opendal_bytes is newly allocated on heap. |
| /// After your usage of that, please call opendal_bytes_free() to free the space. |
| /// |
| /// # Example |
| /// |
| /// Following is an example |
| /// ```C |
| /// // ... you have created an operator named op |
| /// |
| /// opendal_result_operator_reader result = opendal_operator_reader(op, "/testpath"); |
| /// assert(result.error == NULL); |
| /// // The reader is in result.reader |
| /// opendal_reader *reader = result.reader; |
| /// ``` |
| /// |
| /// # 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_reader( |
| op: &opendal_operator, |
| path: *const c_char, |
| ) -> opendal_result_operator_reader { |
| 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 { |
| reader: std::ptr::null_mut(), |
| error: opendal_error::new(err), |
| } |
| } |
| }; |
| |
| match reader.into_std_read(..) { |
| Ok(reader) => opendal_result_operator_reader { |
| reader: Box::into_raw(Box::new(opendal_reader::new(reader))), |
| error: std::ptr::null_mut(), |
| }, |
| Err(e) => opendal_result_operator_reader { |
| reader: std::ptr::null_mut(), |
| error: opendal_error::new(e), |
| }, |
| } |
| } |
| |
| /// \brief Blocking create a writer for the specified path. |
| /// |
| /// This function prepares a writer that can be used to write data to the specified path |
| /// using the provided operator. If successful, it returns a valid writer; otherwise, it |
| /// returns an error. |
| /// |
| /// @param op The opendal_operator created previously |
| /// @param path The designated path where the writer will be used |
| /// @see opendal_operator |
| /// @see opendal_result_operator_writer |
| /// @see opendal_error |
| /// @return Returns opendal_result_operator_writer, containing a writer and an opendal_error. |
| /// If the operation succeeds, the `writer` field holds a valid writer and the `error` field |
| /// is null. Otherwise, the `writer` will be null and the `error` will be set correspondingly. |
| /// |
| /// # Example |
| /// |
| /// Following is an example |
| /// ```C |
| /// //...prepare your opendal_operator, named op for example |
| /// |
| /// opendal_result_operator_writer result = opendal_operator_writer(op, "/testpath"); |
| /// assert(result.error == NULL); |
| /// opendal_writer *writer = result.writer; |
| /// // Use the writer to write data... |
| /// ``` |
| /// |
| /// # 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_writer( |
| op: &opendal_operator, |
| path: *const c_char, |
| ) -> opendal_result_operator_writer { |
| 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 { |
| writer: std::ptr::null_mut(), |
| error: opendal_error::new(err), |
| } |
| } |
| }; |
| |
| opendal_result_operator_writer { |
| writer: Box::into_raw(Box::new(opendal_writer::new(writer))), |
| error: std::ptr::null_mut(), |
| } |
| } |
| |
| /// \brief Blocking delete the object in `path`. |
| /// |
| /// Delete the object in `path` blocking by `op_ptr`. |
| /// Error is NULL if successful, otherwise it contains the error code and error message. |
| /// |
| /// @param op The opendal_operator created previously |
| /// @param path The designated path you want to delete |
| /// @see opendal_operator |
| /// @see opendal_error |
| /// @return NULL if succeeds, otherwise it contains the error code and error message. |
| /// |
| /// # Example |
| /// |
| /// Following is an example |
| /// ```C |
| /// //...prepare your opendal_operator, named op for example |
| /// |
| /// // prepare your data |
| /// char* data = "Hello, World!"; |
| /// opendal_bytes bytes = opendal_bytes { .data = (uint8_t*)data, .len = 13 }; |
| /// opendal_error *error = opendal_operator_write(op, "/testpath", bytes); |
| /// |
| /// assert(error == NULL); |
| /// |
| /// // now you can delete! |
| /// opendal_error *error = opendal_operator_delete(op, "/testpath"); |
| /// |
| /// // Assert that this succeeds |
| /// assert(error == NULL); |
| /// ``` |
| /// |
| /// # 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_delete( |
| op: &opendal_operator, |
| path: *const c_char, |
| ) -> *mut opendal_error { |
| 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), |
| } |
| } |
| |
| /// \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 `is_exist` |
| /// 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_is_exist |
| /// @see opendal_error |
| /// @return Returns opendal_result_is_exist, the `is_exist` field contains whether the path exists. |
| /// However, it the operation fails, the `is_exist` will contain false and the error will be set. |
| /// |
| /// # Example |
| /// |
| /// ```C |
| /// // .. you previously wrote some data to path "/mytest/obj" |
| /// opendal_result_is_exist e = opendal_operator_is_exist(op, "/mytest/obj"); |
| /// assert(e.error == NULL); |
| /// assert(e.is_exist); |
| /// |
| /// // but you previously did **not** write any data to path "/yourtest/obj" |
| /// opendal_result_is_exist e = opendal_operator_is_exist(op, "/yourtest/obj"); |
| /// assert(e.error == NULL); |
| /// assert(!e.is_exist); |
| /// ``` |
| /// |
| /// # 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] |
| #[cfg_attr(cbindgen, cbindgen::ignore)] |
| pub unsafe extern "C" fn opendal_operator_is_exist( |
| op: &opendal_operator, |
| path: *const c_char, |
| ) -> opendal_result_is_exist { |
| 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_is_exist { |
| is_exist: e, |
| error: std::ptr::null_mut(), |
| }, |
| Err(e) => opendal_result_is_exist { |
| is_exist: false, |
| error: opendal_error::new(e), |
| }, |
| } |
| } |
| |
| /// \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. |
| /// |
| /// @param op The opendal_operator created previously |
| /// @param path The path you want to stat |
| /// @see opendal_operator |
| /// @see opendal_result_stat |
| /// @see opendal_metadata |
| /// @return Returns opendal_result_stat, containing a metadata and an opendal_error. |
| /// If the operation succeeds, the `meta` field would hold a valid metadata and |
| /// the `error` field should hold nullptr. Otherwise, the metadata will contain a |
| /// NULL pointer, i.e. invalid, and the `error` will be set correspondingly. |
| /// |
| /// # Example |
| /// |
| /// ```C |
| /// // ... previously you wrote "Hello, World!" to path "/testpath" |
| /// opendal_result_stat s = opendal_operator_stat(op, "/testpath"); |
| /// assert(s.error == NULL); |
| /// |
| /// const opendal_metadata *meta = s.meta; |
| /// |
| /// // ... you could now use your metadata, notice that please only access metadata |
| /// // using the APIs provided by OpenDAL |
| /// ``` |
| /// |
| /// # 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_stat( |
| op: &opendal_operator, |
| path: *const c_char, |
| ) -> opendal_result_stat { |
| 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(), |
| }, |
| Err(e) => opendal_result_stat { |
| meta: std::ptr::null_mut(), |
| error: opendal_error::new(e), |
| }, |
| } |
| } |
| |
| /// \brief Blocking list the objects in `path`. |
| /// |
| /// List the object in `path` blocking by `op_ptr`, return a result with an |
| /// opendal_lister. Users should call opendal_lister_next() on the |
| /// lister. |
| /// |
| /// @param op The opendal_operator created previously |
| /// @param path The designated path you want to list |
| /// @see opendal_lister |
| /// @return Returns opendal_result_list, containing a lister and an opendal_error. |
| /// If the operation succeeds, the `lister` field would hold a valid lister and |
| /// the `error` field should hold nullptr. Otherwise, the `lister`` will contain a |
| /// NULL pointer, i.e. invalid, and the `error` will be set correspondingly. |
| /// |
| /// # Example |
| /// |
| /// Following is an example |
| /// ```C |
| /// // You have written some data into some files path "root/dir1" |
| /// // Your opendal_operator was called op |
| /// opendal_result_list l = opendal_operator_list(op, "root/dir1"); |
| /// assert(l.error == ERROR); |
| /// |
| /// opendal_lister *lister = l.lister; |
| /// opendal_list_entry *entry; |
| /// |
| /// while ((entry = opendal_lister_next(lister)) != NULL) { |
| /// const char* de_path = opendal_list_entry_path(entry); |
| /// const char* de_name = opendal_list_entry_name(entry); |
| /// // ...... your operations |
| /// |
| /// // remember to free the entry after you are done using it |
| /// opendal_list_entry_free(entry); |
| /// } |
| /// |
| /// // and remember to free the lister |
| /// opendal_lister_free(lister); |
| /// ``` |
| /// |
| /// # 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_list( |
| op: &opendal_operator, |
| path: *const c_char, |
| ) -> opendal_result_list { |
| 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(), |
| }, |
| Err(e) => opendal_result_list { |
| lister: std::ptr::null_mut(), |
| error: opendal_error::new(e), |
| }, |
| } |
| } |
| |
| /// \brief Blocking create the directory in `path`. |
| /// |
| /// Create the directory in `path` blocking by `op_ptr`. |
| /// Error is NULL if successful, otherwise it contains the error code and error message. |
| /// |
| /// @param op The opendal_operator created previously |
| /// @param path The designated directory you want to create |
| /// @see opendal_operator |
| /// @see opendal_error |
| /// @return NULL if succeeds, otherwise it contains the error code and error message. |
| /// |
| /// # Example |
| /// |
| /// Following is an example |
| /// ```C |
| /// //...prepare your opendal_operator, named op for example |
| /// |
| /// // create your directory |
| /// opendal_error *error = opendal_operator_create_dir(op, "/testdir/"); |
| /// |
| /// // Assert that this succeeds |
| /// assert(error == NULL); |
| /// ``` |
| /// |
| /// # 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_create_dir( |
| op: &opendal_operator, |
| path: *const c_char, |
| ) -> *mut opendal_error { |
| 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() |
| } |
| } |
| |
| /// \brief Blocking rename the object in `path`. |
| /// |
| /// Rename the object in `src` to `dest` blocking by `op`. |
| /// Error is NULL if successful, otherwise it contains the error code and error message. |
| /// |
| /// @param op The opendal_operator created previously |
| /// @param src The designated source path you want to rename |
| /// @param dest The designated destination path you want to rename |
| /// @see opendal_operator |
| /// @see opendal_error |
| /// @return NULL if succeeds, otherwise it contains the error code and error message. |
| /// |
| /// # Example |
| /// |
| /// Following is an example |
| /// ```C |
| /// //...prepare your opendal_operator, named op for example |
| /// |
| /// // prepare your data |
| /// char* data = "Hello, World!"; |
| /// opendal_bytes bytes = opendal_bytes { .data = (uint8_t*)data, .len = 13 }; |
| /// opendal_error *error = opendal_operator_write(op, "/testpath", bytes); |
| /// |
| /// assert(error == NULL); |
| /// |
| /// // now you can rename! |
| /// opendal_error *error = opendal_operator_rename(op, "/testpath", "/testpath2"); |
| /// |
| /// // Assert that this succeeds |
| /// assert(error == NULL); |
| /// ``` |
| /// |
| /// # 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 `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: &opendal_operator, |
| src: *const c_char, |
| dest: *const c_char, |
| ) -> *mut opendal_error { |
| 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() |
| } |
| } |
| |
| /// \brief Blocking copy the object in `path`. |
| /// |
| /// Copy the object in `src` to `dest` blocking by `op`. |
| /// Error is NULL if successful, otherwise it contains the error code and error message. |
| /// |
| /// @param op The opendal_operator created previously |
| /// @param src The designated source path you want to copy |
| /// @param dest The designated destination path you want to copy |
| /// @see opendal_operator |
| /// @see opendal_error |
| /// @return NULL if succeeds, otherwise it contains the error code and error message. |
| /// |
| /// # Example |
| /// |
| /// Following is an example |
| /// ```C |
| /// //...prepare your opendal_operator, named op for example |
| /// |
| /// // prepare your data |
| /// char* data = "Hello, World!"; |
| /// opendal_bytes bytes = opendal_bytes { .data = (uint8_t*)data, .len = 13 }; |
| /// opendal_error *error = opendal_operator_write(op, "/testpath", bytes); |
| /// |
| /// assert(error == NULL); |
| /// |
| /// // now you can rename! |
| /// opendal_error *error = opendal_operator_copy(op, "/testpath", "/testpath2"); |
| /// |
| /// // Assert that this succeeds |
| /// assert(error == NULL); |
| /// ``` |
| /// |
| /// # 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 `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: &opendal_operator, |
| src: *const c_char, |
| dest: *const c_char, |
| ) -> *mut opendal_error { |
| 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() |
| } |
| } |
| |
| #[no_mangle] |
| pub unsafe extern "C" fn opendal_operator_check(op: &opendal_operator) -> *mut opendal_error { |
| if let Err(err) = op.deref().check() { |
| opendal_error::new(err) |
| } else { |
| std::ptr::null_mut() |
| } |
| } |