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
use {
    crate::{error::Error, Connection, Socket},
    std::{cmp, fmt, future::Future, pin::Pin},
};

pub trait Migration<S: Socket> {
    fn name(&self) -> &'static str;
    fn up<'a>(
        &self,
        conn: &'a mut Connection<S>,
    ) -> Pin<Box<dyn Future<Output = Result<(), Error>> + 'a>>;
    fn down<'a>(
        &self,
        conn: &'a mut Connection<S>,
    ) -> Pin<Box<dyn Future<Output = Result<(), Error>> + 'a>>;
}

pub struct MigrationList<S: Socket + 'static> {
    pub version: Version,
    pub migrations: &'static [&'static dyn Migration<S>],
}

impl<S: Socket + 'static> MigrationList<S> {
    pub fn ordered(list: &[Self]) -> bool {
        if list.len() <= 1 {
            return true;
        }
        for i in 1..list.len() {
            if list[i - 1].version >= list[i].version {
                return false;
            }
        }
        true
    }
}

#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct Version(pub u16, pub u16, pub u16);

impl cmp::Ord for Version {
    fn cmp(&self, other: &Self) -> cmp::Ordering {
        match self.0.cmp(&other.0) {
            core::cmp::Ordering::Equal => {}
            ord => return ord,
        }
        match self.1.cmp(&other.1) {
            core::cmp::Ordering::Equal => {}
            ord => return ord,
        }
        self.2.cmp(&other.2)
    }
}

impl PartialOrd for Version {
    fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
        Some(self.cmp(other))
    }
}

impl fmt::Display for Version {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "({}.{}.{})", self.0, self.1, self.2)
    }
}