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
use crate::private::lib::String;
use crate::{debug, mismatch::Mismatches, MockFnInfo};

pub(crate) type MockResult<T> = Result<T, MockError>;

#[derive(Clone)]
pub(crate) enum MockError {
    Downcast {
        fn_call: debug::FnActualCall,
        pattern: debug::CallPatternDebug,
    },
    NoMockImplementation {
        fn_call: debug::FnActualCall,
    },
    NoMatcherFunction {
        fn_call: debug::FnActualCall,
        pattern: debug::CallPatternDebug,
    },
    NoMatchingCallPatterns {
        fn_call: debug::FnActualCall,
        mismatches: Mismatches,
    },
    NoOutputAvailableForCallPattern {
        fn_call: debug::FnActualCall,
        pattern: debug::CallPatternDebug,
    },
    MockNeverCalled {
        info: MockFnInfo,
    },
    CallOrderNotMatchedForMockFn {
        fn_call: debug::FnActualCall,
        actual_call_order: CallOrder,
        expected: Option<debug::CallPatternDebug>,
    },
    InputsNotMatchedInCallOrder {
        fn_call: debug::FnActualCall,
        actual_call_order: CallOrder,
        pattern: debug::CallPatternDebug,
        mismatches: Mismatches,
    },
    CannotReturnValueMoreThanOnce {
        fn_call: debug::FnActualCall,
        pattern: debug::CallPatternDebug,
    },
    FailedVerification(String),
    CannotUnmock {
        info: MockFnInfo,
    },
    NoDefaultImpl {
        info: MockFnInfo,
    },
    ExplicitPanic {
        fn_call: debug::FnActualCall,
        pattern: debug::CallPatternDebug,
        msg: String,
    },
}

impl core::fmt::Display for MockError {
    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
        match self {
            Self::Downcast { fn_call, pattern } => {
                write!(f, "{fn_call}: Fatal: Failed to downcast in {pattern}.")
            }
            Self::NoMockImplementation { fn_call } => {
                write!(f, "{fn_call}: No mock implementation found.")
            }
            Self::NoMatcherFunction { fn_call, pattern } => {
                write!(
                    f,
                    "{fn_call}: No function supplied for matching inputs for {pattern}."
                )
            }
            Self::NoMatchingCallPatterns {
                fn_call,
                mismatches,
            } => {
                write!(f, "{fn_call}: No matching call patterns. {mismatches}")
            }
            Self::NoOutputAvailableForCallPattern { fn_call, pattern } => {
                write!(
                    f,
                    "{fn_call}: No output available for after matching {pattern}."
                )
            }
            Self::MockNeverCalled { info } => {
                write!(
                    f,
                    "Mock for {path} was never called. Dead mocks should be removed.",
                    path = info.path
                )
            }
            Self::CallOrderNotMatchedForMockFn {
                fn_call,
                actual_call_order,
                expected,
            } => {
                if let Some(expected) = expected {
                    write!(f, "{fn_call}: Method matched in wrong order. Expected a call matching {expected}.")
                } else {
                    write!(f, "{fn_call}: Ordered call ({actual_call_order}) out of range: There were no more ordered call patterns in line for selection.")
                }
            }
            Self::InputsNotMatchedInCallOrder {
                fn_call,
                actual_call_order,
                pattern,
                mismatches,
            } => {
                write!(f, "{fn_call}: Method invoked in the correct order ({actual_call_order}), but inputs didn't match {pattern}. {mismatches}")
            }
            Self::CannotReturnValueMoreThanOnce { fn_call, pattern } => {
                write!(f, "{fn_call}: Cannot return value more than once from {pattern}, because of missing Clone bound. Try using `.each_call()` or explicitly quantifying the response.")
            }
            Self::FailedVerification(message) => write!(f, "{message}"),
            Self::CannotUnmock { info } => {
                write!(
                    f,
                    "{path} cannot be unmocked as there is no function available to call.",
                    path = info.path
                )
            }
            Self::NoDefaultImpl { info } => {
                write!(
                    f,
                    "{path} has not been set up with default implementation delegation.",
                    path = info.path
                )
            }
            Self::ExplicitPanic {
                fn_call,
                pattern,
                msg,
            } => write!(f, "{fn_call}: Explicit panic from {pattern}: {msg}"),
        }
    }
}

#[derive(Clone)]
pub struct CallOrder(pub usize);

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