1use ockam_core::{
2 errcode::{Kind, Origin},
3 Error,
4};
5use std::ffi::CString;
6use std::os::raw::c_char;
7
8#[repr(C)]
9#[derive(Debug, PartialEq, Eq)]
10pub struct FfiOckamError {
12 code: i32,
13 domain: *const c_char,
14}
15
16impl FfiOckamError {
17 pub fn new(code: i32, domain: &str) -> Self {
19 Self {
20 code,
21 domain: CString::new(domain.as_bytes()).unwrap().into_raw(),
23 }
24 }
25
26 pub fn none() -> Self {
28 Self {
29 code: 0,
30 domain: std::ptr::null(),
31 }
32 }
33}
34
35#[derive(Clone, Copy, Debug)]
37pub enum FfiError {
38 VaultDoesNotSupportPersistence = 1,
40
41 ErrorCreatingFilesystemVault,
43
44 InvalidParam,
46
47 EntryNotFound,
49
50 UnknownPublicKeyType,
52
53 InvalidString,
55
56 BufferTooSmall,
58
59 InvalidPublicKey,
61
62 VaultNotFound,
64
65 OwnershipError,
67
68 UnexpectedPanic,
70}
71impl ockam_core::compat::error::Error for FfiError {}
72impl From<FfiError> for Error {
73 #[track_caller]
74 fn from(err: FfiError) -> Self {
75 Error::new(Origin::Other, Kind::Other, err)
76 }
77}
78impl core::fmt::Display for FfiError {
79 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
80 match self {
81 Self::VaultDoesNotSupportPersistence => write!(
82 f,
83 "persistence is not supported for this Vault implementation."
84 ),
85 Self::ErrorCreatingFilesystemVault => write!(
86 f,
87 "an underlying filesystem error prevented Vault creation."
88 ),
89 Self::InvalidParam => write!(f, "invalid parameter."),
90 Self::EntryNotFound => write!(f, "entry not found."),
91 Self::UnknownPublicKeyType => write!(f, "unknown public key type."),
92 Self::InvalidString => write!(f, "invalid string."),
93 Self::BufferTooSmall => write!(f, "buffer is too small."),
94 Self::InvalidPublicKey => write!(f, "a public key is invalid."),
95 Self::VaultNotFound => write!(f, "no such Vault."),
96 Self::OwnershipError => write!(f, "ownership error."),
97 Self::UnexpectedPanic => write!(
98 f,
99 "caught a panic (which would be UB if we let it unwind across the FFI)."
100 ),
101 }
102 }
103}
104
105impl From<Error> for FfiOckamError {
106 fn from(err: Error) -> Self {
107 Self::new(
108 err.code().origin as i32 * 10_000 + err.code().kind as i32,
109 "unknown",
110 )
111 }
112}
113
114impl From<FfiError> for FfiOckamError {
115 fn from(err: FfiError) -> Self {
116 let err2: Error = err.into();
117 Self::from(err2)
118 }
119}
120
121#[no_mangle]
124pub unsafe extern "C" fn ockam_vault_free_error(context: &mut FfiOckamError) {
125 if !context.domain.is_null() {
126 let _ = CString::from_raw(context.domain as *mut _);
127 context.domain = core::ptr::null();
128 }
129}