summaryrefslogtreecommitdiff
path: root/src/event/sequence.rs
blob: c566156508fc09b2ef0926d69cccd6fa5ad4b0e7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
use std::fmt;

use crate::clock::DateTime;

#[derive(Clone, Copy, Debug, Eq, PartialEq, serde::Serialize)]
pub struct Instant {
    pub at: DateTime,
    #[serde(skip)]
    pub sequence: Sequence,
}

impl From<Instant> for Sequence {
    fn from(instant: Instant) -> Self {
        instant.sequence
    }
}

#[derive(
    Clone,
    Copy,
    Debug,
    Eq,
    Ord,
    PartialEq,
    PartialOrd,
    serde::Deserialize,
    serde::Serialize,
    sqlx::Type,
)]
#[serde(transparent)]
#[sqlx(transparent)]
pub struct Sequence(i64);

impl fmt::Display for Sequence {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        let Self(value) = self;
        value.fmt(f)
    }
}

impl Sequence {
    pub fn up_to<E>(resume_point: Option<Self>) -> impl for<'e> Fn(&'e E) -> bool
    where
        E: Sequenced,
    {
        move |event| resume_point.map_or(true, |resume_point| event.sequence() <= resume_point)
    }

    pub fn after<E>(resume_point: Option<Self>) -> impl for<'e> Fn(&'e E) -> bool
    where
        E: Sequenced,
    {
        move |event| resume_point < Some(event.sequence())
    }

    pub fn start_from<E>(resume_point: Self) -> impl for<'e> Fn(&'e E) -> bool
    where
        E: Sequenced,
    {
        move |event| resume_point <= event.sequence()
    }
}

pub trait Sequenced {
    fn instant(&self) -> Instant;

    fn sequence(&self) -> Sequence {
        self.instant().into()
    }
}

impl<E> Sequenced for &E
where
    E: Sequenced,
{
    fn instant(&self) -> Instant {
        (*self).instant()
    }

    fn sequence(&self) -> Sequence {
        (*self).sequence()
    }
}