blob: 87d1df14314a27ece928112588750e505e2b36e8 [file] [log] [blame]
// Copyright 2020 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
use crate::base::SettingType;
use crate::handler::device_storage::DeviceStorageFactory;
use crate::policy::{
BoxedHandler, Context, GenerateHandler, PolicyHandlerFactory, PolicyHandlerFactoryError,
PolicyType,
};
use crate::service;
use async_trait::async_trait;
use std::collections::HashMap;
use std::collections::HashSet;
use std::sync::atomic::{AtomicU64, Ordering};
use std::sync::Arc;
/// PolicyHandlerFactoryImpl houses registered closures for generating setting
/// handlers.
pub struct PolicyHandlerFactoryImpl<T: DeviceStorageFactory + Send + Sync> {
policies: HashSet<PolicyType>,
settings: HashSet<SettingType>,
storage_factory: Arc<T>,
generators: HashMap<PolicyType, GenerateHandler<T>>,
/// Atomic counter used to generate new IDs, which uniquely identify a context.
context_id_counter: Arc<AtomicU64>,
}
#[async_trait]
impl<T: DeviceStorageFactory + Send + Sync> PolicyHandlerFactory for PolicyHandlerFactoryImpl<T> {
async fn generate(
&mut self,
policy_type: PolicyType,
service_messenger: service::message::Messenger,
) -> Result<BoxedHandler, PolicyHandlerFactoryError> {
let setting_type = policy_type.setting_type();
if !self.policies.contains(&policy_type) {
return Err(PolicyHandlerFactoryError::PolicyNotFound(policy_type));
}
if !self.settings.contains(&setting_type) {
return Err(PolicyHandlerFactoryError::SettingNotFound(setting_type, policy_type));
}
let generate_function = self
.generators
.get(&policy_type)
.ok_or(PolicyHandlerFactoryError::GeneratorNotFound(policy_type))?;
let context = Context {
policy_type,
service_messenger,
storage_factory: self.storage_factory.clone(),
id: self.context_id_counter.fetch_add(1, Ordering::Relaxed),
};
let handler = (generate_function)(context)
.await
.map_err(|_| PolicyHandlerFactoryError::HandlerStartupError(policy_type))?;
return Ok(handler);
}
}
impl<T: DeviceStorageFactory + Send + Sync> PolicyHandlerFactoryImpl<T> {
pub fn new(
policies: HashSet<PolicyType>,
settings: HashSet<SettingType>,
storage_factory: Arc<T>,
context_id_counter: Arc<AtomicU64>,
) -> PolicyHandlerFactoryImpl<T> {
PolicyHandlerFactoryImpl {
policies,
settings,
storage_factory,
generators: HashMap::new(),
context_id_counter,
}
}
pub fn register(&mut self, policy_type: PolicyType, generate_function: GenerateHandler<T>) {
self.generators.insert(policy_type, generate_function);
}
}