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,
19 pub position: usize,
21 pub placeholder: Option<String>,
23}
24
25impl PlaceholderErrorInfo {
26 #[must_use]
35 pub fn new(message: &'static str, position: usize, placeholder: Option<String>) -> Self {
36 Self {
37 message,
38 position,
39 placeholder,
40 }
41 }
42}
43
44impl fmt::Display for PlaceholderErrorInfo {
45 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
46 match &self.placeholder {
47 Some(name) => write!(
48 f,
49 "{} for placeholder `{}` at byte {} (zero-based)",
50 self.message, name, self.position
51 ),
52 None => write!(f, "{} at byte {} (zero-based)", self.message, self.position),
53 }
54 }
55}
56
57#[derive(Debug, Error)]
67pub enum PatternError {
68 #[error("{0}")]
69 Placeholder(PlaceholderErrorInfo),
71 #[error(transparent)]
72 Regex(#[from] regex::Error),
74}
75
76pub(crate) fn placeholder_error(
77 message: &'static str,
78 position: usize,
79 placeholder: Option<String>,
80) -> PatternError {
81 PatternError::Placeholder(PlaceholderErrorInfo::new(message, position, placeholder))
82}
83
84#[cfg(test)]
85mod tests {
86 use super::*;
87
88 #[test]
89 fn formats_placeholder_with_name() {
90 let info = PlaceholderErrorInfo::new("invalid", 4, Some("count".into()));
91 assert_eq!(
92 info.to_string(),
93 "invalid for placeholder `count` at byte 4 (zero-based)"
94 );
95 }
96
97 #[test]
98 fn formats_placeholder_without_name() {
99 let info = PlaceholderErrorInfo::new("oops", 1, None);
100 assert_eq!(info.to_string(), "oops at byte 1 (zero-based)");
101 }
102
103 #[test]
104 fn forwards_regex_error_display() {
105 let err = PatternError::Regex(regex::Error::Syntax("bad".into()));
106 assert_eq!(
107 err.to_string(),
108 regex::Error::Syntax("bad".into()).to_string()
109 );
110 }
111}