use std::ffi::c_void;
use anyhow::Result;
use async_trait::async_trait;
use drasi_lib::identity::{Credentials, IdentityProvider};
use super::identity::IdentityProviderVtable;
pub struct FfiIdentityProviderProxy {
vtable: *const IdentityProviderVtable,
}
unsafe impl Send for FfiIdentityProviderProxy {}
unsafe impl Sync for FfiIdentityProviderProxy {}
impl FfiIdentityProviderProxy {
pub unsafe fn new(vtable: *const IdentityProviderVtable) -> Self {
Self { vtable }
}
}
#[async_trait]
impl IdentityProvider for FfiIdentityProviderProxy {
async fn get_credentials(&self) -> Result<Credentials> {
let vtable = unsafe { &*self.vtable };
let result = (vtable.get_credentials_fn)(vtable.state);
unsafe { result.into_result() }
}
fn clone_box(&self) -> Box<dyn IdentityProvider> {
let vtable = unsafe { &*self.vtable };
let cloned_state = (vtable.clone_fn)(vtable.state);
let cloned_vtable = Box::new(IdentityProviderVtable {
state: cloned_state,
get_credentials_fn: vtable.get_credentials_fn,
clone_fn: vtable.clone_fn,
drop_fn: vtable.drop_fn,
});
Box::new(FfiIdentityProviderProxy {
vtable: Box::into_raw(cloned_vtable),
})
}
}
impl Drop for FfiIdentityProviderProxy {
fn drop(&mut self) {
if !self.vtable.is_null() {
let vtable = unsafe { &*self.vtable };
(vtable.drop_fn)(vtable.state);
}
}
}