|
- use std::net::Ipv4Addr;
- use chrono::{DateTime, Utc};
- use uuid::Uuid;
-
- pub struct Event<T> {
- pub time: DateTime<Utc>,
- pub id: Uuid,
- pub event: T,
- }
-
- pub struct Pending{
- pub recipient: Ipv4Addr,
- }
-
- pub struct Sending {
- pub payload: Vec<u8>,
- pub bytes_sent: usize,
- pub prev: Event<Ipv4Addr>,
- }
-
- pub struct Sent {
- pub ack_req: bool,
- pub prev: Event<Sending>,
- }
-
- pub struct Ack {
- pub data: Vec<u8>,
- pub prev: Event<Sent>,
- }
-
- pub struct Finished<T> {
- pub prev: Event<T>,
- }
-
- pub enum Active {
- Pending(Event<Pending>),
- Sending(Event<Sending>),
- Sent(Event<Sent>),
- Acked(Event<Ack>),
- FinishedNoAck(Event<Finished<Sent>>),
- FinishedAcked(Event<Finished<Ack>>),
- }
-
- pub trait Timestamped {
- fn time(&self) -> DateTime<Utc>;
- }
-
- pub trait Chronological {
- type Prev;
- type Next;
-
- fn prev(&self) -> Self::Prev;
- fn next(&self) -> Self::Next;
- }
-
- pub trait Elapsed<P, N>: Chronological<Prev = P, Next = N> {
- fn elapsed(&self) -> chrono::Duration;
- }
-
- impl<T> Timestamped for Event<T> {
- fn time(&self) -> DateTime<Utc> { self.time }
- }
-
- impl<P, N, T> Elapsed<P, N> for T
- where T: Chronological<Prev = P, Next = N>,
- P: Timestamped,
- N: Timestamped
- {
- fn elapsed(&self) -> chrono::Duration {
- self.next().time().signed_duration_since(self.prev().time())
- }
- }
-
- impl<N, T> Elapsed<(), N> for T
- where T: Chronological<Prev = (), Next = N>
- {
- fn elapsed(&self) -> chrono::Duration {
- chrono::Duration::seconds(0)
- }
- }
-
- impl Timestamped for Active {
- fn time(&self) -> DateTime<Utc> {
- use Active::*;
- match self {
- Pending(event) => event.time,
- Sending(event) => event.time,
- Sent(event) => event.time,
- Acked(event) => event.time,
- FinishedNoAck(event) => event.time,
- FinishedAcked(event) => event.time,
- }
- }
- }
-
- macro_rules! event_attr {
- ($method:ident, $t:ident, $attr:ident) => {
- 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 {
- event_attr!(id, Uuid, id);
- }
-
-
- impl From<Event<Pending>> for Active {
- fn from(pending: Event<Pending>) -> Active {
- Active::Pending(pending)
- }
- }
-
- macro_rules! from_event {
- ($t:ty, $variant:ident) => {
- impl From<Event<$t>> for Active {
- fn from(event: Event<$t>) -> Active {
- Active::$variant(event)
- }
- }
- }
- }
-
- //from_event!(Pending, Pending);
- from_event!(Sending, Sending);
- from_event!(Sent, Sent);
- from_event!(Ack, Acked);
- from_event!(Finished<Sent>, FinishedNoAck);
-
- #[allow(unused)]
- #[cfg(test)]
- mod tests {
- use super::*;
- use std::str::FromStr;
-
- #[test]
- fn event_attr_accessors_work() {
- let pending = Pending { recipient: "0.0.0.0".parse().unwrap() };
- let now = Utc::now();
- let id = Uuid::new_v4();
- let pending_event = Event {
- time: now,
- id,
- event: pending,
- };
- let pending_active = Active::Pending(pending_event);
- assert_eq!(pending_active.time(), now);
- assert_eq!(pending_active.id(), id);
- }
- }
|