1use alloc::{boxed::Box, string::String, vec::Vec};
2use core::{error::Error, fmt};
3
4#[derive(Clone, Debug)]
5pub struct ShaderError<E> {
6 pub source: String,
8 pub label: Option<String>,
9 pub inner: Box<E>,
10}
11
12#[cfg(feature = "wgsl-in")]
13impl fmt::Display for ShaderError<crate::front::wgsl::ParseError> {
14 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
15 let label = self.label.as_deref().unwrap_or_default();
16 let string = self.inner.emit_to_string(&self.source);
17 write!(f, "\nShader '{label}' parsing {string}")
18 }
19}
20#[cfg(feature = "glsl-in")]
21impl fmt::Display for ShaderError<crate::front::glsl::ParseErrors> {
22 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
23 let label = self.label.as_deref().unwrap_or_default();
24 let string = self.inner.emit_to_string(&self.source);
25 write!(f, "\nShader '{label}' parsing {string}")
26 }
27}
28#[cfg(feature = "spv-in")]
29impl fmt::Display for ShaderError<crate::front::spv::Error> {
30 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
31 let label = self.label.as_deref().unwrap_or_default();
32 let string = self.inner.emit_to_string(&self.source);
33 write!(f, "\nShader '{label}' parsing {string}")
34 }
35}
36impl fmt::Display for ShaderError<crate::WithSpan<crate::valid::ValidationError>> {
37 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
38 use codespan_reporting::{files::SimpleFile, term};
39
40 let label = self.label.as_deref().unwrap_or_default();
41 let files = SimpleFile::new(label, &self.source);
42 let config = term::Config::default();
43 let mut writer = term::termcolor::NoColor::new(Vec::new());
44 term::emit(&mut writer, &config, &files, &self.inner.diagnostic())
45 .expect("cannot write error");
46 write!(
47 f,
48 "\nShader validation {}",
49 String::from_utf8_lossy(&writer.into_inner())
50 )
51 }
52}
53impl<E> Error for ShaderError<E>
54where
55 ShaderError<E>: fmt::Display,
56 E: Error + 'static,
57{
58 fn source(&self) -> Option<&(dyn Error + 'static)> {
59 Some(&self.inner)
60 }
61}