Browse Source

begin adding case study

master
Jonathan Strong 4 years ago
parent
commit
1cee3956d2
3 changed files with 160 additions and 16 deletions
  1. +2
    -0
      Cargo.toml
  2. +137
    -0
      src/case_study.rs
  3. +21
    -16
      src/lib.rs

+ 2
- 0
Cargo.toml View File

@@ -7,3 +7,5 @@ edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
chrono = "0.4"
uuid = { version = "0.7", features = ["v4"] }

+ 137
- 0
src/case_study.rs View File

@@ -0,0 +1,137 @@
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);
}

#[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);
}
}


+ 21
- 16
src/lib.rs View File

@@ -44,7 +44,12 @@
//! }
//! make_adder_fn!(42);
//! ```
//!

pub mod case_study;


#[allow(unused)]
#[cfg(test)]
mod tests {

@@ -319,26 +324,26 @@ mod tests {
<A as Devious>::abc(&$x)
}
}
let c = <A as ::tests::example_for_why_you_should_use_fully_qualified_names::Devious>::abc(&a);
//let c = <A as ::tests::example_for_why_you_should_use_fully_qualified_names::Devious>::abc(&a);

macro_rules! you_gotta_be_wiser {
{ [[ $x:ident ]] } => {
<A as ::tests::example_for_why_you_should_use_fully_qualified_names::Devious>::abc(&$x)
}
//{ [[ $x:ident ]] } => {
// <A as crate::tests::example_for_why_you_should_use_fully_qualified_names::Devious>::abc(&$x)
//};
//{ -^-^- $x:ident -^-^- } => {{
// // invoking the version that's inside `the_upside_down`
// use crate::tests::example_for_why_you_should_use_fully_qualified_names::the_upside_down::Devious as OtherDevious;
// <A as crate::tests::example_for_why_you_should_use_fully_qualified_names::the_upside_down::OtherDevious>::xyz(&$x)
//}};
}
//macro_rules! you_gotta_be_wiser {
// { [[ $x:ident ]] } => {
// <A as ::tests::example_for_why_you_should_use_fully_qualified_names::Devious>::abc(&$x)
// }
// //{ [[ $x:ident ]] } => {
// // <A as crate::tests::example_for_why_you_should_use_fully_qualified_names::Devious>::abc(&$x)
// //};
// //{ -^-^- $x:ident -^-^- } => {{
// // // invoking the version that's inside `the_upside_down`
// // use crate::tests::example_for_why_you_should_use_fully_qualified_names::the_upside_down::Devious as OtherDevious;
// // <A as crate::tests::example_for_why_you_should_use_fully_qualified_names::the_upside_down::OtherDevious>::xyz(&$x)
// //}};
//}

assert_eq!(didnt_see_it_coming!{ a <-> }, 42);

assert_eq!(you_gotta_be_wiser!{ [[ a ]] }, 42);
//assert_eq!(you_gotta_be_wiser!{ [[ a ]] }, 42);
//assert_eq!(you_gotta_be_wiser!{ -^-^- a -^-^- }, -42);

/// muhaha


Loading…
Cancel
Save