agent_tk/
states.rs

1//! Module to define the state of an agent.
2
3use serde::{Deserialize, Serialize};
4use std::any::TypeId;
5use std::ops::{Deref, DerefMut};
6
7use crate::{Error, Result};
8
9// Structures
10
11/// Represent a position state
12#[derive(Clone, Copy, PartialEq, Serialize, Deserialize)]
13pub struct Position
14{
15  /// Longitude
16  pub longitude: f64,
17  /// Latitude
18  pub latitude: f64,
19}
20
21/// Represent a velocity state
22#[derive(Clone, Copy, PartialEq, Serialize, Deserialize)]
23pub struct Velocity
24{
25  /// x-component of the velocity
26  pub x: f32,
27  /// y-component of the velocity
28  pub y: f32,
29}
30
31/// Trait to conveniently build a State from one of the possible states
32pub trait StateTrait
33{
34  /// Convert to a State enum
35  fn to_state(self) -> State;
36}
37
38//  ____    _             _
39// / ___|  | |_    __ _  | |_    ___
40// \___ \  | __|  / _` | | __|  / _ \
41//  ___) | | |_  | (_| | | |_  |  __/
42// |____/   \__|  \__,_|  \__|  \___|
43
44/// Enum that serves as a container for any of the state
45#[derive(Clone, Copy, PartialEq, Serialize, Deserialize)]
46pub enum State
47{
48  /// Position state
49  Position(Position),
50  /// Velocity state
51  Velocity(Velocity),
52}
53
54//  ____    _             _
55// / ___|  | |_    __ _  | |_    ___   ___
56// \___ \  | __|  / _` | | __|  / _ \ / __|
57//  ___) | | |_  | (_| | | |_  |  __/ \__ \
58// |____/   \__|  \__,_|  \__|  \___| |___/
59
60/// States of an agent
61#[derive(Default, Clone, PartialEq, Serialize, Deserialize)]
62pub struct States(Vec<State>);
63
64impl Deref for States
65{
66  type Target = Vec<State>;
67  fn deref(&self) -> &Self::Target
68  {
69    &self.0
70  }
71}
72
73impl DerefMut for States
74{
75  fn deref_mut(&mut self) -> &mut Self::Target
76  {
77    &mut self.0
78  }
79}
80
81// Implementation
82
83macro_rules! build_states_getter {
84  ($(#[$attr:meta])* => ($name:tt, $type:tt)) => {
85    $(#[$attr])*
86    pub fn $name(&self) -> Result<$type>
87    {
88      let res = self.0.iter().find_map(|x| match x
89      {
90        State::$type(p) => Some(p),
91        _ => None,
92      });
93      if res.is_none()
94      {
95        Err(Error::UnknownState(std::any::type_name::<$type>()))
96      }
97      else
98      {
99        Ok(*res.unwrap())
100      }
101    }
102  };
103}
104
105impl States
106{
107  build_states_getter!(
108    /// Get the position state, if any
109    => (get_position, Position));
110  build_states_getter!(
111    /// Get the velocity state, if any
112    => (get_velocity, Velocity));
113  /// Add a state
114  pub fn add_state<T: StateTrait + 'static>(&mut self, t: T) -> crate::Result<&mut States>
115  {
116    let it = self.0.iter().find(|x| match x
117    {
118      State::Position(_) => TypeId::of::<Position>() == TypeId::of::<T>(),
119      State::Velocity(_) => TypeId::of::<Velocity>() == TypeId::of::<T>(),
120    });
121    if it.is_none()
122    {
123      self.push(t.to_state());
124      Ok(self)
125    }
126    else
127    {
128      Err(Error::DuplicateState(std::any::type_name::<T>()))
129    }
130  }
131  /// Update a state
132  pub fn update_state<T: StateTrait + 'static>(&mut self, t: T) -> crate::Result<&mut States>
133  {
134    let it = self.0.iter().enumerate().find(|(_, x)| match x
135    {
136      State::Position(_) => TypeId::of::<Position>() == TypeId::of::<T>(),
137      State::Velocity(_) => TypeId::of::<Velocity>() == TypeId::of::<T>(),
138    });
139    if let Some((index, _)) = it
140    {
141      self.remove(index);
142      self.push(t.to_state());
143      Ok(self)
144    }
145    else
146    {
147      Err(Error::UnknownState(std::any::type_name::<T>()))
148    }
149  }
150}
151
152impl From<States> for SharedStates
153{
154  fn from(val: States) -> Self
155  {
156    SharedStates::new(val)
157  }
158}
159
160impl StateTrait for Position
161{
162  fn to_state(self) -> State
163  {
164    State::Position(self)
165  }
166}
167
168impl StateTrait for Velocity
169{
170  fn to_state(self) -> State
171  {
172    State::Velocity(self)
173  }
174}
175
176//  ____    _                                 _   ____    _             _
177// / ___|  | |__     __ _   _ __    ___    __| | / ___|  | |_    __ _  | |_    ___
178// \___ \  | '_ \   / _` | | '__|  / _ \  / _` | \___ \  | __|  / _` | | __|  / _ \
179//  ___) | | | | | | (_| | | |    |  __/ | (_| |  ___) | | |_  | (_| | | |_  |  __/
180// |____/  |_| |_|  \__,_| |_|     \___|  \__,_| |____/   \__|  \__,_|  \__|  \___|
181
182macro_rules! build_shared_states_getter {
183  ($(#[$attr:meta])* => ($name:tt, $type:tt)) => {
184    $(#[$attr])*
185    pub fn $name(&self) -> Result<$type>
186    {
187      self.states.lock()?.$name()
188    }
189  };
190}
191
192/// States that are protected by a mutx
193#[derive(Clone)]
194pub struct SharedStates
195{
196  states: ccutils::sync::ArcMutex<States>,
197}
198
199impl SharedStates
200{
201  build_shared_states_getter!(
202    /// Get the position state, if any
203    => (get_position, Position));
204  build_shared_states_getter!(
205    /// Get the velocity state, if any
206    => (get_velocity, Velocity));
207  /// Create a shared states from an initial states
208  pub fn new(states: States) -> Self
209  {
210    Self {
211      states: states.into(),
212    }
213  }
214  /// This function is used to update the states
215  pub fn update_states(&self, updater: impl Fn(&mut crate::states::States)) -> Result<()>
216  {
217    let mut locked = self.states.lock()?;
218    updater(&mut locked);
219    Ok(())
220  }
221  /// Update a state
222  pub fn update_state<T: crate::states::StateTrait + 'static>(&self, state: T)
223    -> crate::Result<()>
224  {
225    self.states.lock()?.update_state(state)?;
226    Ok(())
227  }
228  /// Return a copy of the states, as a non shared variant.
229  pub fn to_owned_states(&self) -> Result<States>
230  {
231    Ok(self.states.lock()?.to_owned())
232  }
233}