1use crate::ffi;
2use crate::ffi::jpeg_common_struct;
3use std::borrow::Cow;
4use std::mem;
5use std::os::raw::c_int;
6
7pub use crate::ffi::jpeg_error_mgr as ErrorMgr;
8
9#[allow(clippy::unnecessary_box_returns)]
10pub(crate) fn unwinding_error_mgr() -> Box<ErrorMgr> {
11 unsafe {
12 let mut err = Box::new(mem::zeroed());
13 ffi::jpeg_std_error(&mut err);
14 err.error_exit = Some(unwind_error_exit);
15 err.emit_message = Some(silence_message);
16 err
17 }
18}
19
20#[cold]
21fn formatted_message(prefix: &str, cinfo: &mut jpeg_common_struct) -> String {
22 unsafe {
23 let err = cinfo.err.as_ref().unwrap();
24 match err.format_message {
25 Some(fmt) => {
26 let mut buffer = mem::zeroed();
27 let correct_fn_type = mem::transmute::<
28 unsafe extern "C-unwind" fn(cinfo: &mut jpeg_common_struct, buffer: &[u8; 80]),
29 unsafe extern "C-unwind" fn(cinfo: &mut jpeg_common_struct, buffer: &mut [u8; 80])>(fmt);
30 (correct_fn_type)(cinfo, &mut buffer);
31 let buf = buffer.split(|&c| c == 0).next().unwrap_or_default();
32 let msg = String::from_utf8_lossy(buf);
33 let mut out = String::with_capacity(prefix.len() + msg.len());
34 push_str_in_cap(&mut out, prefix);
35 push_str_in_cap(&mut out, &msg);
36 out
37 },
38 None => format!("{}code {}", prefix, err.msg_code),
39 }
40 }
41}
42
43fn push_str_in_cap(out: &mut String, s: &str) {
44 let needs_to_grow = s.len() > out.capacity().wrapping_sub(out.len());
45 if !needs_to_grow {
46 out.push_str(s);
47 }
48}
49
50#[cold]
51extern "C-unwind" fn silence_message(_cinfo: &mut jpeg_common_struct, _level: c_int) {
52}
53
54#[cold]
55extern "C-unwind" fn unwind_error_exit(cinfo: &mut jpeg_common_struct) {
56 let msg = formatted_message("libjpeg fatal error: ", cinfo);
57 std::panic::resume_unwind(Box::new(msg));
59}