use std::ffi::c_void;
use super::types::{FfiResult, FfiStr};
#[repr(C)]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum FfiCredentialType {
UsernamePassword = 0,
Token = 1,
Certificate = 2,
}
#[repr(C)]
pub struct FfiCredentials {
pub credential_type: FfiCredentialType,
pub field1: *mut std::os::raw::c_char,
pub field2: *mut std::os::raw::c_char,
pub field3: *mut std::os::raw::c_char,
}
#[repr(C)]
pub struct FfiCredentialsResult {
pub error_code: i32,
pub error_msg: *mut std::os::raw::c_char,
pub credentials: FfiCredentials,
}
#[repr(C)]
pub struct IdentityProviderVtable {
pub state: *mut c_void,
pub get_credentials_fn: extern "C" fn(state: *const c_void) -> FfiCredentialsResult,
pub clone_fn: extern "C" fn(state: *const c_void) -> *mut c_void,
pub drop_fn: extern "C" fn(state: *mut c_void),
}
unsafe impl Send for IdentityProviderVtable {}
unsafe impl Sync for IdentityProviderVtable {}
impl FfiCredentials {
pub unsafe fn into_credentials(self) -> drasi_lib::identity::Credentials {
let field1 = if self.field1.is_null() {
String::new()
} else {
let s = std::ffi::CStr::from_ptr(self.field1)
.to_string_lossy()
.into_owned();
libc_free(self.field1 as *mut c_void);
s
};
let field2 = if self.field2.is_null() {
String::new()
} else {
let s = std::ffi::CStr::from_ptr(self.field2)
.to_string_lossy()
.into_owned();
libc_free(self.field2 as *mut c_void);
s
};
let field3 = if self.field3.is_null() {
None
} else {
let s = std::ffi::CStr::from_ptr(self.field3)
.to_string_lossy()
.into_owned();
libc_free(self.field3 as *mut c_void);
Some(s)
};
match self.credential_type {
FfiCredentialType::UsernamePassword => {
drasi_lib::identity::Credentials::UsernamePassword {
username: field1,
password: field2,
}
}
FfiCredentialType::Token => drasi_lib::identity::Credentials::Token {
username: field1,
token: field2,
},
FfiCredentialType::Certificate => drasi_lib::identity::Credentials::Certificate {
cert_pem: field1,
key_pem: field2,
username: field3,
},
}
}
}
impl FfiCredentialsResult {
pub fn ok(credentials: FfiCredentials) -> Self {
Self {
error_code: 0,
error_msg: std::ptr::null_mut(),
credentials,
}
}
pub fn err(msg: String) -> Self {
let c_msg = std::ffi::CString::new(msg).unwrap_or_default();
Self {
error_code: 1,
error_msg: c_msg.into_raw(),
credentials: FfiCredentials {
credential_type: FfiCredentialType::UsernamePassword,
field1: std::ptr::null_mut(),
field2: std::ptr::null_mut(),
field3: std::ptr::null_mut(),
},
}
}
pub unsafe fn into_result(self) -> anyhow::Result<drasi_lib::identity::Credentials> {
if self.error_code == 0 {
Ok(self.credentials.into_credentials())
} else {
let msg = if self.error_msg.is_null() {
"Unknown error".to_string()
} else {
let s = std::ffi::CStr::from_ptr(self.error_msg)
.to_string_lossy()
.into_owned();
libc_free(self.error_msg as *mut c_void);
s
};
Err(anyhow::anyhow!(msg))
}
}
}
unsafe fn libc_free(ptr: *mut c_void) {
if !ptr.is_null() {
drop(std::ffi::CString::from_raw(
ptr as *mut std::os::raw::c_char,
));
}
}
pub fn credentials_to_ffi(creds: drasi_lib::identity::Credentials) -> FfiCredentials {
match creds {
drasi_lib::identity::Credentials::UsernamePassword { username, password } => {
FfiCredentials {
credential_type: FfiCredentialType::UsernamePassword,
field1: std::ffi::CString::new(username)
.unwrap_or_default()
.into_raw(),
field2: std::ffi::CString::new(password)
.unwrap_or_default()
.into_raw(),
field3: std::ptr::null_mut(),
}
}
drasi_lib::identity::Credentials::Token { username, token } => FfiCredentials {
credential_type: FfiCredentialType::Token,
field1: std::ffi::CString::new(username)
.unwrap_or_default()
.into_raw(),
field2: std::ffi::CString::new(token).unwrap_or_default().into_raw(),
field3: std::ptr::null_mut(),
},
drasi_lib::identity::Credentials::Certificate {
cert_pem,
key_pem,
username,
} => FfiCredentials {
credential_type: FfiCredentialType::Certificate,
field1: std::ffi::CString::new(cert_pem)
.unwrap_or_default()
.into_raw(),
field2: std::ffi::CString::new(key_pem)
.unwrap_or_default()
.into_raw(),
field3: username
.map(|u| std::ffi::CString::new(u).unwrap_or_default().into_raw())
.unwrap_or(std::ptr::null_mut()),
},
}
}