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
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
//! `cxx` bindings for IDA's own generic container `qvector<T>` (`bridge::*vec_*`).
//!
//! `cxx` has no generic-template support and its built-in `CxxVector<T>` is `std::vector`-only,
//! so it cannot match `qvector`'s `{ T* array; size_t n; size_t alloc; }` ABI. This module binds
//! each concrete `qvector<T>` instantiation as its own `Opaque` [`cxx::ExternType`] (one distinct
//! `type_id!` per instantiation), the mechanical per-`T` boilerplate emitted by the
//! [`qvec_opaque!`] macro; this is the per-instantiation recipe KDAB's cxx-qt uses for its own
//! Qt container bindings. Two instantiations prove the recipe from scalar `T` to a
//! `Trivial`-struct `T`:
//!
//! - [`IntVec`] binds the SDK's `intvec_t` (`qvector<int>`), sourced from a flow-chart block's
//! successor edge list.
//! - [`RangeVec`] binds the SDK's `rangevec_t` (`struct : qvector<range_t>`), built from a
//! function's chunk ranges, with [`RangeT`](crate::bridge_gen::RangeT) (the `Trivial` ExternType
//! from the generated [`bridge_gen`](crate::bridge_gen)) as its element.
//!
//! Both `intvec_t` and `rangevec_t` are real global SDK names, so `#[cxx_name]` names them
//! directly with no C++ `using` alias (angle-bracketed `#[cxx_name = "qvector<int>"]` does not
//! parse in `type_id!`/`cxx_name`, which require an identifier path).
//!
//! Each instantiation is read two ways, contrasting cost:
//!
//! - **Copy** (`intvec_copy`): one linear copy into an owned [`Vec`], no lifetime tie. The safe
//! default when the data outlives the container.
//! - **Zero-copy** (`intvec_slice`, `rangevec_slice`): a `&[T]` reconstructed on the C++ side
//! from the container's `{array, n}` and returned as `rust::Slice`, borrowing the live
//! backing store with no allocation and no copy. Sound only because the returned slice's
//! lifetime is tied to the borrowed container (`&'a V -> &'a [T]`), the access is read-only
//! (`alloc`/`qalloc`/`qfree` are never touched), and the `{array, n}` layout is fixed by the
//! ABI-per-minor pin. The bodies are hand-written in `facade/qvec_bridge.cpp`.
//!
//! This is a recipe demonstration, not yet consumed by the `idakit` library.
// cxx::bridge's own attribute allowlist rejects #[expect]/#[allow] on individual fn items
// (`unsupported attribute`), so the three zero-copy fns' required explicit `<'a>` -- cxx has no
// lifetime elision -- is silenced here at module scope instead.
// cxx::bridge's own expansion mis-attributes a missing_errors_doc warning to the #[cxx::bridge]
// attribute's own span, though every Result-returning fn below already documents its `Err`
// condition.
/// Emit the per-instantiation `Opaque` handle for one `qvector<T>`: a zero-sized `!Unpin`
/// mirror struct plus its [`cxx::ExternType`] impl bound to the SDK type named by `$cxx`.
///
/// This is the reusable core of the recipe: the ExternType boilerplate that differs only by
/// `(RustName, "cxx_name")` per instantiation. The `#[cxx::bridge]` fn declarations and the
/// `impl UniquePtr<T> {}` container glue cannot be folded in here, because `cxx_build` parses
/// the source file textually (with `syn`) and cannot expand a `macro_rules!`, so anything it
/// must see, the bridge module itself, has to be written literally below.
qvec_opaque!;
qvec_opaque!;
pub use ;