1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
//! Turning a `cxx::Exception` into a structured `idakit` snafu error.
//!
//! `cxx`'s `Result<T>` gives back a `cxx::Exception` whose only datum is `what()`, a flat string,
//! the C++ `std::exception::what()`. That alone does not match idakit's house style, where an
//! [`Error`] variant is struct-style and carries context (`op`, `address`, `errno`, `reason`).
//! These tests exercise a real `cxx::Exception` (from the `probe_throw` shim, which needs no
//! kernel) and show the two conversion strategies the spike weighed:
//!
//! * fold `what()` in as the `reason` of a structured variant (shown here, since it runs without
//! a database), and
//! * the recommended production path: treat the C++ `throw` as a bare failure *signal* and
//! re-derive `errno` + `reason` on the Rust side from `Database::last_reason()`, exactly as
//! the raw facade path already does. The C++ body then needs no message at all.
//!
//! `probe_throw`'s third kind (a bare `throw 42`, not a `std::exception`) escapes `cxx`'s
//! `catch (std::exception const&)` shim and calls `std::terminate()`: a real, documented
//! containment gap in `cxx` itself, not exercised here since provoking it would abort this test
//! process along with every other test sharing it.
use assert;
use ;
use idakit_sys as sys;
/// Illustrative conversion: the message from a `cxx::Exception` (a segment-index read that threw),
/// mapped to a structured variant carrying the offending index and the C++ message. The variant
/// here is only a stand-in (idakit has no segment-by-index error today); the point is the *shape*,
/// a flat `what()` becoming a struct-style snafu error with call-site context. In a real kernel
/// path `errno` and `reason` would come from `Database::last_reason()` rather than from `what()`.
/// Every field the conversion is supposed to carry, checked directly rather than through a
/// stringified message: `op` and `address` come from the call site, `reason` from the caught
/// exception's `what()`, and `errno` is the stand-in's fixed `Ok` (a real kernel path would
/// re-derive it from `Database::last_reason()` instead).
/// The limitation, made explicit: everything `cxx` hands back for a caught exception is the one
/// `what()` string. There is no `errno`, index, or typed reason to read off the `Exception`
/// itself; any structure has to be supplied by the Rust call site (context, as
/// [`cxx_exception_becomes_structured_error`] shows) or re-derived from the kernel
/// (`last_reason()`).
/// A `kind` that matches none of the throwing arms is the containment baseline: the bridge call
/// returns `Ok` with no exception involved at all, not merely "didn't crash".