use crate::export::{Export, Result};
use crate::path::Path;
use crate::sensor_id::SensorId;
use std::any::Any;
use std::collections::HashMap;
use std::rc::Rc;
use std::str::FromStr;
pub type LocalSensors = HashMap<SensorId, Rc<Box<dyn Any>>>;
pub type NbrSensors = HashMap<SensorId, HashMap<i32, Rc<Box<dyn Any>>>>;
pub type Exports = HashMap<i32, Export>;
#[derive(Debug, Clone)]
pub struct Context {
self_id: i32,
local_sensor: LocalSensors,
nbr_sensor: NbrSensors,
exports: Exports,
}
impl Context {
pub fn new(
self_id: i32,
local_sensor: LocalSensors,
nbr_sensor: NbrSensors,
exports: Exports,
) -> Self {
Self {
self_id,
local_sensor,
nbr_sensor,
exports,
}
}
pub fn self_id(&self) -> &i32 {
&self.self_id
}
pub fn exports(&self) -> &Exports {
&self.exports
}
pub fn put_export(&mut self, id: i32, data: Export) {
self.exports.insert(id, data);
}
pub fn read_export_value<A: 'static + FromStr + Clone>(
&self,
id: &i32,
path: &Path,
) -> Result<A> {
self.exports
.get(id)
.ok_or("Export not found".into())
.and_then(|export| export.get(path))
}
pub fn local_sensors(&self) -> &LocalSensors {
&self.local_sensor
}
pub fn local_sense<A: 'static>(&self, local_sensor_id: &SensorId) -> Option<&A> {
self.local_sensor
.get(local_sensor_id)
.and_then(|value| value.downcast_ref::<A>())
}
pub fn nbr_sensors(&self) -> &NbrSensors {
&self.nbr_sensor
}
pub fn nbr_sense<A: 'static>(&self, sensor_id: &SensorId, nbr_id: &i32) -> Option<&A> {
self.nbr_sensor
.get(sensor_id)
.and_then(|value| value.get(nbr_id))
.and_then(|value| value.downcast_ref::<A>())
}
}
#[cfg(test)]
mod test {
use super::*;
use crate::path::Path;
use crate::sensor_id::{sensor, SensorId};
use crate::slot::Slot::{Branch, Nbr, Rep};
use crate::{export, path};
use std::any::Any;
use std::collections::HashMap;
use std::rc::Rc;
fn context_builder() -> Context {
let local_sensor = HashMap::from([(sensor("test"), Rc::new(Box::new(10) as Box<dyn Any>))]);
let nbr_sensor = HashMap::from([(
sensor("test"),
HashMap::from([(0, Rc::new(Box::new(10) as Box<dyn Any>))]),
)]);
let export = HashMap::from([(0, export!((path!(Rep(0), Nbr(0)), 10)))]);
Context::new(7, local_sensor, nbr_sensor, export)
}
#[test]
fn assert_on_fields() {
let context = context_builder();
assert_eq!(context.self_id, 7);
assert_eq!(context.exports.len(), 1);
assert_eq!(context.local_sensor.len(), 1);
assert_eq!(context.nbr_sensor.len(), 1);
}
#[test]
fn test_put_export() {
let mut context = context_builder();
assert_eq!(context.exports.len(), 1);
let add_export = export!((path!(Branch(0), Nbr(0)), 5));
context.put_export(1, add_export);
assert_eq!(context.exports.len(), 2)
}
#[test]
fn test_read_export_value() {
let context = context_builder();
assert_eq!(
context
.read_export_value::<i32>(&0, &path!(Rep(0), Nbr(0)))
.unwrap(),
10
);
assert!(context.read_export_value::<i32>(&1, &Path::new()).is_err());
assert!(context.read_export_value::<i32>(&0, &Path::new()).is_err());
}
#[test]
fn test_local_sense() {
let context = context_builder();
assert_eq!(
context
.local_sense::<i32>(&SensorId::new("test".to_string()))
.unwrap(),
&10
);
}
#[test]
fn test_nbr_sense() {
let context = context_builder();
assert_eq!(
context
.nbr_sense::<i32>(&SensorId::new("test".to_string()), &0)
.unwrap(),
&10
);
}
}