use super::Provide;
use parsec_interface::operations::ProviderInfo;
use parsec_interface::operations::{OpListOpcodes, ResultListOpcodes};
use parsec_interface::operations::{OpListProviders, ResultListProviders};
use parsec_interface::operations::{OpPing, ResultPing};
use parsec_interface::requests::{Opcode, ProviderID, Result};
use std::io::{Error, ErrorKind};
use uuid::Uuid;
const SUPPORTED_OPCODES: [Opcode; 3] = [Opcode::ListProviders, Opcode::ListOpcodes, Opcode::Ping];
#[derive(Debug)]
pub struct CoreProvider {
version_min: u8,
version_maj: u8,
providers: Vec<ProviderInfo>,
}
impl Provide for CoreProvider {
fn list_opcodes(&self, _op: OpListOpcodes) -> Result<ResultListOpcodes> {
Ok(ResultListOpcodes {
opcodes: SUPPORTED_OPCODES.iter().copied().collect(),
})
}
fn list_providers(&self, _op: OpListProviders) -> Result<ResultListProviders> {
Ok(ResultListProviders {
providers: self.providers.clone(),
})
}
fn describe(&self) -> ProviderInfo {
ProviderInfo {
uuid: Uuid::parse_str("47049873-2a43-4845-9d72-831eab668784").unwrap(),
description: String::from("Software provider that implements only administrative (i.e. no cryptographic) operations"),
vendor: String::new(),
version_maj: 0,
version_min: 1,
version_rev: 0,
id: ProviderID::CoreProvider,
}
}
fn ping(&self, _op: OpPing) -> Result<ResultPing> {
let result = ResultPing {
supp_version_maj: self.version_maj,
supp_version_min: self.version_min,
};
Ok(result)
}
}
#[derive(Debug, Default)]
pub struct CoreProviderBuilder {
version_maj: Option<u8>,
version_min: Option<u8>,
providers: Option<Vec<ProviderInfo>>,
}
impl CoreProviderBuilder {
pub fn new() -> Self {
CoreProviderBuilder {
version_maj: None,
version_min: None,
providers: None,
}
}
pub fn with_version(mut self, version_min: u8, version_maj: u8) -> Self {
self.version_maj = Some(version_maj);
self.version_min = Some(version_min);
self
}
pub fn with_provider_info(mut self, provider_info: ProviderInfo) -> Self {
match self.providers {
Some(mut providers) => {
providers.push(provider_info);
self.providers = Some(providers);
}
None => {
let mut providers = Vec::new();
providers.push(provider_info);
self.providers = Some(providers);
}
}
self
}
pub fn build(self) -> std::io::Result<CoreProvider> {
let mut core_provider = CoreProvider {
version_maj: self
.version_maj
.ok_or_else(|| Error::new(ErrorKind::InvalidData, "version maj is missing"))?,
version_min: self
.version_min
.ok_or_else(|| Error::new(ErrorKind::InvalidData, "version min is missing"))?,
providers: self
.providers
.ok_or_else(|| Error::new(ErrorKind::InvalidData, "provider info is missing"))?,
};
core_provider.providers.push(core_provider.describe());
Ok(core_provider)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_ping() {
let provider = CoreProvider {
version_min: 8,
version_maj: 10,
providers: Vec::new(),
};
let op = OpPing {};
let result = provider.ping(op).unwrap();
assert_eq!(result.supp_version_maj, provider.version_maj);
assert_eq!(result.supp_version_min, provider.version_min);
}
}