spirv_cross2/
error.rs

1use crate::handle::{Handle, Id};
2use crate::reflect::DecorationValue;
3use spirv_cross_sys as sys;
4use spirv_cross_sys::{spvc_context_s, spvc_result};
5use std::ffi::CStr;
6use std::ptr::NonNull;
7
8/// Result type for SPIR-V Cross.
9pub type Result<T> = std::result::Result<T, SpirvCrossError>;
10
11/// Error type for SPIR-V Cross.
12#[derive(Debug, thiserror::Error)]
13pub enum SpirvCrossError {
14    #[error("The SPIR-V is invalid: {0}.")]
15    /// The SPIR-V is invalid.
16    InvalidSpirv(String),
17    #[error("The SPIR-V operation is unsupported: {0}.")]
18    /// The SPIR-V operation is invalid.
19    UnsupportedSpirv(String),
20    #[error("Allocation failure: {0}.")]
21    /// Allocation failure.
22    OutOfMemory(String),
23    #[error("The argument is invalid: {0}.")]
24    /// The argument is invalid.
25    InvalidArgument(String),
26    #[error("The tag of the handle does not match the compiler instance: {0:?}")]
27    /// The handle provided originated from a different compiler instance.
28    InvalidHandle(Handle<Box<dyn Id>>),
29    #[error("The operation is invalid: {0:?}")]
30    /// The requested operation is invalid.
31    InvalidOperation(String),
32    #[error("The decoration value is invalid for the given decoration: {0:?} = {1}")]
33    /// The decoration value invalid for the given decoration.
34    ///
35    /// This is mostly returned if there is an invalid `OpDecoration Builtin` or `OpDecoration FPRoundingMode`
36    /// in the SPIR-V module.
37    InvalidDecorationOutput(spirv::Decoration, u32),
38    #[error("The decoration value is invalid for the given decoration: {0:?} = {1:?}")]
39    /// The decoration value is invalid for the given decoration.
40    InvalidDecorationInput(spirv::Decoration, DecorationValue<'static>),
41    #[error("The string is invalid: {0:?}")]
42    /// The string is invalid.
43    ///
44    /// Strings must not be nul-terminated, and must be valid UTF-8.
45    InvalidString(String),
46    #[error("The provided index was out of bounds for the resource: ({row}, {column}).")]
47    /// The index is out of bounds when trying to access a constant resource.
48    ///
49    /// Multiscalar specialization constants are stored in column-major order.
50    /// Vectors are always in column 1.
51    IndexOutOfBounds {
52        /// The vector index or row accessed.
53        row: u32,
54        /// The column accessed.
55        column: u32,
56    },
57    #[error("An unexpected enum value was found.")]
58    /// An unexpected enum value was found.
59    InvalidEnum,
60}
61
62pub(crate) trait ToContextError {
63    fn ok(self, context: impl ContextRooted) -> Result<()>;
64}
65
66fn get_last_error(context: NonNull<spvc_context_s>) -> String {
67    let cstr = unsafe { CStr::from_ptr(sys::spvc_context_get_last_error_string(context.as_ptr())) };
68
69    cstr.to_string_lossy().to_string()
70}
71
72impl ToContextError for spvc_result {
73    fn ok(self, context: impl ContextRooted) -> Result<()> {
74        match self {
75            spvc_result::SPVC_SUCCESS => Ok(()),
76            spvc_result::SPVC_ERROR_INVALID_SPIRV => Err(SpirvCrossError::InvalidSpirv(
77                get_last_error(context.context()),
78            )),
79            spvc_result::SPVC_ERROR_UNSUPPORTED_SPIRV => Err(SpirvCrossError::UnsupportedSpirv(
80                get_last_error(context.context()),
81            )),
82            spvc_result::SPVC_ERROR_OUT_OF_MEMORY => Err(SpirvCrossError::OutOfMemory(
83                get_last_error(context.context()),
84            )),
85            spvc_result::SPVC_ERROR_INVALID_ARGUMENT => Err(SpirvCrossError::InvalidArgument(
86                get_last_error(context.context()),
87            )),
88        }
89    }
90}
91
92pub(crate) use crate::sealed::ContextRooted;