use ockam_core::{
errcode::{Kind, Origin},
Error,
};
use std::ffi::CString;
use std::os::raw::c_char;
#[repr(C)]
#[derive(Debug, PartialEq, Eq)]
pub struct FfiOckamError {
code: i32,
domain: *const c_char,
}
impl FfiOckamError {
pub fn new(code: i32, domain: &str) -> Self {
Self {
code,
domain: CString::new(domain.as_bytes()).unwrap().into_raw(),
}
}
pub fn none() -> Self {
Self {
code: 0,
domain: std::ptr::null(),
}
}
}
#[derive(Clone, Copy, Debug)]
pub enum FfiError {
VaultDoesNotSupportPersistence = 1,
ErrorCreatingFilesystemVault,
InvalidParam,
EntryNotFound,
UnknownPublicKeyType,
InvalidString,
BufferTooSmall,
InvalidPublicKey,
VaultNotFound,
OwnershipError,
UnexpectedPanic,
}
impl ockam_core::compat::error::Error for FfiError {}
impl From<FfiError> for Error {
#[track_caller]
fn from(err: FfiError) -> Self {
Error::new(Origin::Other, Kind::Other, err)
}
}
impl core::fmt::Display for FfiError {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
match self {
Self::VaultDoesNotSupportPersistence => write!(
f,
"persistence is not supported for this Vault implementation."
),
Self::ErrorCreatingFilesystemVault => write!(
f,
"an underlying filesystem error prevented Vault creation."
),
Self::InvalidParam => write!(f, "invalid parameter."),
Self::EntryNotFound => write!(f, "entry not found."),
Self::UnknownPublicKeyType => write!(f, "unknown public key type."),
Self::InvalidString => write!(f, "invalid string."),
Self::BufferTooSmall => write!(f, "buffer is too small."),
Self::InvalidPublicKey => write!(f, "a public key is invalid."),
Self::VaultNotFound => write!(f, "no such Vault."),
Self::OwnershipError => write!(f, "ownership error."),
Self::UnexpectedPanic => write!(
f,
"caught a panic (which would be UB if we let it unwind across the FFI)."
),
}
}
}
impl From<Error> for FfiOckamError {
fn from(err: Error) -> Self {
Self::new(
err.code().origin as i32 * 10_000 + err.code().kind as i32,
"unknown",
)
}
}
impl From<FfiError> for FfiOckamError {
fn from(err: FfiError) -> Self {
let err2: Error = err.into();
Self::from(err2)
}
}
#[no_mangle]
pub unsafe extern "C" fn ockam_vault_free_error(context: &mut FfiOckamError) {
if !context.domain.is_null() {
let _ = CString::from_raw(context.domain as *mut _);
context.domain = core::ptr::null();
}
}