blob: d3e8c2678d88031f97e562a44b3c4839e2a7ed03 [file]
// 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.
#[repr(C)]
/// FFI-safe representation of a Rust `Vec<u8>` buffer.
///
/// The buffer ownership is transferred to the caller and must be released by
/// calling `opendal_read_result_release` exactly once.
pub struct ByteBuffer {
/// Pointer to the start of the allocated bytes.
pub data: *mut u8,
/// Number of initialized bytes.
pub len: usize,
/// Total allocated capacity in bytes.
pub capacity: usize,
}
impl ByteBuffer {
/// Create an empty buffer that does not own any allocation.
pub fn empty() -> Self {
Self {
data: std::ptr::null_mut(),
len: 0,
capacity: 0,
}
}
/// Convert a vector into a raw FFI buffer without copying.
///
/// The returned memory must be released by the C# side via
/// `opendal_read_result_release`.
pub fn from_vec(mut value: Vec<u8>) -> Self {
if value.is_empty() {
return Self::empty();
}
let data = value.as_mut_ptr();
let len = value.len();
let capacity = value.capacity();
std::mem::forget(value);
Self {
data,
len,
capacity,
}
}
}
/// # Safety
///
/// - `data`, `len`, and `capacity` must come from `ByteBuffer::from_vec`.
/// - This function must be called at most once for the same allocation.
/// - Callers must not access `data` after this function returns.
pub unsafe fn buffer_free(data: *mut u8, len: usize, capacity: usize) {
if data.is_null() {
debug_assert_eq!(len, 0, "len must be zero when data is null");
debug_assert_eq!(capacity, 0, "capacity must be zero when data is null");
return;
}
if capacity == 0 {
debug_assert!(
capacity > 0,
"capacity must be greater than zero when data is not null"
);
return;
}
if capacity < len {
debug_assert!(
capacity >= len,
"capacity must be greater than or equal to len"
);
return;
}
unsafe {
drop(Vec::from_raw_parts(data, len, capacity));
}
}