You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

161 lines
3.4KB

  1. use std::net::Ipv4Addr;
  2. use chrono::{DateTime, Utc};
  3. use uuid::Uuid;
  4. pub struct Event<T> {
  5. pub time: DateTime<Utc>,
  6. pub id: Uuid,
  7. pub event: T,
  8. }
  9. pub struct Pending{
  10. pub recipient: Ipv4Addr,
  11. }
  12. pub struct Sending {
  13. pub payload: Vec<u8>,
  14. pub bytes_sent: usize,
  15. pub prev: Event<Ipv4Addr>,
  16. }
  17. pub struct Sent {
  18. pub ack_req: bool,
  19. pub prev: Event<Sending>,
  20. }
  21. pub struct Ack {
  22. pub data: Vec<u8>,
  23. pub prev: Event<Sent>,
  24. }
  25. pub struct Finished<T> {
  26. pub prev: Event<T>,
  27. }
  28. pub enum Active {
  29. Pending(Event<Pending>),
  30. Sending(Event<Sending>),
  31. Sent(Event<Sent>),
  32. Acked(Event<Ack>),
  33. FinishedNoAck(Event<Finished<Sent>>),
  34. FinishedAcked(Event<Finished<Ack>>),
  35. }
  36. pub trait Timestamped {
  37. fn time(&self) -> DateTime<Utc>;
  38. }
  39. pub trait Chronological {
  40. type Prev;
  41. type Next;
  42. fn prev(&self) -> Self::Prev;
  43. fn next(&self) -> Self::Next;
  44. }
  45. pub trait Elapsed<P, N>: Chronological<Prev = P, Next = N> {
  46. fn elapsed(&self) -> chrono::Duration;
  47. }
  48. impl<T> Timestamped for Event<T> {
  49. fn time(&self) -> DateTime<Utc> { self.time }
  50. }
  51. impl<P, N, T> Elapsed<P, N> for T
  52. where T: Chronological<Prev = P, Next = N>,
  53. P: Timestamped,
  54. N: Timestamped
  55. {
  56. fn elapsed(&self) -> chrono::Duration {
  57. self.next().time().signed_duration_since(self.prev().time())
  58. }
  59. }
  60. impl<N, T> Elapsed<(), N> for T
  61. where T: Chronological<Prev = (), Next = N>
  62. {
  63. fn elapsed(&self) -> chrono::Duration {
  64. chrono::Duration::seconds(0)
  65. }
  66. }
  67. impl Timestamped for Active {
  68. fn time(&self) -> DateTime<Utc> {
  69. use Active::*;
  70. match self {
  71. Pending(event) => event.time,
  72. Sending(event) => event.time,
  73. Sent(event) => event.time,
  74. Acked(event) => event.time,
  75. FinishedNoAck(event) => event.time,
  76. FinishedAcked(event) => event.time,
  77. }
  78. }
  79. }
  80. macro_rules! event_attr {
  81. ($method:ident, $t:ident, $attr:ident) => {
  82. fn $method(&self) -> $t {
  83. use Active::*;
  84. match self {
  85. Pending(event) => event.$attr,
  86. Sending(event) => event.$attr,
  87. Sent(event) => event.$attr,
  88. Acked(event) => event.$attr,
  89. FinishedNoAck(event) => event.$attr,
  90. FinishedAcked(event) => event.$attr,
  91. }
  92. }
  93. }
  94. }
  95. impl Active {
  96. event_attr!(id, Uuid, id);
  97. }
  98. impl From<Event<Pending>> for Active {
  99. fn from(pending: Event<Pending>) -> Active {
  100. Active::Pending(pending)
  101. }
  102. }
  103. macro_rules! from_event {
  104. ($t:ty, $variant:ident) => {
  105. impl From<Event<$t>> for Active {
  106. fn from(event: Event<$t>) -> Active {
  107. Active::$variant(event)
  108. }
  109. }
  110. }
  111. }
  112. //from_event!(Pending, Pending);
  113. from_event!(Sending, Sending);
  114. from_event!(Sent, Sent);
  115. from_event!(Ack, Acked);
  116. from_event!(Finished<Sent>, FinishedNoAck);
  117. #[allow(unused)]
  118. #[cfg(test)]
  119. mod tests {
  120. use super::*;
  121. use std::str::FromStr;
  122. #[test]
  123. fn event_attr_accessors_work() {
  124. let pending = Pending { recipient: "0.0.0.0".parse().unwrap() };
  125. let now = Utc::now();
  126. let id = Uuid::new_v4();
  127. let pending_event = Event {
  128. time: now,
  129. id,
  130. event: pending,
  131. };
  132. let pending_active = Active::Pending(pending_event);
  133. assert_eq!(pending_active.time(), now);
  134. assert_eq!(pending_active.id(), id);
  135. }
  136. }