use futures::lock::{Mutex, MutexGuard};
trait ResourceTrait: From<Resource>
{
fn to_resource(self) -> Resource;
fn is_resource(r: &Resource) -> bool;
}
macro_rules! define_resource {
($type:ident) => {
impl ResourceTrait for $type
{
fn to_resource(self) -> Resource
{
return Resource::$type(self);
}
fn is_resource(r: &Resource) -> bool
{
match r
{
Resource::$type(_) => true,
_ => false,
}
}
}
impl From<Resource> for $type
{
fn from(value: Resource) -> Self
{
match value
{
Resource::$type(x) => x,
_ => panic!("Invalid resource ask for $type, contains {:?}.", value),
}
}
}
};
}
pub trait Sensor {}
#[derive(Clone, Debug)]
pub struct Camera;
impl Sensor for Camera {}
define_resource!(Camera);
#[derive(Clone, Debug)]
pub struct Lidar;
impl Sensor for Lidar {}
define_resource!(Lidar);
#[derive(Clone, Debug)]
pub struct Gripper;
define_resource!(Gripper);
#[derive(Clone, Debug)]
pub struct Dropper;
define_resource!(Dropper);
#[derive(Clone, Debug)]
pub struct Bucket
{
#[allow(dead_code)]
capacity: i32,
}
define_resource!(Bucket);
#[derive(Clone, Debug)]
pub struct Locomotion;
define_resource!(Locomotion);
#[derive(Clone, Debug)]
enum Resource
{
Camera(Camera),
Lidar(Lidar),
Gripper(Gripper),
Dropper(Dropper),
Bucket(Bucket),
Locomotion(Locomotion),
}
pub trait ResourceQuery<'a>
{
type Answer;
fn has_resources(&self, rss: &Resources) -> bool;
fn borrow_resources(&self, rss: &'a Resources) -> Option<Self::Answer>;
}
impl<'a, T1: ResourceTrait> ResourceQuery<'a> for T1
{
type Answer = ResourceGuard<'a, T1>;
fn has_resources(&self, rss: &Resources) -> bool
{
for a in rss.resources.iter()
{
if T1::is_resource(&a.res)
{
return true;
}
}
false
}
fn borrow_resources(&self, rss: &'a Resources) -> Option<Self::Answer>
{
for a in rss.resources.iter()
{
if T1::is_resource(&a.res)
{
let lock = a.lock.try_lock();
if let Some(guard) = lock
{
return Some(ResourceGuard::<'a, T1> {
res: a.res.clone().into(),
guard,
});
}
}
}
None
}
}
struct InnerResource
{
res: Resource,
lock: Mutex<()>,
}
impl InnerResource
{
#[allow(dead_code)]
fn is_available(&self) -> bool
{
true
}
}
#[allow(private_bounds)]
pub struct ResourceGuard<'a, T: ResourceTrait>
{
#[allow(dead_code)]
res: T,
#[allow(dead_code)]
guard: MutexGuard<'a, ()>,
}
#[derive(Default)]
pub struct Resources
{
resources: Vec<InnerResource>,
}
#[allow(private_bounds)]
impl Resources
{
pub fn add_resource(&mut self, r: impl ResourceTrait) -> crate::Result<&mut Resources>
{
self.resources.push(InnerResource {
res: r.to_resource(),
lock: Default::default(),
});
Ok(self)
}
pub fn borrow_resources<RQ>(&mut self, q: RQ) -> <RQ as ResourceQuery<'_>>::Answer
where
RQ: for<'a> ResourceQuery<'a>,
{
loop
{
if let Some(b) = q.borrow_resources(self)
{
return b;
}
}
}
}