1use core::mem::size_of;
6use std::fmt::{Debug, Display};
7use std::future::Future;
8use std::pin::Pin;
9use std::rc::Rc;
10
11use async_trait::async_trait;
12use gwr_track::id::Unique;
13
14use crate::types::{AccessType, SimResult};
15
16pub trait TotalBytes {
22 fn total_bytes(&self) -> usize;
23}
24
25pub trait Routable {
28 fn destination(&self) -> u64;
29 fn access_type(&self) -> AccessType;
30}
31
32pub trait SimObject: Clone + Debug + Display + Unique + TotalBytes + 'static {}
48
49impl TotalBytes for i32 {
54 fn total_bytes(&self) -> usize {
55 size_of::<i32>()
56 }
57}
58
59impl Routable for i32 {
60 fn destination(&self) -> u64 {
61 *self as u64
62 }
63 fn access_type(&self) -> AccessType {
64 match self {
65 0 => AccessType::ReadRequest,
66 1 => AccessType::WriteRequest,
67 2 => AccessType::WriteNonPostedRequest,
68 3 => AccessType::ReadResponse,
69 4 => AccessType::WriteNonPostedResponse,
70 _ => AccessType::Control,
71 }
72 }
73}
74
75impl SimObject for i32 {}
76
77impl TotalBytes for usize {
79 fn total_bytes(&self) -> usize {
80 size_of::<usize>()
81 }
82}
83
84impl Routable for usize {
85 fn destination(&self) -> u64 {
86 *self as u64
87 }
88 fn access_type(&self) -> AccessType {
89 match self {
90 0 => AccessType::ReadRequest,
91 1 => AccessType::WriteRequest,
92 2 => AccessType::WriteNonPostedRequest,
93 3 => AccessType::ReadResponse,
94 4 => AccessType::WriteNonPostedResponse,
95 _ => AccessType::Control,
96 }
97 }
98}
99
100impl SimObject for usize {}
101
102pub trait Event<T> {
114 #[must_use = "Futures do nothing unless you `.await` or otherwise use them"]
115 fn listen(&self) -> BoxFuture<'static, T>;
116
117 fn clone_dyn(&self) -> Box<dyn Event<T>>;
121}
122
123impl<T> Clone for Box<dyn Event<T>> {
125 fn clone(self: &Box<dyn Event<T>>) -> Box<dyn Event<T>> {
126 self.clone_dyn()
127 }
128}
129
130pub trait Resolve {
132 fn resolve(&self);
134}
135
136pub trait Resolver {
139 fn add_resolve(&self, resolve: Rc<dyn Resolve + 'static>);
140}
141
142pub type BoxFuture<'a, T> = Pin<std::boxed::Box<dyn Future<Output = T> + 'a>>;
143
144#[async_trait(?Send)]
165pub trait Runnable {
166 async fn run(&self) -> SimResult {
170 Ok(())
171 }
172}
173
174#[cfg(test)]
175mod tests {
176 use super::*;
177
178 #[test]
180 fn integer_sim_object_defaults_are_available() {
181 assert_eq!(0_i32.total_bytes(), size_of::<i32>());
182 assert_eq!(7_i32.destination(), 7);
183 assert_eq!(0_i32.access_type(), AccessType::ReadRequest);
184 assert_eq!(1_i32.access_type(), AccessType::WriteRequest);
185 assert_eq!(2_i32.access_type(), AccessType::WriteNonPostedRequest);
186 assert_eq!(3_i32.access_type(), AccessType::ReadResponse);
187 assert_eq!(4_i32.access_type(), AccessType::WriteNonPostedResponse);
188 assert_eq!(5_i32.access_type(), AccessType::Control);
189
190 assert_eq!(0_usize.total_bytes(), size_of::<usize>());
191 assert_eq!(7_usize.destination(), 7);
192 assert_eq!(0_usize.access_type(), AccessType::ReadRequest);
193 assert_eq!(1_usize.access_type(), AccessType::WriteRequest);
194 assert_eq!(2_usize.access_type(), AccessType::WriteNonPostedRequest);
195 assert_eq!(3_usize.access_type(), AccessType::ReadResponse);
196 assert_eq!(4_usize.access_type(), AccessType::WriteNonPostedResponse);
197 assert_eq!(5_usize.access_type(), AccessType::Control);
198 }
199
200 struct PassiveRunnable;
201
202 #[test]
203 fn runnable_default_run_completes_successfully() {
204 let runnable = PassiveRunnable;
205
206 futures::executor::LocalPool::new()
207 .run_until(runnable.run())
208 .unwrap();
209 }
210
211 #[async_trait(?Send)]
212 impl Runnable for PassiveRunnable {}
213}