use crate::error::ErrorStack;
use native_ossl_sys as sys;
#[derive(Debug)]
pub struct LibCtx {
ptr: *mut sys::OSSL_LIB_CTX,
owned: bool,
}
impl LibCtx {
pub fn new() -> Result<Self, ErrorStack> {
let ptr = unsafe { sys::OSSL_LIB_CTX_new() };
if ptr.is_null() {
return Err(ErrorStack::drain());
}
Ok(LibCtx { ptr, owned: true })
}
pub fn load_provider(&self, name: &std::ffi::CStr) -> Result<Provider, ErrorStack> {
let ptr = unsafe { sys::OSSL_PROVIDER_load(self.ptr, name.as_ptr()) };
if ptr.is_null() {
return Err(ErrorStack::drain());
}
Ok(Provider { ptr })
}
#[must_use]
pub fn as_ptr(&self) -> *mut sys::OSSL_LIB_CTX {
self.ptr
}
pub unsafe fn from_raw_unowned(ptr: *mut sys::OSSL_LIB_CTX) -> Self {
LibCtx { ptr, owned: false }
}
}
impl Drop for LibCtx {
fn drop(&mut self) {
if self.owned {
unsafe { sys::OSSL_LIB_CTX_free(self.ptr) };
}
}
}
unsafe impl Send for LibCtx {}
unsafe impl Sync for LibCtx {}
pub struct Provider {
ptr: *mut sys::OSSL_PROVIDER,
}
impl Drop for Provider {
fn drop(&mut self) {
unsafe { sys::OSSL_PROVIDER_unload(self.ptr) };
}
}
unsafe impl Send for Provider {}
unsafe impl Sync for Provider {}
#[cfg(test)]
mod tests {
use super::*;
use std::sync::Arc;
#[test]
fn create_and_drop() {
let ctx = LibCtx::new().unwrap();
drop(ctx);
}
#[test]
fn load_default_provider() {
let ctx = LibCtx::new().unwrap();
let _prov = ctx.load_provider(c"default").unwrap();
}
#[test]
fn arc_shared_context() {
let ctx = Arc::new(LibCtx::new().unwrap());
let _prov = ctx.load_provider(c"default").unwrap();
let ctx2 = Arc::clone(&ctx);
drop(ctx);
drop(ctx2);
}
}