Skip to content

Commit 1ae2353

Browse files
authored
cabi: Add getter for error debug info (#775)
1 parent 49a4091 commit 1ae2353

File tree

3 files changed

+38
-0
lines changed

3 files changed

+38
-0
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ All notable changes to MiniJinja are documented here.
55
## 2.10.0
66

77
- Fix incorrect permissions when `--output` is used in the CLI. #772
8+
- Added `mj_err_get_debug_info` to the C-ABI. #775
89

910
## 2.9.0
1011

minijinja-cabi/include/minijinja.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,11 @@ void mj_env_set_undefined_behavior(struct mj_env *env,
207207
*/
208208
MINIJINJA_API void mj_err_clear(void);
209209

210+
/*
211+
Returns the error's debug info if there is an error.
212+
*/
213+
MINIJINJA_API char *mj_err_get_debug_info(void);
214+
210215
/*
211216
Returns the error's description if there is an error.
212217
*/

minijinja-cabi/src/error.rs

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use std::cell::RefCell;
22
use std::error::Error as _;
33
use std::ffi::{c_char, CString};
4+
use std::fmt::Write;
45
use std::ptr;
56

67
use minijinja::{Error, ErrorKind};
@@ -48,6 +49,37 @@ pub extern "C" fn mj_err_print() -> bool {
4849
})
4950
}
5051

52+
/// Returns the error's debug info if there is an error.
53+
///
54+
/// The value must be freed with `mj_str_free`.
55+
#[no_mangle]
56+
pub unsafe extern "C" fn mj_err_get_debug_info() -> *mut c_char {
57+
LAST_ERROR
58+
.with_borrow(|x| {
59+
x.as_ref()
60+
.and_then(|x| {
61+
let mut info = String::new();
62+
if x.name().is_some() {
63+
writeln!(info, "{}", x.display_debug_info()).unwrap();
64+
}
65+
let mut source_opt = x.source();
66+
while let Some(source) = source_opt {
67+
writeln!(info, "\ncaused by: {source}").unwrap();
68+
if let Some(source) = source.downcast_ref::<Error>() {
69+
if source.name().is_some() {
70+
writeln!(info, "{}", source.display_debug_info()).unwrap();
71+
}
72+
}
73+
source_opt = source.source();
74+
}
75+
info.into()
76+
})
77+
.and_then(|info| CString::new(info).ok())
78+
.map(|cstr| cstr.into_raw())
79+
})
80+
.unwrap_or(ptr::null_mut())
81+
}
82+
5183
/// Returns the error's description if there is an error.
5284
///
5385
/// The value must be freed with `mj_str_free`.

0 commit comments

Comments
 (0)