rstest_bdd_patterns/
errors.rs1use std::fmt;
4use thiserror::Error;
5
6#[derive(Debug, Clone, PartialEq, Eq)]
16pub struct PlaceholderErrorInfo {
17 pub message: &'static str,
18 pub position: usize,
19 pub placeholder: Option<String>,
20}
21
22impl PlaceholderErrorInfo {
23 #[must_use]
32 pub fn new(message: &'static str, position: usize, placeholder: Option<String>) -> Self {
33 Self {
34 message,
35 position,
36 placeholder,
37 }
38 }
39}
40
41impl fmt::Display for PlaceholderErrorInfo {
42 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
43 match &self.placeholder {
44 Some(name) => write!(
45 f,
46 "{} for placeholder `{}` at byte {} (zero-based)",
47 self.message, name, self.position
48 ),
49 None => write!(f, "{} at byte {} (zero-based)", self.message, self.position),
50 }
51 }
52}
53
54#[derive(Debug, Error)]
64pub enum PatternError {
65 #[error("{0}")]
66 Placeholder(PlaceholderErrorInfo),
67 #[error(transparent)]
68 Regex(#[from] regex::Error),
69}
70
71pub(crate) fn placeholder_error(
72 message: &'static str,
73 position: usize,
74 placeholder: Option<String>,
75) -> PatternError {
76 PatternError::Placeholder(PlaceholderErrorInfo::new(message, position, placeholder))
77}
78
79#[cfg(test)]
80mod tests {
81 use super::*;
82
83 #[test]
84 fn formats_placeholder_with_name() {
85 let info = PlaceholderErrorInfo::new("invalid", 4, Some("count".into()));
86 assert_eq!(
87 info.to_string(),
88 "invalid for placeholder `count` at byte 4 (zero-based)"
89 );
90 }
91
92 #[test]
93 fn formats_placeholder_without_name() {
94 let info = PlaceholderErrorInfo::new("oops", 1, None);
95 assert_eq!(info.to_string(), "oops at byte 1 (zero-based)");
96 }
97
98 #[test]
99 fn forwards_regex_error_display() {
100 let err = PatternError::Regex(regex::Error::Syntax("bad".into()));
101 assert_eq!(
102 err.to_string(),
103 regex::Error::Syntax("bad".into()).to_string()
104 );
105 }
106}