agent-tk 0.4.0

`agent-tk` (`agent toolkit/tasks-knowledge`) is a crate for the development of autonomous agents using Rust, with an emphasis on tasks and knowledge based agents. This project is part of the [auKsys](http://auksys.org) project.
Documentation
//! Resources of agent

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),
        }
      }
    }
  };
}

//  ____
// / ___|  ___ _ __  ___  ___  _ __
// \___ \ / _ \ '_ \/ __|/ _ \| '__|
//  ___) |  __/ | | \__ \ (_) | |
// |____/ \___|_| |_|___/\___/|_|

/// Trait for tagging sensors
pub trait Sensor {}

//   ____
//  / ___|__ _ _ __ ___   ___ _ __ __ _
// | |   / _` | '_ ` _ \ / _ \ '__/ _` |
// | |__| (_| | | | | | |  __/ | | (_| |
//  \____\__,_|_| |_| |_|\___|_|  \__,_|

/// Represent a camera sensor
#[derive(Clone, Debug)]
pub struct Camera;

impl Sensor for Camera {}

define_resource!(Camera);

//  _     _     _
// | |   (_) __| | __ _ _ __
// | |   | |/ _` |/ _` | '__|
// | |___| | (_| | (_| | |
// |_____|_|\__,_|\__,_|_|

/// Represent a Lidar sensor
#[derive(Clone, Debug)]
pub struct Lidar;

impl Sensor for Lidar {}

define_resource!(Lidar);

//   ____      _
//  / ___|_ __(_)_ __  _ __   ___ _ __
// | |  _| '__| | '_ \| '_ \ / _ \ '__|
// | |_| | |  | | |_) | |_) |  __/ |
//  \____|_|  |_| .__/| .__/ \___|_|
//              |_|   |_|

/// Represent a gripper sensor
#[derive(Clone, Debug)]
pub struct Gripper;

define_resource!(Gripper);

//  ____
// |  _ \ _ __ ___  _ __  _ __   ___ _ __
// | | | | '__/ _ \| '_ \| '_ \ / _ \ '__|
// | |_| | | | (_) | |_) | |_) |  __/ |
// |____/|_|  \___/| .__/| .__/ \___|_|
//                 |_|   |_|

/// Represent a dropper
#[derive(Clone, Debug)]
pub struct Dropper;

define_resource!(Dropper);

//  ____             _        _
// | __ ) _   _  ___| | _____| |_
// |  _ \| | | |/ __| |/ / _ \ __|
// | |_) | |_| | (__|   <  __/ |_
// |____/ \__,_|\___|_|\_\___|\__|

/// Represent a bucket
#[derive(Clone, Debug)]
pub struct Bucket
{
  #[allow(dead_code)]
  capacity: i32,
}

define_resource!(Bucket);

//  _                                    _   _
// | |    ___   ___ ___  _ __ ___   ___ | |_(_) ___  _ __
// | |   / _ \ / __/ _ \| '_ ` _ \ / _ \| __| |/ _ \| '_ \
// | |__| (_) | (_| (_) | | | | | | (_) | |_| | (_) | | | |
// |_____\___/ \___\___/|_| |_| |_|\___/ \__|_|\___/|_| |_|

/// Represent the locomotion of an agent
#[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),
}

//  ____                                     ___
// |  _ \ ___  ___  ___  _   _ _ __ ___ ___ / _ \ _   _  ___ _ __ _   _
// | |_) / _ \/ __|/ _ \| | | | '__/ __/ _ \ | | | | | |/ _ \ '__| | | |
// |  _ <  __/\__ \ (_) | |_| | | | (_|  __/ |_| | |_| |  __/ |  | |_| |
// |_| \_\___||___/\___/ \__,_|_|  \___\___|\__\_\\__,_|\___|_|   \__, |
//                                                                |___/

/// Query for resources and borrow them
pub trait ResourceQuery<'a>
{
  /// Type of the answer to a query, should be a tuple
  type Answer;
  /// Query if the resources exist
  fn has_resources(&self, rss: &Resources) -> bool;
  /// Query and borrow the resources
  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
  }
}

//  ____                                     ____                     _
// |  _ \ ___  ___  ___  _   _ _ __ ___ ___ / ___|_   _  __ _ _ __ __| |
// | |_) / _ \/ __|/ _ \| | | | '__/ __/ _ \ |  _| | | |/ _` | '__/ _` |
// |  _ <  __/\__ \ (_) | |_| | | | (_|  __/ |_| | |_| | (_| | | | (_| |
// |_| \_\___||___/\___/ \__,_|_|  \___\___|\____|\__,_|\__,_|_|  \__,_|

/// Guard a resource, for as long as the object live, the holder has exclusive access to the resource
#[allow(private_bounds)]
pub struct ResourceGuard<'a, T: ResourceTrait>
{
  #[allow(dead_code)]
  res: T,
  #[allow(dead_code)]
  guard: MutexGuard<'a, ()>,
}

//  ____
// |  _ \ ___  ___  ___  _   _ _ __ ___ ___  ___
// | |_) / _ \/ __|/ _ \| | | | '__/ __/ _ \/ __|
// |  _ <  __/\__ \ (_) | |_| | | | (_|  __/\__ \
// |_| \_\___||___/\___/ \__,_|_|  \___\___||___/

/// Resources of an agent
#[derive(Default)]
pub struct Resources
{
  resources: Vec<InnerResource>,
}

#[allow(private_bounds)]
impl Resources
{
  /// Add a resource
  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)
  }
  /// Borrow a resource
  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;
      }
    }
  }
}