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
use crate::*;
use anyhow::anyhow;
use anyhow::Result;
use colorize::*;
use std::fmt::Debug;

impl<T> Matcher<T> {
	pub fn assert_option_with_received<T2>(
		&self,
		received: Option<T2>,
	) -> Result<T2> {
		self.disallow_negated()?;
		match received {
			Some(r) => Ok(r),
			None => Err(self.to_error_with_received(&"Some", &"None")),
		}
	}

	pub fn assert_option_with_received_negatable<T2>(
		&self,
		received: Option<T2>,
	) -> Result<()> {
		if self.negated && received.is_some() {
			Err(self.to_error_with_received(&"None", &"Some"))
		} else if !self.negated && received.is_none() {
			Err(self.to_error_with_received(&"Some", &"None"))
		} else {
			Ok(())
		}
	}

	pub fn assert_correct_with_received<T2: Debug, T3: Debug>(
		&self,
		result: bool,
		expected: &T2,
		received: &T3,
	) -> Result<()> {
		if self.is_true_with_negated(result) {
			Ok(())
		} else {
			Err(self.to_error_with_received(expected, received))
		}
	}

	/// Testing use only
	pub fn to_error_with_received<T2: Debug, T3: Debug>(
		&self,
		expected: &T2,
		received: &T3,
	) -> anyhow::Error {
		self.to_error_with_received_and_backtrace(expected, received, 0)
	}

	pub fn to_error_with_received_and_backtrace<T2: Debug, T3: Debug>(
		&self,
		expected: &T2,
		received: &T3,
		backtrace_depth: usize,
	) -> anyhow::Error {
		let mut expected = format!("{:?}", expected)
			.trim_matches('"')
			.to_string()
			.green();

		if self.negated {
			expected = format!("{} {}", "NOT".bold().green(), expected);
		}
		let received = format!("{:?}", received)
			.trim_matches('"')
			.to_string()
			.red();

		let backtrace = file_context_depth(4 + backtrace_depth);
		anyhow!("Expected: {expected}\nReceived: {received}\n\n{backtrace}",)
	}
	pub fn to_custom_error(err: &str) -> anyhow::Error {
		Self::to_custom_error_with_backtrace(err, 1)
	}

	pub fn to_custom_error_with_backtrace(
		err: &str,
		backtrace_depth: usize,
	) -> anyhow::Error {
		let backtrace = file_context_depth(4 + backtrace_depth);
		anyhow!("{err}\n\n{backtrace}")
	}
}


impl<T> Matcher<T>
where
	T: Debug,
{
	/// Ensure result is true, and check negated
	pub fn assert_correct<T2: Debug>(
		&self,
		result: bool,
		expected: &T2,
	) -> Result<()> {
		if self.is_true_with_negated(result) {
			Ok(())
		} else {
			Err(self.to_error(expected))
		}
	}

	pub fn to_error<T2: Debug>(&self, expected: &T2) -> anyhow::Error {
		self.to_error_with_received_and_backtrace(expected, &self.value, 0)
	}
	pub fn to_error_with_backtrace<T2: Debug>(
		&self,
		expected: &T2,
		backtrace_depth: usize,
	) -> anyhow::Error {
		self.to_error_with_received_and_backtrace(
			expected,
			&self.value,
			backtrace_depth,
		)
	}
}