librashader_capi/
error.rs1use std::any::Any;
3use std::ffi::{c_char, CString};
4use std::mem::MaybeUninit;
5use std::ptr::NonNull;
6use thiserror::Error;
7
8#[non_exhaustive]
10#[derive(Error, Debug)]
11pub enum LibrashaderError {
12 #[error("There was an unknown error.")]
14 UnknownError(Box<dyn Any + Send + 'static>),
15
16 #[error("The parameter was null or invalid.")]
18 InvalidParameter(&'static str),
19
20 #[error("The provided string was not valid UTF8.")]
22 InvalidString(#[from] std::str::Utf8Error),
23
24 #[error("There was an error parsing the preset.")]
26 PresetError(#[from] librashader::presets::ParsePresetError),
27
28 #[error("There was an error preprocessing the shader source.")]
30 PreprocessError(#[from] librashader::preprocess::PreprocessError),
31
32 #[error("There was an error compiling the shader source.")]
34 ShaderCompileError(#[from] librashader::reflect::ShaderCompileError),
35
36 #[error("There was an error reflecting the shader source.")]
38 ShaderReflectError(#[from] librashader::reflect::ShaderReflectError),
39
40 #[error("The provided parameter name was invalid.")]
42 UnknownShaderParameter(*const c_char),
43
44 #[cfg(feature = "runtime-opengl")]
46 #[cfg_attr(feature = "docsrs", doc(cfg(feature = "runtime-opengl")))]
47 #[error("There was an error in the OpenGL filter chain.")]
48 OpenGlFilterError(#[from] librashader::runtime::gl::error::FilterChainError),
49
50 #[cfg(all(target_os = "windows", feature = "runtime-d3d11"))]
52 #[cfg_attr(
53 feature = "docsrs",
54 doc(cfg(all(target_os = "windows", feature = "runtime-d3d11")))
55 )]
56 #[error("There was an error in the D3D11 filter chain.")]
57 D3D11FilterError(#[from] librashader::runtime::d3d11::error::FilterChainError),
58
59 #[cfg(all(target_os = "windows", feature = "runtime-d3d12"))]
61 #[cfg_attr(
62 feature = "docsrs",
63 doc(cfg(all(target_os = "windows", feature = "runtime-d3d12")))
64 )]
65 #[error("There was an error in the D3D12 filter chain.")]
66 D3D12FilterError(#[from] librashader::runtime::d3d12::error::FilterChainError),
67
68 #[cfg(all(target_os = "windows", feature = "runtime-d3d9"))]
70 #[cfg_attr(
71 feature = "docsrs",
72 doc(cfg(all(target_os = "windows", feature = "runtime-d3d9")))
73 )]
74 #[error("There was an error in the D3D9 filter chain.")]
75 D3D9FilterError(#[from] librashader::runtime::d3d9::error::FilterChainError),
76
77 #[cfg(feature = "runtime-vulkan")]
80 #[cfg_attr(feature = "docsrs", doc(cfg(feature = "runtime-vulkan")))]
81 #[error("There was an error in the Vulkan filter chain.")]
82 VulkanFilterError(#[from] librashader::runtime::vk::error::FilterChainError),
83
84 #[cfg_attr(
86 feature = "docsrs",
87 doc(cfg(all(target_vendor = "apple", feature = "runtime-metal")))
88 )]
89 #[cfg(all(target_vendor = "apple", feature = "runtime-metal"))]
90 #[error("There was an error in the Metal filter chain.")]
91 MetalFilterError(#[from] librashader::runtime::mtl::error::FilterChainError),
92 #[error("This error is not reachable")]
94 Infallible(#[from] std::convert::Infallible),
95}
96
97#[repr(i32)]
99pub enum LIBRA_ERRNO {
100 UNKNOWN_ERROR = 0,
102
103 INVALID_PARAMETER = 1,
105
106 INVALID_STRING = 2,
108
109 PRESET_ERROR = 3,
111
112 PREPROCESS_ERROR = 4,
114
115 SHADER_PARAMETER_ERROR = 5,
117
118 REFLECT_ERROR = 6,
120
121 RUNTIME_ERROR = 7,
123}
124
125pub type PFN_libra_error_errno = extern "C" fn(error: libra_error_t) -> LIBRA_ERRNO;
129#[no_mangle]
130pub unsafe extern "C" fn libra_error_errno(error: libra_error_t) -> LIBRA_ERRNO {
135 let Some(error) = error else {
136 return LIBRA_ERRNO::UNKNOWN_ERROR;
137 };
138
139 unsafe { error.as_ref().get_code() }
140}
141
142pub type PFN_libra_error_print = extern "C" fn(error: libra_error_t) -> i32;
144#[no_mangle]
145pub unsafe extern "C" fn libra_error_print(error: libra_error_t) -> i32 {
151 let Some(error) = error else { return 1 };
152 unsafe {
153 let error = error.as_ref();
154 println!("{error:?}: {error}");
155 }
156 0
157}
158
159pub type PFN_libra_error_free = extern "C" fn(error: *mut libra_error_t) -> i32;
161#[no_mangle]
162pub unsafe extern "C" fn libra_error_free(error: *mut libra_error_t) -> i32 {
169 if error.is_null() {
170 return 1;
171 }
172
173 let error = unsafe { &mut *error };
174 let error = error.take();
175 let Some(error) = error else {
176 return 1;
177 };
178
179 unsafe { drop(Box::from_raw(error.as_ptr())) }
180 0
181}
182
183pub type PFN_libra_error_write =
185 extern "C" fn(error: libra_error_t, out: *mut MaybeUninit<*mut c_char>) -> i32;
186#[no_mangle]
187pub unsafe extern "C" fn libra_error_write(
194 error: libra_error_t,
195 out: *mut MaybeUninit<*mut c_char>,
196) -> i32 {
197 let Some(error) = error else { return 1 };
198 if out.is_null() {
199 return 1;
200 }
201
202 unsafe {
203 let error = error.as_ref();
204 let Ok(cstring) = CString::new(format!("{error:?}: {error}")) else {
205 return 1;
206 };
207
208 out.write(MaybeUninit::new(cstring.into_raw()))
209 }
210 0
211}
212
213pub type PFN_libra_error_free_string = extern "C" fn(out: *mut *mut c_char) -> i32;
215#[no_mangle]
216pub unsafe extern "C" fn libra_error_free_string(out: *mut *mut c_char) -> i32 {
224 if out.is_null() {
225 return 1;
226 }
227
228 unsafe {
229 let ptr = out.read();
230 *out = std::ptr::null_mut();
231 drop(CString::from_raw(ptr))
232 }
233 0
234}
235
236impl LibrashaderError {
237 pub(crate) const fn get_code(&self) -> LIBRA_ERRNO {
238 match self {
239 LibrashaderError::UnknownError(_) => LIBRA_ERRNO::UNKNOWN_ERROR,
240 LibrashaderError::InvalidParameter(_) => LIBRA_ERRNO::INVALID_PARAMETER,
241 LibrashaderError::InvalidString(_) => LIBRA_ERRNO::INVALID_STRING,
242 LibrashaderError::PresetError(_) => LIBRA_ERRNO::PRESET_ERROR,
243 LibrashaderError::PreprocessError(_) => LIBRA_ERRNO::PREPROCESS_ERROR,
244 LibrashaderError::ShaderCompileError(_) | LibrashaderError::ShaderReflectError(_) => {
245 LIBRA_ERRNO::REFLECT_ERROR
246 }
247 LibrashaderError::UnknownShaderParameter(_) => LIBRA_ERRNO::SHADER_PARAMETER_ERROR,
248 #[cfg(feature = "runtime-opengl")]
249 LibrashaderError::OpenGlFilterError(_) => LIBRA_ERRNO::RUNTIME_ERROR,
250 #[cfg(all(target_os = "windows", feature = "runtime-d3d11"))]
251 LibrashaderError::D3D11FilterError(_) => LIBRA_ERRNO::RUNTIME_ERROR,
252 #[cfg(all(target_os = "windows", feature = "runtime-d3d12"))]
253 LibrashaderError::D3D12FilterError(_) => LIBRA_ERRNO::RUNTIME_ERROR,
254 #[cfg(all(target_os = "windows", feature = "runtime-d3d9"))]
255 LibrashaderError::D3D9FilterError(_) => LIBRA_ERRNO::RUNTIME_ERROR,
256 #[cfg(feature = "runtime-vulkan")]
257 LibrashaderError::VulkanFilterError(_) => LIBRA_ERRNO::RUNTIME_ERROR,
258 #[cfg(all(target_vendor = "apple", feature = "runtime-metal"))]
259 LibrashaderError::MetalFilterError(_) => LIBRA_ERRNO::RUNTIME_ERROR,
260 LibrashaderError::Infallible(_) => LIBRA_ERRNO::UNKNOWN_ERROR,
261 }
262 }
263 pub(crate) const fn ok() -> libra_error_t {
264 None
265 }
266
267 pub(crate) fn export(self) -> libra_error_t {
268 NonNull::new(Box::into_raw(Box::new(self)))
269 }
270}
271
272macro_rules! assert_non_null {
273 (@EXPORT $value:ident) => {
274 if $value.is_null() || !$crate::ffi::ptr_is_aligned($value) {
275 return $crate::error::LibrashaderError::InvalidParameter(stringify!($value)).export();
276 }
277 };
278 ($value:ident) => {
279 if $value.is_null() || !$crate::ffi::ptr_is_aligned($value) {
280 return Err($crate::error::LibrashaderError::InvalidParameter(
281 stringify!($value),
282 ));
283 }
284 };
285}
286
287macro_rules! assert_some_ptr {
288 ($value:ident) => {
289 if $value.is_none() {
290 return Err($crate::error::LibrashaderError::InvalidParameter(
291 stringify!($value),
292 ));
293 }
294
295 let $value = unsafe { $value.as_ref().unwrap_unchecked().as_ref() };
296 };
297 (mut $value:ident) => {
298 if $value.is_none() {
299 return Err($crate::error::LibrashaderError::InvalidParameter(
300 stringify!($value),
301 ));
302 }
303
304 let $value = unsafe { $value.as_mut().unwrap_unchecked().as_mut() };
305 };
306}
307
308use crate::ctypes::libra_error_t;
309pub(crate) use assert_non_null;
310
311pub(crate) use assert_some_ptr;