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
84
85
86
87
88
89
90
91
92
93
94
95
96
use std::fmt::{Display, Formatter};
use serde::Serialize;

static NO_DATABASE: u32 = 1;
static MONGO: u32 = 1 << 1;
static MYSQL: u32 = 1 << 2;
static POSTGRES: u32 = 1 << 3;
static SQLITE: u32 = 1 << 4;
static SQL: u32 = MYSQL | POSTGRES | SQLITE;
static DATABASE: u32 = MONGO | SQL;
static ALL: u32 = DATABASE | NO_DATABASE;

#[repr(transparent)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Serialize)]
pub struct Availability(u32);

impl Availability {

    pub fn no_database() -> Self {
        Self(NO_DATABASE)
    }

    pub fn none() -> Self {
        Self(0)
    }

    pub fn database() -> Self {
        Self(DATABASE)
    }

    pub fn mongo() -> Self {
        Self(MONGO)
    }

    pub fn sql() -> Self {
        Self(SQL)
    }

    pub fn mysql() -> Self {
        Self(MYSQL)
    }

    pub fn postgres() -> Self {
        Self(POSTGRES)
    }

    pub fn sqlite() -> Self {
        Self(SQLITE)
    }

    pub fn contains(&self, actual: Availability) -> bool {
        self.0 & actual.0 != 0
    }

    pub fn is_none(&self) -> bool {
        self.0 == 0
    }

    pub fn bi_and(&self, other: Availability) -> Availability {
        Self(self.0 & other.0)
    }
}

impl Default for Availability {

    fn default() -> Self {
        Self(ALL)
    }
}

impl Display for Availability {

    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
        let mut to_join = vec![];
        if self.0 & NO_DATABASE > 0 {
            to_join.push("noDatabase");
        }
        if self.0 & MYSQL > 0 {
            to_join.push("mysql");
        }
        if self.0 & POSTGRES > 0 {
            to_join.push("postgres");
        }
        if self.0 & SQLITE > 0 {
            to_join.push("sqlite");
        }
        if self.0 & MONGO > 0 {
            to_join.push("mongo");
        }
        if to_join.is_empty() {
            f.write_str(&"none")
        } else {
            f.write_str(&to_join.join(" | "))
        }
    }
}