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
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
//!

use std::sync::TryLockError;


#[macro_export]
macro_rules! ensure_eq {
    ($left:expr, $right:expr) => {{
        let (lstr, rstr) = (stringify!($left), stringify!($right));
        ensure!(
            $left == $right,
            "violation: {} == {}\n{} == {}\n{} == {}",
            lstr, rstr,
            lstr, $left,
            rstr, $right
        )
    }};
}

#[macro_export]
macro_rules! ensure_ne {
    ($left:expr, $right:expr) => {{
        let (lstr, rstr) = (stringify!($left), stringify!($right));
        ensure!(
            $left != $right,
            "violation: {} != {}\n{} == {}\n{} == {}",
            lstr, rstr,
            lstr, $left,
            rstr, $right
        )
    }};
}

#[macro_export]
macro_rules! ensure_gt {
    ($left:expr, $right:expr) => {{
        let (lstr, rstr) = (stringify!($left), stringify!($right));
        ensure!(
            $left > $right,
            "violation: {} > {}\n{} == {}\n{} == {}",
            lstr, rstr,
            lstr, $left,
            rstr, $right
        )
    }};
}

#[macro_export]
macro_rules! ensure_lt {
    ($left:expr, $right:expr) => {{
        let (lstr, rstr) = (stringify!($left), stringify!($right));
        ensure!(
            $left < $right,
            "violation: {} < {}\n{} == {}\n{} == {}",
            lstr, rstr,
            lstr, $left,
            rstr, $right
        )
    }};
}

#[macro_export]
macro_rules! ensure_ge {
    ($left:expr, $right:expr) => {{
        let (lstr, rstr) = (stringify!($left), stringify!($right));
        ensure!(
            $left >= $right,
            "violation: {} >= {}\n{} == {}\n{} == {}",
            lstr, rstr,
            lstr, $left,
            rstr, $right
        )
    }};
}

#[macro_export]
macro_rules! ensure_le {
    ($left:expr, $right:expr) => {{
        let (lstr, rstr) = (stringify!($left), stringify!($right));
        ensure!(
            $left <= $right,
            "violation: {} <= {}\n{} == {}\n{} == {}",
            lstr, rstr,
            lstr, $left,
            rstr, $right
        )
    }};
}

#[macro_export]
macro_rules! ensure {
    ($predicate:expr $(, $fmt:expr $(, $args:expr)*)? ) => {
        if $predicate {
            $crate::error::DeltaResult::Ok(())
        } else {
            Err($crate::error::DeltaError::FailedToEnsure {
                predicate: stringify!($predicate).to_string(),
                msg: {
                    #[allow(unused)] let mut msg = String::new();
                    $(  msg = format!($fmt $(, $args)*);  )?
                    msg
                },
                file: file!().to_string(),
                line: line!(),
                column: column!(),
            })
        }
    };
}

#[macro_export]
macro_rules! bug_detected {
    ($($fmt:expr $(, $args:expr)*)?) => {
        Err($crate::error::DeltaError::BugDetected {
            msg: { #[allow(redundant_semicolon)] {
                #[allow(unused)] let mut msg = String::new();
                $(  msg = format!($fmt $(, $args)*);  )? ;
                msg
            }},
            file: file!().to_string(),
            line: line!(),
            column: column!(),
        })
    };
}



pub type DeltaResult<T> = Result<T, DeltaError>;

#[derive(
    Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord,
    serde_derive::Deserialize, serde_derive::Serialize,
)]
pub enum DeltaError {
    BugDetected {
        msg: String,
        file: String,
        line: u32,
        column: u32
    },
    ExpectedValue,
    FailedToEnsure {
        predicate: String,
        msg: String,
        file: String,
        line: u32,
        column: u32
    },
    FailedToApplyDelta { reason: String },
    IllegalDelta { index: usize },
    RwLockAccessWouldBlock,
    RwLockPoisoned(String)
}


impl<T> From<TryLockError<T>> for DeltaError {
    fn from(err: TryLockError<T>) -> DeltaError {
        match err {
            TryLockError::WouldBlock =>
                DeltaError::RwLockAccessWouldBlock,
            TryLockError::Poisoned(psn_err) =>
                DeltaError::RwLockPoisoned(format!("{}", psn_err)),
        }
    }
}