use std::sync::Arc;
use mbedtls_sys::types::raw_types::{c_int, c_uchar, c_void};
use mbedtls_sys::types::size_t;
use mbedtls_sys::*;
use crate::error::{IntoResult, Result};
use crate::rng::{EntropyCallback, EntropyCallbackMut};
callback!(EntropySourceCallbackMut,EntropySourceCallback(data: *mut c_uchar, size: size_t, out: *mut size_t) -> c_int);
define!(
#[c_ty(entropy_context)]
#[repr(C)]
struct OsEntropy {
sources: Vec<Arc<dyn EntropySourceCallback + 'static>>,
};
pub const new: fn() -> Self = entropy_init { sources: Vec::with_capacity(1), };
const drop: fn(&mut Self) = entropy_free;
impl<'a> Into<ptr> {}
);
unsafe impl Sync for OsEntropy {}
#[allow(dead_code)]
impl OsEntropy {
pub fn add_source<F: EntropySourceCallback + 'static>(
&mut self,
source: Arc<F>,
threshold: size_t,
strong: bool,
) -> Result<()> {
unsafe {
entropy_add_source(
self.inner_ffi_mut(),
Some(F::call),
source.data_ptr(),
threshold,
if strong { ENTROPY_SOURCE_STRONG } else { ENTROPY_SOURCE_WEAK },
)
.into_result()?
};
self.sources.push(source);
Ok(())
}
pub fn gather(&self) -> Result<()> {
unsafe { entropy_gather(self.inner_ffi_mut()) }.into_result()?;
Ok(())
}
pub fn update_manual(&self, data: &[u8]) -> Result<()> {
unsafe { entropy_update_manual(self.inner_ffi_mut(), data.as_ptr(), data.len()) }.into_result()?;
Ok(())
}
}
impl EntropyCallback for OsEntropy {
#[inline(always)]
unsafe extern "C" fn call(user_data: *mut c_void, data: *mut c_uchar, len: size_t) -> c_int {
entropy_func(user_data, data, len)
}
fn data_ptr(&self) -> *mut c_void {
&self.inner as *const _ as *mut _
}
}
impl EntropyCallbackMut for OsEntropy {
#[inline(always)]
unsafe extern "C" fn call_mut(user_data: *mut c_void, data: *mut c_uchar, len: size_t) -> c_int {
entropy_func(user_data, data, len)
}
fn data_ptr_mut(&mut self) -> *mut c_void {
&self.inner as *const _ as *mut _
}
}