192f3ab15Sopenharmony_ciuse crate::error::ErrorStack;
292f3ab15Sopenharmony_ciuse crate::lib_ctx::LibCtxRef;
392f3ab15Sopenharmony_ciuse crate::{cvt, cvt_p};
492f3ab15Sopenharmony_ciuse foreign_types::{ForeignType, ForeignTypeRef};
592f3ab15Sopenharmony_ciuse openssl_macros::corresponds;
692f3ab15Sopenharmony_ciuse std::ffi::CString;
792f3ab15Sopenharmony_ciuse std::ptr;
892f3ab15Sopenharmony_ci
992f3ab15Sopenharmony_ciforeign_type_and_impl_send_sync! {
1092f3ab15Sopenharmony_ci    type CType = ffi::OSSL_PROVIDER;
1192f3ab15Sopenharmony_ci    fn drop = ossl_provider_free;
1292f3ab15Sopenharmony_ci
1392f3ab15Sopenharmony_ci    pub struct Provider;
1492f3ab15Sopenharmony_ci    /// A reference to a [`Provider`].
1592f3ab15Sopenharmony_ci    pub struct ProviderRef;
1692f3ab15Sopenharmony_ci}
1792f3ab15Sopenharmony_ci
1892f3ab15Sopenharmony_ci#[inline]
1992f3ab15Sopenharmony_ciunsafe fn ossl_provider_free(p: *mut ffi::OSSL_PROVIDER) {
2092f3ab15Sopenharmony_ci    ffi::OSSL_PROVIDER_unload(p);
2192f3ab15Sopenharmony_ci}
2292f3ab15Sopenharmony_ci
2392f3ab15Sopenharmony_ciimpl Provider {
2492f3ab15Sopenharmony_ci    /// Loads a new provider into the specified library context, disabling the fallback providers.
2592f3ab15Sopenharmony_ci    ///
2692f3ab15Sopenharmony_ci    /// If `ctx` is `None`, the provider will be loaded in to the default library context.
2792f3ab15Sopenharmony_ci    #[corresponds(OSSL_provider_load)]
2892f3ab15Sopenharmony_ci    pub fn load(ctx: Option<&LibCtxRef>, name: &str) -> Result<Self, ErrorStack> {
2992f3ab15Sopenharmony_ci        let name = CString::new(name).unwrap();
3092f3ab15Sopenharmony_ci        unsafe {
3192f3ab15Sopenharmony_ci            let p = cvt_p(ffi::OSSL_PROVIDER_load(
3292f3ab15Sopenharmony_ci                ctx.map_or(ptr::null_mut(), ForeignTypeRef::as_ptr),
3392f3ab15Sopenharmony_ci                name.as_ptr(),
3492f3ab15Sopenharmony_ci            ))?;
3592f3ab15Sopenharmony_ci
3692f3ab15Sopenharmony_ci            Ok(Provider::from_ptr(p))
3792f3ab15Sopenharmony_ci        }
3892f3ab15Sopenharmony_ci    }
3992f3ab15Sopenharmony_ci
4092f3ab15Sopenharmony_ci    /// Loads a new provider into the specified library context, disabling the fallback providers if `retain_fallbacks`
4192f3ab15Sopenharmony_ci    /// is `false` and the load succeeds.
4292f3ab15Sopenharmony_ci    ///
4392f3ab15Sopenharmony_ci    /// If `ctx` is `None`, the provider will be loaded into the default library context.
4492f3ab15Sopenharmony_ci    #[corresponds(OSSL_provider_try_load)]
4592f3ab15Sopenharmony_ci    pub fn try_load(
4692f3ab15Sopenharmony_ci        ctx: Option<&LibCtxRef>,
4792f3ab15Sopenharmony_ci        name: &str,
4892f3ab15Sopenharmony_ci        retain_fallbacks: bool,
4992f3ab15Sopenharmony_ci    ) -> Result<Self, ErrorStack> {
5092f3ab15Sopenharmony_ci        let name = CString::new(name).unwrap();
5192f3ab15Sopenharmony_ci        unsafe {
5292f3ab15Sopenharmony_ci            let p = cvt_p(ffi::OSSL_PROVIDER_try_load(
5392f3ab15Sopenharmony_ci                ctx.map_or(ptr::null_mut(), ForeignTypeRef::as_ptr),
5492f3ab15Sopenharmony_ci                name.as_ptr(),
5592f3ab15Sopenharmony_ci                retain_fallbacks as _,
5692f3ab15Sopenharmony_ci            ))?;
5792f3ab15Sopenharmony_ci
5892f3ab15Sopenharmony_ci            Ok(Provider::from_ptr(p))
5992f3ab15Sopenharmony_ci        }
6092f3ab15Sopenharmony_ci    }
6192f3ab15Sopenharmony_ci
6292f3ab15Sopenharmony_ci    /// Specifies the default search path that is to be used for looking for providers in the specified library context.
6392f3ab15Sopenharmony_ci    /// If left unspecified, an environment variable and a fall back default value will be used instead
6492f3ab15Sopenharmony_ci    ///
6592f3ab15Sopenharmony_ci    /// If `ctx` is `None`, the provider will be loaded into the default library context.
6692f3ab15Sopenharmony_ci    #[corresponds(OSSL_PROVIDER_set_default_search_path)]
6792f3ab15Sopenharmony_ci    pub fn set_default_search_path(ctx: Option<&LibCtxRef>, path: &str) -> Result<(), ErrorStack> {
6892f3ab15Sopenharmony_ci        let path = CString::new(path).unwrap();
6992f3ab15Sopenharmony_ci        unsafe {
7092f3ab15Sopenharmony_ci            cvt(ffi::OSSL_PROVIDER_set_default_search_path(
7192f3ab15Sopenharmony_ci                ctx.map_or(ptr::null_mut(), ForeignTypeRef::as_ptr),
7292f3ab15Sopenharmony_ci                path.as_ptr(),
7392f3ab15Sopenharmony_ci            ))
7492f3ab15Sopenharmony_ci            .map(|_| ())
7592f3ab15Sopenharmony_ci        }
7692f3ab15Sopenharmony_ci    }
7792f3ab15Sopenharmony_ci}
78