#[cfg(feature = "alloc")]
use alloc::boxed::Box;
use core::marker::PhantomData;
use crate::api::CryptoProvider;
use crate::error::Result;
pub trait ContextOps {
fn init(&mut self) -> Result<()>;
fn is_initialized(&self) -> bool;
fn provider(&self) -> Option<&dyn CryptoProvider>;
fn set_provider(&mut self, provider: Box<dyn CryptoProvider>);
}
#[cfg(feature = "alloc")]
pub struct BaseContext<T> {
_phantom: PhantomData<T>,
initialized: bool,
provider: Option<Box<dyn CryptoProvider>>,
}
#[cfg(feature = "alloc")]
impl<T> BaseContext<T> {
pub fn new() -> Self {
Self {
_phantom: PhantomData,
initialized: false,
provider: None,
}
}
pub fn with_provider(provider: Box<dyn CryptoProvider>) -> Self {
Self {
_phantom: PhantomData,
initialized: false,
provider: Some(provider),
}
}
pub fn init(&mut self) -> Result<()> {
if self.initialized {
return Ok(());
}
self.initialized = true;
Ok(())
}
pub fn is_initialized(&self) -> bool {
self.initialized
}
pub fn provider(&self) -> Option<&dyn CryptoProvider> {
self.provider.as_deref()
}
pub fn set_provider(&mut self, provider: Box<dyn CryptoProvider>) {
self.provider = Some(provider);
}
pub fn ensure_initialized(&mut self) -> Result<()> {
if !self.initialized {
self.init()?;
}
Ok(())
}
}
#[cfg(feature = "alloc")]
impl<T> Default for BaseContext<T> {
fn default() -> Self {
Self::new()
}
}
#[cfg(feature = "alloc")]
pub struct ContextBuilder<T> {
provider: Option<Box<dyn CryptoProvider>>,
_phantom: PhantomData<T>,
}
#[cfg(feature = "alloc")]
impl<T> ContextBuilder<T> {
pub fn new() -> Self {
Self {
provider: None,
_phantom: PhantomData,
}
}
pub fn with_provider(mut self, provider: Box<dyn CryptoProvider>) -> Self {
self.provider = Some(provider);
self
}
pub fn build(self) -> BaseContext<T> {
match self.provider {
Some(provider) => BaseContext::with_provider(provider),
None => BaseContext::new(),
}
}
}
#[cfg(feature = "alloc")]
impl<T> Default for ContextBuilder<T> {
fn default() -> Self {
Self::new()
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::api::CryptoProvider;
struct MockProvider;
impl CryptoProvider for MockProvider {
fn kem(&self) -> Option<&dyn crate::api::KemOperations> {
None
}
fn signature(&self) -> Option<&dyn crate::api::SignatureOperations> {
None
}
fn hash(&self) -> Option<&dyn crate::api::HashOperations> {
None
}
fn aead(&self) -> Option<&dyn crate::api::AeadOperations> {
None
}
}
#[test]
fn test_base_context_creation() {
let context = BaseContext::<()>::new();
assert!(!context.is_initialized());
assert!(context.provider().is_none());
}
#[test]
fn test_base_context_with_provider() {
let provider = Box::new(MockProvider);
let context = BaseContext::<()>::with_provider(provider);
assert!(!context.is_initialized());
assert!(context.provider().is_some());
}
#[test]
fn test_base_context_initialization() {
let mut context = BaseContext::<()>::new();
assert!(!context.is_initialized());
let result = context.init();
assert!(result.is_ok());
assert!(context.is_initialized());
let result = context.init();
assert!(result.is_ok());
assert!(context.is_initialized());
}
#[test]
fn test_base_context_provider_management() {
let mut context = BaseContext::<()>::new();
assert!(context.provider().is_none());
let provider = Box::new(MockProvider);
context.set_provider(provider);
assert!(context.provider().is_some());
}
#[test]
fn test_context_builder() {
let provider = Box::new(MockProvider);
let context = ContextBuilder::<()>::new().with_provider(provider).build();
assert!(!context.is_initialized());
assert!(context.provider().is_some());
}
#[test]
fn test_context_builder_default() {
let context = ContextBuilder::<()>::default().build();
assert!(!context.is_initialized());
assert!(context.provider().is_none());
}
#[test]
fn test_ensure_initialized() {
let mut context = BaseContext::<()>::new();
assert!(!context.is_initialized());
let result = context.ensure_initialized();
assert!(result.is_ok());
assert!(context.is_initialized());
let result = context.ensure_initialized();
assert!(result.is_ok());
assert!(context.is_initialized());
}
}