blob: 97388ddfe24073a263a0a61984cf1a73c15adc76 [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 ::opendal as core;
use opendal::Buffer;
use crate::types::opendal_bytes;
/// \brief The error code for all opendal APIs in C binding.
/// \todo The error handling is not complete, the error with error message will be
/// added in the future.
#[repr(C)]
pub enum opendal_code {
/// returning it back. For example, s3 returns an internal service error.
OPENDAL_UNEXPECTED,
/// Underlying service doesn't support this operation.
OPENDAL_UNSUPPORTED,
/// The config for backend is invalid.
OPENDAL_CONFIG_INVALID,
/// The given path is not found.
OPENDAL_NOT_FOUND,
/// The given path doesn't have enough permission for this operation
OPENDAL_PERMISSION_DENIED,
/// The given path is a directory.
OPENDAL_IS_A_DIRECTORY,
/// The given path is not a directory.
OPENDAL_NOT_A_DIRECTORY,
/// The given path already exists thus we failed to the specified operation on it.
OPENDAL_ALREADY_EXISTS,
/// Requests that sent to this path is over the limit, please slow down.
OPENDAL_RATE_LIMITED,
/// The given file paths are same.
OPENDAL_IS_SAME_FILE,
/// The condition of this operation is not match.
OPENDAL_CONDITION_NOT_MATCH,
/// The range of the content is not satisfied.
OPENDAL_RANGE_NOT_SATISFIED,
}
impl From<core::ErrorKind> for opendal_code {
fn from(value: core::ErrorKind) -> Self {
match value {
core::ErrorKind::Unexpected => opendal_code::OPENDAL_UNEXPECTED,
core::ErrorKind::Unsupported => opendal_code::OPENDAL_UNSUPPORTED,
core::ErrorKind::ConfigInvalid => opendal_code::OPENDAL_CONFIG_INVALID,
core::ErrorKind::NotFound => opendal_code::OPENDAL_NOT_FOUND,
core::ErrorKind::PermissionDenied => opendal_code::OPENDAL_PERMISSION_DENIED,
core::ErrorKind::IsADirectory => opendal_code::OPENDAL_IS_A_DIRECTORY,
core::ErrorKind::NotADirectory => opendal_code::OPENDAL_NOT_A_DIRECTORY,
core::ErrorKind::AlreadyExists => opendal_code::OPENDAL_ALREADY_EXISTS,
core::ErrorKind::RateLimited => opendal_code::OPENDAL_RATE_LIMITED,
core::ErrorKind::IsSameFile => opendal_code::OPENDAL_IS_SAME_FILE,
core::ErrorKind::ConditionNotMatch => opendal_code::OPENDAL_CONDITION_NOT_MATCH,
core::ErrorKind::RangeNotSatisfied => opendal_code::OPENDAL_RANGE_NOT_SATISFIED,
// if this is triggered, check the [`core`] crate and add a
// new error code accordingly
_ => unimplemented!(
"The newly added ErrorKind in core crate is not handled in C bindings"
),
}
}
}
/// \brief The opendal error type for C binding, containing an error code and corresponding error
/// message.
///
/// The normal operations returns a pointer to the opendal_error, and the **nullptr normally
/// represents no error has taken placed**. If any error has taken place, the caller should check
/// the error code and print the error message.
///
/// The error code is represented in opendal_code, which is an enum on different type of errors.
/// The error messages is represented in opendal_bytes, which is a non-null terminated byte array.
///
/// \note 1. The error message is on heap, so the error needs to be freed by the caller, by calling
/// opendal_error_free. 2. The error message is not null terminated, so the caller should
/// never use "%s" to print the error message.
///
/// @see opendal_code
/// @see opendal_bytes
/// @see opendal_error_free
#[repr(C)]
pub struct opendal_error {
code: opendal_code,
message: opendal_bytes,
}
impl opendal_error {
/// Create a new opendal error via `core::Error`.
///
/// We will call `Box::leak()` to leak this error, so the caller should be responsible for
/// free this error.
pub fn new(err: core::Error) -> *mut opendal_error {
let code = opendal_code::from(err.kind());
let message = opendal_bytes::new(Buffer::from(err.to_string()));
Box::into_raw(Box::new(opendal_error { code, message }))
}
/// \brief Frees the opendal_error, ok to call on NULL
#[no_mangle]
pub unsafe extern "C" fn opendal_error_free(ptr: *mut opendal_error) {
if !ptr.is_null() {
drop(Box::from_raw(ptr));
}
}
}