blob: 07a04f86bd78f5d305b14ef1b0741d16d579091f [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::model::collector::DataCollector, crate::model::controller::DataController,
std::collections::HashMap, std::sync::Arc,
};
/// `PluginHooks` holds all the collectors and controllers that a plugin needs
/// to operate correctly. These are hooked into the `ControllerDispatcher` and
/// `CollectorScheduler` when `load` is called and removed when `unload` is
/// called.
#[derive(Clone)]
pub struct PluginHooks {
pub collectors: HashMap<String, Arc<dyn DataCollector>>,
pub controllers: HashMap<String, Arc<dyn DataController>>,
}
impl PluginHooks {
pub fn new(
collectors: HashMap<String, Arc<dyn DataCollector>>,
controllers: HashMap<String, Arc<dyn DataController>>,
) -> Self {
Self { collectors: collectors, controllers: controllers }
}
}
// Utility macro to give unique names to each collector for a given plugin.
// This additional naming information is used to make individual controllers
// human readable.
#[macro_export]
macro_rules! collectors {
($($ns:expr => $ctrl:expr,)+) => {collectors!($($ns => $ctrl),+)};
($($ns:expr => $ctrl:expr),*) => {{
let mut _collectors: ::std::collections::HashMap<String,
std::sync::Arc<dyn DataCollector>> = ::std::collections::HashMap::new();
$(
_collectors.insert(String::from($ns), Arc::new($ctrl));
)*
_collectors
}}
}
// Utility macro to generate controller hook mappings from a namespace => constructor
// mapping. It automatically fixes the string type and sets the correct arc, rwlock
// on the controllers provided.
#[macro_export]
macro_rules! controllers {
($($ns:expr => $ctrl:expr,)+) => {controllers!($($ns => $ctrl),+)};
($($ns:expr => $ctrl:expr),*) => {{
let mut _hooks: ::std::collections::HashMap<String,
std::sync::Arc<dyn DataController>> = ::std::collections::HashMap::new();
$(
if $ns.starts_with("/") {
_hooks.insert(format!("/api{}", $ns), Arc::new($ctrl));
} else {
_hooks.insert(format!("/api/{}", $ns), Arc::new($ctrl));
}
)*
_hooks
}}
}
#[cfg(test)]
mod tests {
use {
crate::model::controller::DataController,
crate::model::model::DataModel,
anyhow::Result,
serde_json::{json, value::Value},
std::sync::Arc,
};
#[derive(Default)]
struct FakeController {}
impl DataController for FakeController {
fn query(&self, _: Arc<DataModel>, _: Value) -> Result<Value> {
Ok(json!(null))
}
}
#[test]
fn test_controller_hooks() {
let hooks = controllers! {
"/foo/bar" => FakeController::default(),
"foo/baz" => FakeController::default(),
};
assert_eq!(hooks.contains_key("/api/foo/bar"), true);
assert_eq!(hooks.contains_key("/api/foo/baz"), true);
assert_eq!(hooks.len(), 2);
}
}