|
|
@@ -12,22 +12,26 @@ pub struct Pending{ |
|
|
|
pub recipient: Ipv4Addr, |
|
|
|
} |
|
|
|
|
|
|
|
#[derive(Default)] |
|
|
|
pub struct Sending { |
|
|
|
pub payload: Vec<u8>, |
|
|
|
pub bytes_sent: usize, |
|
|
|
pub prev: Event<Ipv4Addr>, |
|
|
|
pub prev: Event<Pending>, |
|
|
|
} |
|
|
|
|
|
|
|
#[derive(Default)] |
|
|
|
pub struct Sent { |
|
|
|
pub ack_req: bool, |
|
|
|
pub prev: Event<Sending>, |
|
|
|
} |
|
|
|
|
|
|
|
#[derive(Default)] |
|
|
|
pub struct Ack { |
|
|
|
pub data: Vec<u8>, |
|
|
|
pub prev: Event<Sent>, |
|
|
|
} |
|
|
|
|
|
|
|
#[derive(Default)] |
|
|
|
pub struct Finished<T> { |
|
|
|
pub prev: Event<T>, |
|
|
|
} |
|
|
@@ -79,6 +83,7 @@ impl<N, T> Elapsed<(), N> for T |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/* |
|
|
|
impl Timestamped for Active { |
|
|
|
fn time(&self) -> DateTime<Utc> { |
|
|
|
use Active::*; |
|
|
@@ -92,9 +97,10 @@ impl Timestamped for Active { |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
*/ |
|
|
|
|
|
|
|
macro_rules! event_attr { |
|
|
|
($method:ident, $t:ident, $attr:ident) => { |
|
|
|
($method:ident, $t:ty, $attr:ident) => { |
|
|
|
fn $method(&self) -> $t { |
|
|
|
use Active::*; |
|
|
|
match self { |
|
|
@@ -109,10 +115,33 @@ macro_rules! event_attr { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
impl Active { |
|
|
|
event_attr!(id, Uuid, id); |
|
|
|
impl Timestamped for Active { |
|
|
|
event_attr!(time, DateTime<Utc>, time); |
|
|
|
} |
|
|
|
|
|
|
|
macro_rules! optionally_public_event_attr { |
|
|
|
|
|
|
|
// note: `vis` is automatically optional, doesn't need |
|
|
|
// this will work as-is if there is nothing there |
|
|
|
|
|
|
|
($pub:vis $method:ident, $t:ident, $attr:ident) => { |
|
|
|
$pub fn $method(&self) -> $t { |
|
|
|
use Active::*; |
|
|
|
match self { |
|
|
|
Pending(event) => event.$attr, |
|
|
|
Sending(event) => event.$attr, |
|
|
|
Sent(event) => event.$attr, |
|
|
|
Acked(event) => event.$attr, |
|
|
|
FinishedNoAck(event) => event.$attr, |
|
|
|
FinishedAcked(event) => event.$attr, |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
impl Active { |
|
|
|
optionally_public_event_attr!(pub id, Uuid, id); |
|
|
|
} |
|
|
|
|
|
|
|
impl From<Event<Pending>> for Active { |
|
|
|
fn from(pending: Event<Pending>) -> Active { |
|
|
@@ -135,6 +164,90 @@ from_event!(Sending, Sending); |
|
|
|
from_event!(Sent, Sent); |
|
|
|
from_event!(Ack, Acked); |
|
|
|
from_event!(Finished<Sent>, FinishedNoAck); |
|
|
|
from_event!(Finished<Ack>, FinishedAcked); |
|
|
|
|
|
|
|
macro_rules! variant_check { |
|
|
|
($f:ident, $variant:ident) => { |
|
|
|
impl Active { |
|
|
|
pub fn $f(&self) -> bool { |
|
|
|
match self { |
|
|
|
Active::$variant(..) => true, |
|
|
|
_ => false, |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
variant_check!(is_pending, Pending); |
|
|
|
variant_check!(is_sending, Sending); |
|
|
|
variant_check!(is_sent, Sent); |
|
|
|
variant_check!(is_acked, Acked); |
|
|
|
variant_check!(is_finished_noack, FinishedNoAck); |
|
|
|
variant_check!(is_finished_acked, FinishedAcked); |
|
|
|
|
|
|
|
macro_rules! multiple_variant_check { |
|
|
|
($f:ident; $($variant:ident),*) => { |
|
|
|
impl Active { |
|
|
|
pub fn $f(&self) -> bool { |
|
|
|
match self { |
|
|
|
$( Active::$variant(..) => { true } )* |
|
|
|
|
|
|
|
_ => false, |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
multiple_variant_check!(is_finished; FinishedNoAck, FinishedAcked); |
|
|
|
multiple_variant_check!(is_still_unfinished; Pending, Sending, Sent, Acked); |
|
|
|
multiple_variant_check!(anything_but_sent; Pending, Sending, Acked, FinishedNoAck, FinishedAcked); |
|
|
|
|
|
|
|
// needed because Ipv4Addr does not implement Default |
|
|
|
// other event type structs derive Default instead |
|
|
|
impl Default for Pending { |
|
|
|
fn default() -> Self { |
|
|
|
Self { recipient: Ipv4Addr::new(127, 0, 0, 1) } |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
impl<T> Default for Event<T> |
|
|
|
where T: Default |
|
|
|
{ |
|
|
|
fn default() -> Self { |
|
|
|
Self { |
|
|
|
time: Utc::now(), |
|
|
|
id: Uuid::new_v4(), |
|
|
|
event: T::default(), |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
impl Default for Active { |
|
|
|
fn default() -> Self { |
|
|
|
Active::Pending(Default::default()) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
macro_rules! new_with_default { |
|
|
|
($f:ident, $t:ty) => { |
|
|
|
impl Active { |
|
|
|
pub fn $f() -> Self { |
|
|
|
let inner: Event<$t> = Default::default(); |
|
|
|
Self::from(inner) |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
new_with_default!(new_pending, Pending); |
|
|
|
new_with_default!(new_sending, Sending); |
|
|
|
new_with_default!(new_sent, Sent); |
|
|
|
new_with_default!(new_acked, Ack); |
|
|
|
new_with_default!(new_finished_noack, Finished<Sent>); |
|
|
|
new_with_default!(new_finished_acked, Finished<Ack>); |
|
|
|
|
|
|
|
#[allow(unused)] |
|
|
|
#[cfg(test)] |
|
|
@@ -156,5 +269,78 @@ mod tests { |
|
|
|
assert_eq!(pending_active.time(), now); |
|
|
|
assert_eq!(pending_active.id(), id); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
#[test] |
|
|
|
fn check_generated_methods_for_pending() { |
|
|
|
let active = Active::new_pending(); |
|
|
|
assert!(active.is_pending()); |
|
|
|
assert!(active.is_still_unfinished()); |
|
|
|
} |
|
|
|
|
|
|
|
#[test] |
|
|
|
fn generated_method_check_for_variant() { |
|
|
|
macro_rules! check_for_variant { |
|
|
|
($new:ident, $single:ident, $multiple:ident, $not:ident) => { |
|
|
|
let active = Active::$new(); |
|
|
|
assert!(active.$single()); |
|
|
|
assert!(active.$multiple()); |
|
|
|
assert!( ! active.$not()); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
check_for_variant!(new_pending, is_pending, is_still_unfinished, is_sent); |
|
|
|
check_for_variant!(new_sending, is_sending, is_still_unfinished, is_acked); |
|
|
|
check_for_variant!(new_sent, is_sent, is_still_unfinished, is_finished_noack); |
|
|
|
check_for_variant!(new_acked, is_acked, is_still_unfinished, is_pending); |
|
|
|
check_for_variant!(new_finished_noack, is_finished_noack, is_finished, is_still_unfinished); |
|
|
|
check_for_variant!(new_finished_acked, is_finished_acked, is_finished, is_still_unfinished); |
|
|
|
} |
|
|
|
|
|
|
|
#[test] |
|
|
|
fn active_impls_timestamped() { |
|
|
|
fn tm_plus_42min<T: Timestamped>(x: &T) -> DateTime<Utc> { |
|
|
|
x.time() + chrono::Duration::minutes(42) |
|
|
|
} |
|
|
|
|
|
|
|
let active = Active::new_sent(); |
|
|
|
let t2 = tm_plus_42min(&active); |
|
|
|
assert_eq!(active.time() + chrono::Duration::minutes(42), t2); |
|
|
|
} |
|
|
|
|
|
|
|
#[test] |
|
|
|
fn check_that_vis_can_handle_all_three_possibilities_for_visibility() { |
|
|
|
pub struct A { |
|
|
|
x: i32, |
|
|
|
y: DateTime<Utc>, |
|
|
|
z: f32, |
|
|
|
} |
|
|
|
|
|
|
|
macro_rules! a_attr { |
|
|
|
($pub:vis $method:ident, $t:ty, $attr:ident) => { |
|
|
|
impl A { |
|
|
|
$pub fn $method(&self) -> $t { |
|
|
|
self.$attr |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
a_attr!(get_x, i32, x); |
|
|
|
a_attr!(pub(crate) get_y, DateTime<Utc>, y); |
|
|
|
a_attr!(pub get_z, f32, z); |
|
|
|
|
|
|
|
let a = A { x: 0i32, y: Utc::now(), z: 1.234f32 }; |
|
|
|
|
|
|
|
assert_eq!(a.get_x(), a.x); |
|
|
|
assert_eq!(a.get_y(), a.y); |
|
|
|
assert_eq!(a.get_z(), a.z); |
|
|
|
} |
|
|
|
|
|
|
|
#[test] |
|
|
|
fn usage_of_variant_check_example() { |
|
|
|
let pending = Pending { recipient: Ipv4Addr::new(127, 0, 0, 1) }; |
|
|
|
let event = Event { time: Utc::now(), id: Uuid::new_v4(), event: pending }; |
|
|
|
let active = Active::from(event); |
|
|
|
assert_eq!(active.is_pending(), true); |
|
|
|
} |
|
|
|
} |