Skip to content
This repository was archived by the owner on May 7, 2024. It is now read-only.

Feature/context #22

Merged
merged 13 commits into from
May 16, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
148 changes: 148 additions & 0 deletions src/core/context.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
use std::any::Any;
use std::collections::HashMap;
use crate::core::context::context::Context;
use crate::core::export::export::Export;
use crate::core::path::path::path::Path;
use crate::core::sensor_id::sensor_id::SensorId;

pub mod context {
use std::any::Any;
use std::collections::HashMap;
use crate::core::export::export::Export;
use crate::core::sensor_id::sensor_id::SensorId;

/// Context implementation
///
/// * `selfId` The ID of the device that this context is for.
///
/// * `local_sensor` The values perceived by the local sensors of the device.
///
/// * `nbr_sensor` The values perceived by the sensors for each neighbor of the device.
///
/// * `exports` All the export that are available to the device.
#[derive(Debug)]
pub struct Context {
pub(crate) self_id: i32,
pub(crate) local_sensor: HashMap<SensorId, Box<dyn Any>>,
pub(crate) nbr_sensor: HashMap<SensorId, HashMap<i32, Box<dyn Any>>>,
pub(crate) exports: HashMap<i32, Export>
}
}

impl Context {
/// ## Create new Context of a device from the given parameters.
///
/// ### Arguments
///
/// * `self_id` - the ID of the device
///
/// * `local_sensor` - The values perceived by the local sensors of the device.
///
/// * `nbr_sensor` - The values perceived by the sensors for each neighbor of the device.
///
/// * `exports` - All the export that are available to the device.
pub fn new(
self_id: i32,
local_sensor: HashMap<SensorId, Box<dyn Any>>,
nbr_sensor: HashMap<SensorId, HashMap<i32, Box<dyn Any>>>,
exports: HashMap<i32, Export>) -> Context {
Context {
self_id,
local_sensor,
nbr_sensor,
exports
}
}

/// Add an export of a device to the context.
///
/// * `id` the ID of the device
/// * `data` the export of the device
pub fn put_export(&mut self, id: i32, data: Export) {
self.exports.insert(id, data);
}

/// Read the value corresponding to the given path from the export of a device.
///
/// * `id` the ID of the device
/// * `path` the path to the value
/// * `A` the type of the value
/// * return the value if it exists
pub fn read_export_value<A: 'static>(&self, id: i32, path: Path) -> Option<&A> {
self.exports.get(&id).and_then(|export| export.get(&path))
}

/// Get the value of the given sensor.
/// * `name` the name of the sensor
/// * `T` the type of the value
/// * return the value if it exists
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>())
}

/// Get the value of the given sensor for the given neighbor.
/// * `sensor_id` the neighbor sensor id
/// * `nbr_id` the neighbor id
/// * `T` the type of the value
/// * return the value if it exists
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 std::any::Any;
use std::collections::HashMap;
use crate::core::context::context::Context;
use crate::core::export::export::Export;
use crate::core::export_factory::export_factory::empty_path;
use crate::core::path::path::path::Path;
use crate::core::path::slot::slot::Slot::{Branch, Nbr, Rep};
use crate::core::sensor_id::sensor_id::SensorId;

fn context_builder() -> Context {
let local_sensor = HashMap::from([(SensorId::new("test".to_string()), Box::new(10) as Box<dyn Any>)]);
let nbr_sensor = HashMap::from([(SensorId::new("test".to_string()), HashMap::from([(0, Box::new(10) as Box<dyn Any>)]))]);
let export = HashMap::from([(0, Export::new(HashMap::from([(Path::new(vec![Rep(0), Nbr(0)]), Box::new(10) as Box<dyn Any>)])))]);
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::new(HashMap::from([(Path::new(vec![Branch(0), Nbr(0)]), Box::new(5) as Box<dyn Any>)]));
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::new(vec![Rep(0), Nbr(0)])).unwrap(), &10);
assert_eq!(context.read_export_value::<i32>(1, empty_path()), None);
assert_eq!(context.read_export_value::<i32>(0, empty_path()), None);
}

#[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);
}
}
4 changes: 3 additions & 1 deletion src/core/mod.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
pub mod vm;
pub mod path;
pub mod export;
pub mod export_factory;
pub mod export_factory;
pub mod context;
pub mod sensor_id;
29 changes: 29 additions & 0 deletions src/core/sensor_id.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
use crate::core::sensor_id::sensor_id::SensorId;

///Sensor is piece of hardware that allow the device to interact with the environment.
pub mod sensor_id {
#[derive(PartialEq, Debug, Clone, Eq, Hash)]
pub struct SensorId {
pub(crate) name: String
}
}

impl SensorId {
/// Given a string, creates a new sensor id
pub fn new(name: String) -> SensorId {
SensorId {
name
}
}
}

#[cfg(test)]
mod tests {
use crate::core::sensor_id::sensor_id::SensorId;

#[test]
fn test_new() {
let sensor_id = SensorId::new("foo".to_string());
assert_eq!(sensor_id.name, "foo".to_string())
}
}