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
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
/// Internal helper. Generates a `#[repr(transparent)]` newtype wrapping an
/// FFI value, with `Drop` calling the supplied `Unload*` raylib function.
///
/// Use this when a raylib type is owned by Rust outright (no parent handle
/// keeps it alive). The generated wrapper is `Debug`, has a private
/// positional field, and gets the standard set of impls from
/// `impl_wrapper!`, `gen_from_raw_wrapper!`, and (by default)
/// `deref_impl_wrapper!`. Pass a trailing `false` to suppress the
/// `Deref` / `DerefMut` / `AsRef` / `AsMut` impls when the wrapper should
/// hide its inner FFI value (e.g. when an explicit accessor API is
/// preferred — see `AutomationEventList`).
///
/// The wrapper struct is `!Send` / `!Sync` only insofar as the wrapped FFI
/// type is — most raylib types are non-thread-safe by construction, so in
/// practice these wrappers must stay on the raylib thread.
///
/// Expansion shape (conceptual):
///
/// ```text
/// #[repr(transparent)]
/// #[derive(Debug)]
/// pub struct $name(pub(crate) $t);
///
/// // Always:
/// impl Drop for $name { fn drop(&mut self) { ($dropfunc)(self.0); } }
/// impl $name { pub unsafe fn unwrap(self) -> $t { ... } }
/// // With the default (`, true`) variant:
/// impl AsRef<$t> for $name { ... }
/// impl AsMut<$t> for $name { ... }
/// impl Deref for $name { type Target = $t; ... }
/// impl DerefMut for $name { ... }
/// impl $name { pub fn to_raw(self) -> $t { ... } pub unsafe fn from_raw(raw: $t) -> Self { ... } }
/// ```
///
/// Used internally to wrap `Image`, `Texture2D`, `RenderTexture2D`, `Font`,
/// `Mesh`, `Shader`, `Material`, `Model`, `ModelAnimation`, `VrStereoConfig`,
/// `FilePathList`, `AutomationEventList`, `AutomationEvent`, and the
/// borrow-checker-only `Weak*` aliases (which pass a no-op `no_drop`
/// function so they don't free the inner value).
/// Internal helper. Like [`make_thin_wrapper!`] but with a lifetime
/// parameter that ties the wrapped FFI value to a parent borrow.
///
/// Use this when a raylib resource is logically owned by another handle —
/// e.g. every [`Wave`], [`Sound`], [`Music`], and [`AudioStream`] is bound
/// to the lifetime of the `RaylibAudio` that initialised the audio device.
/// The generated struct holds an extra `&'a $t2` field so the borrow
/// checker prevents the child outliving its parent. As with
/// [`make_thin_wrapper!`], a trailing `false` suppresses the `Deref` /
/// `AsRef` family for wrappers that want a hand-written accessor surface.
///
/// Expansion shape (conceptual):
///
/// ```text
/// #[derive(Debug)]
/// pub struct $name<'a>(pub(crate) $t1, &'a $t2);
///
/// // Always:
/// impl<'a> Drop for $name<'a> { fn drop(&mut self) { ($dropfunc)(self.0); } }
/// impl<'a> $name<'a> { pub unsafe fn unwrap(self) -> $t1 { ... } }
/// // With the default (`, true`) variant:
/// impl<'a> AsRef<$t1> for $name<'a> { ... }
/// impl<'a> AsMut<$t1> for $name<'a> { ... }
/// impl<'a> Deref for $name<'a> { type Target = $t1; ... }
/// impl<'a> DerefMut for $name<'a> { ... }
/// ```
///
/// Note: this macro deliberately does **not** invoke
/// `gen_from_raw_wrapper!`, because constructing a lifetime-bound wrapper
/// from a raw FFI value requires a matching borrow of the parent — the
/// owning module supplies its own constructors (e.g.
/// `RaylibAudio::new_sound`) instead.
///
/// [`Wave`]: crate::core::audio::Wave
/// [`Sound`]: crate::core::audio::Sound
/// [`Music`]: crate::core::audio::Music
/// [`AudioStream`]: crate::core::audio::AudioStream
/// Internal helper. Emits the always-present pieces of a thin wrapper:
/// the `Drop` impl that calls `$dropfunc`, and an `unsafe fn unwrap`
/// associated function that consumes the wrapper and returns the raw FFI
/// value without running `Drop` (the caller takes over freeing it).
///
/// Invoked from inside [`make_thin_wrapper!`] and
/// [`make_thin_wrapper_lifetime!`] — not intended as a standalone entry
/// point. The optional `$lifetime` token lets the same expansion serve
/// both the non-generic and `<'a>`-generic wrappers.
///
/// Expansion shape (conceptual):
///
/// ```text
/// impl[<'a>] $name[<'a>] {
/// pub unsafe fn unwrap(self) -> $t { /* mem::forget(self) and return inner */ }
/// }
/// impl[<'a>] Drop for $name[<'a>] {
/// fn drop(&mut self) { unsafe { ($dropfunc)(self.$rawfield); } }
/// }
/// ```
/// Internal helper. Emits the raw-FFI conversion surface for wrappers that
/// can be freely constructed from a raylib-sys value:
///
/// * `to_raw(self) -> $t` — non-`unsafe` counterpart of `unwrap`, used when
/// the destination type doesn't need callers to think about ownership
/// ceremony beyond "you now own this raylib resource."
/// * `unsafe fn from_raw(raw: $t) -> Self` — takes ownership of an FFI
/// value loaded elsewhere (e.g. from raylib functions that return by
/// value) and wraps it for RAII cleanup.
///
/// Invoked from [`make_thin_wrapper!`]. Deliberately **omitted** from
/// [`make_thin_wrapper_lifetime!`] expansions because a lifetime-bound
/// child needs an explicit borrow of its parent that this macro can't
/// supply.
///
/// Expansion shape (conceptual):
///
/// ```text
/// impl[<'a>] $name[<'a>] {
/// pub fn to_raw(self) -> $t { /* mem::forget + return */ }
/// pub unsafe fn from_raw(raw: $t) -> Self { Self(raw) }
/// }
/// ```
/// Internal helper. Emits the `AsRef` / `AsMut` / `Deref` / `DerefMut`
/// impls that expose the wrapped FFI value as the wrapper's `Target`.
///
/// Use this when callers should be able to pass `&wrapper` everywhere a
/// `&ffi::T` is expected — that lets the safe wrappers participate in
/// raylib's FFI surface without needing a separate `.as_raw()` call. Some
/// wrappers (e.g. `AutomationEventList`) opt out by passing the trailing
/// `false` to [`make_thin_wrapper!`], because they want to expose a
/// hand-written, type-safe accessor API rather than handing out the raw
/// FFI struct.
///
/// Expansion shape (conceptual):
///
/// ```text
/// impl[<'a>] AsRef<$t> for $name[<'a>] { fn as_ref(&self) -> &$t { &self.$rawfield } }
/// impl[<'a>] AsMut<$t> for $name[<'a>] { fn as_mut(&mut self) -> &mut $t { &mut self.$rawfield } }
/// impl[<'a>] Deref for $name[<'a>] { type Target = $t; fn deref(&self) -> &$t { ... } }
/// impl[<'a>] DerefMut for $name[<'a>] { fn deref_mut(&mut self) -> &mut $t { ... } }
/// ```
/// Internal helper. Generates a wrapper for a raylib-allocated slice
/// (`ManuallyDrop<Box<[T]>>`) that is freed via the supplied
/// `Unload*` / `MemFree` function instead of the global Rust allocator.
///
/// raylib functions like `LoadImageColors` and `LoadImagePalette` return a
/// pointer plus a length — Rust can borrow that as a `Box<[T]>` for safe
/// indexed access, but **must not** let `Box`'s `Drop` call `free()` on
/// the buffer because raylib may have been built with a custom allocator
/// (see `DECISIONS.md`). The wrapper holds the box inside
/// [`std::mem::ManuallyDrop`] and routes its own `Drop` through
/// `$dropfunc` (typically `ffi::UnloadImageColors`,
/// `ffi::UnloadImagePalette`, or `MemFree`).
///
/// Used internally for `ImagePalette` and `ImageColors`.
///
/// Expansion shape (conceptual):
///
/// ```text
/// #[repr(transparent)]
/// #[derive(Debug)]
/// pub struct $name(pub(crate) std::mem::ManuallyDrop<Box<[$t]>>);
///
/// impl Drop for $name { /* takes the Box, leaks it back to raw, and calls ($dropfunc)(ptr) */ }
/// impl AsRef<Box<[$t]>> for $name { ... }
/// impl AsMut<Box<[$t]>> for $name { ... }
/// impl Deref for $name { type Target = Box<[$t]>; ... }
/// impl DerefMut for $name { ... }
/// ```
/// Internal helper. Emits the `Drop` + `AsRef` / `AsMut` / `Deref` /
/// `DerefMut` impls for an rslice wrapper produced by [`make_rslice!`].
///
/// The `Drop` impl is the load-bearing piece: it takes the inner
/// `ManuallyDrop<Box<[T]>>`, calls `Box::leak` to recover the raw pointer
/// without running the global allocator's free, and then hands that
/// pointer to `$dropfunc` (the matching raylib `Unload*` /
/// `MemFree`). This keeps the wrapper correct under raylib builds that
/// use a custom allocator.
///
/// Not intended to be called outside of [`make_rslice!`].
///
/// Expansion shape (conceptual):
///
/// ```text
/// impl Drop for $name { /* see above */ }
/// impl AsRef<Box<[T]>> for $name { ... }
/// impl AsMut<Box<[T]>> for $name { ... }
/// impl Deref for $name { type Target = Box<[T]>; ... }
/// impl DerefMut for $name { ... }
/// ```