1use crate::conversions;
2use console::{Style, StyledObject};
3use std::path::PathBuf;
4use tokio::task::JoinError;
5
6pub type Result<A> = std::result::Result<A, Error>;
7
8#[derive(Debug)]
9pub enum Error {
10 UnknownTestCase {
11 path: String,
12 },
13
14 OpenApiTypes {
16 path: PathBuf,
17 cause: openapi_types::Error,
18 },
19 Conversion {
20 path: PathBuf,
21 cause: conversions::Error,
22 },
23
24 JoinError {
26 schema_path: PathBuf,
27 cause: JoinError,
28 },
29
30 DiffDetected {
32 output: String,
33 actual: PathBuf,
34 expected: PathBuf,
35 },
36 FormatFailed {
37 path: PathBuf,
38 detail: String,
39 },
40 CannotCreateFile {
41 path: PathBuf,
42 detail: String,
43 },
44 CannotReadFile {
45 path: PathBuf,
46 detail: String,
47 },
48 CannotCopyFile {
49 from: PathBuf,
50 to: PathBuf,
51 detail: String,
52 },
53 CannotRender {
54 path: PathBuf,
55 detail: String,
56 },
57 Errors(Vec<Self>),
58 ThreadNotFound(String),
59 UnsupportedExampleLocation(String),
60}
61
62impl Error {
63 pub fn detail(&self, theme: ErrorTheme) -> String {
64 match self {
65 Error::DiffDetected {
66 output,
67 actual,
68 expected,
69 } => {
70 let style = theme.diff_style();
71 format!(
72 "\n {: <10} : {}\n {} : {}\n\n{}",
73 style.src_lines,
74 actual.to_string_lossy(),
75 style.dst_lines,
76 expected.to_string_lossy(),
77 output
78 )
79 }
80 Error::FormatFailed { detail, .. } => {
81 format!("rustfmt>\n{}", detail)
82 }
83 Error::Conversion {
84 path,
85 cause: conversions::Error::TransformBroken { detail },
86 } => {
87 format!(
88 "internal error: transform broken.\n{}\n{}",
89 path.display(),
90 detail,
91 )
92 }
93 Error::Errors(errors) => errors
94 .iter()
95 .map(|e| e.detail(theme))
96 .collect::<Vec<_>>()
97 .join("\n"),
98
99 _ => {
100 format!("{:#?}", self)
101 }
102 }
103 }
104 pub fn conversion<A: Into<PathBuf>>(path: A) -> impl FnOnce(conversions::Error) -> Self {
105 |cause| Self::Conversion {
106 path: path.into(),
107 cause,
108 }
109 }
110 pub fn openapi<A: Into<PathBuf>>(path: A) -> impl FnOnce(openapi_types::Error) -> Self {
111 |cause| Self::OpenApiTypes {
112 path: path.into(),
113 cause,
114 }
115 }
116 pub fn dump(&self) -> String {
117 self.detail(ErrorTheme::Test)
118 }
119}
120
121#[derive(Copy, Clone)]
122pub enum ErrorTheme {
123 Test,
124 Overwrite,
125}
126
127pub struct DiffStyle {
128 src_lines: StyledObject<&'static str>,
129 dst_lines: StyledObject<&'static str>,
130}
131
132impl ErrorTheme {
133 pub fn diff_style(&self) -> DiffStyle {
134 match self {
135 ErrorTheme::Test => DiffStyle {
136 src_lines: Style::new().red().apply_to("- actual"),
137 dst_lines: Style::new().green().apply_to("+ expected"),
138 },
139 ErrorTheme::Overwrite => DiffStyle {
140 src_lines: Style::new().red().apply_to("- current"),
141 dst_lines: Style::new().green().apply_to("+ modified"),
142 },
143 }
144 }
145}