blob: cba8f254006357bb9fbd7cac8a4f8015b82f3387 [file] [log] [blame]
// 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 opendal::Buffer;
/// \brief opendal_bytes carries raw-bytes with its length
///
/// The opendal_bytes type is a C-compatible substitute for Vec type
/// in Rust, it has to be manually freed. You have to call opendal_bytes_free()
/// to free the heap memory to avoid memory leak.
///
/// @see opendal_bytes_free
#[repr(C)]
pub struct opendal_bytes {
/// Pointing to the byte array on heap
pub data: *mut u8,
/// The length of the byte array
pub len: usize,
/// The capacity of the byte array
pub capacity: usize,
}
impl opendal_bytes {
pub(crate) fn empty() -> Self {
Self {
data: std::ptr::null_mut(),
len: 0,
capacity: 0,
}
}
/// Construct a [`opendal_bytes`] from the Rust [`Vec`] of bytes
pub(crate) fn new(b: Buffer) -> Self {
let mut b = std::mem::ManuallyDrop::new(b.to_vec());
Self {
data: b.as_mut_ptr(),
len: b.len(),
capacity: b.capacity(),
}
}
/// \brief Frees the heap memory used by the opendal_bytes
#[no_mangle]
pub unsafe extern "C" fn opendal_bytes_free(ptr: *mut opendal_bytes) {
if !ptr.is_null() {
let bs = &mut *ptr;
if !bs.data.is_null() {
drop(Vec::from_raw_parts(bs.data, bs.len, bs.capacity));
bs.data = std::ptr::null_mut();
bs.len = 0;
bs.capacity = 0;
}
}
}
}
impl Drop for opendal_bytes {
fn drop(&mut self) {
unsafe {
// Safety: the pointer is always valid
Self::opendal_bytes_free(self);
}
}
}
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))
}
}
/// \brief The configuration for the initialization of opendal_operator.
///
/// \note This is also a heap-allocated struct, please free it after you use it
///
/// @see opendal_operator_new has an example of using opendal_operator_options
/// @see opendal_operator_options_new This function construct the operator
/// @see opendal_operator_options_free This function frees the heap memory of the operator
/// @see opendal_operator_options_set This function allow you to set the options
#[repr(C)]
pub struct opendal_operator_options {
/// The pointer to the HashMap<String, String> in the Rust code.
/// Only touch this on judging whether it is NULL.
inner: *mut c_void,
}
impl opendal_operator_options {
pub(crate) fn deref(&self) -> &HashMap<String, String> {
// Safety: the inner should never be null once constructed
// The use-after-free is undefined behavior
unsafe { &*(self.inner as *mut HashMap<String, String>) }
}
pub(crate) fn deref_mut(&mut self) -> &mut HashMap<String, String> {
// Safety: the inner should never be null once constructed
// The use-after-free is undefined behavior
unsafe { &mut *(self.inner as *mut HashMap<String, String>) }
}
}
impl opendal_operator_options {
/// \brief Construct a heap-allocated opendal_operator_options
///
/// @return An empty opendal_operator_option, which could be set by
/// opendal_operator_option_set().
///
/// @see opendal_operator_option_set
#[no_mangle]
pub extern "C" fn opendal_operator_options_new() -> *mut Self {
let map: HashMap<String, String> = HashMap::default();
let options = Self {
inner: Box::into_raw(Box::new(map)) as _,
};
Box::into_raw(Box::new(options))
}
/// \brief Set a Key-Value pair inside opendal_operator_options
///
/// # Safety
///
/// This function is unsafe because it dereferences and casts the raw pointers
/// Make sure the pointer of `key` and `value` point to a valid string.
///
/// # Example
///
/// ```C
/// opendal_operator_options *options = opendal_operator_options_new();
/// opendal_operator_options_set(options, "root", "/myroot");
///
/// // .. use your opendal_operator_options
///
/// opendal_operator_options_free(options);
/// ```
#[no_mangle]
pub unsafe extern "C" fn opendal_operator_options_set(
&mut self,
key: *const c_char,
value: *const c_char,
) {
let k = unsafe { std::ffi::CStr::from_ptr(key) }
.to_str()
.unwrap()
.to_string();
let v = unsafe { std::ffi::CStr::from_ptr(value) }
.to_str()
.unwrap()
.to_string();
self.deref_mut().insert(k, v);
}
/// \brief Free the allocated memory used by [`opendal_operator_options`]
#[no_mangle]
pub unsafe extern "C" fn opendal_operator_options_free(ptr: *mut opendal_operator_options) {
if !ptr.is_null() {
drop(Box::from_raw((*ptr).inner as *mut HashMap<String, String>));
drop(Box::from_raw(ptr));
}
}
}