1use sys::{interface_fn, GodotFfi, SysPtr};
9
10use crate::builtin::collections::extend_buffer::{ExtendBuffer, ExtendBufferTrait};
11use crate::builtin::PackedArray;
12use crate::meta::signed_range::SignedRange;
13use crate::meta::{CowArg, FromGodot, GodotType, ToGodot};
14use crate::registry::property::builtin_type_string;
15use crate::{builtin, sys};
16
17#[diagnostic::on_unimplemented(
19 message = "`PackedArray<T>` can only store element types supported in Godot packed arrays.",
20 label = "has invalid element type"
21)]
22pub trait PackedArrayElement: GodotType + Clone + ToGodot + FromGodot {
25 #[doc(hidden)]
27 const VARIANT_TYPE: sys::VariantType;
28
29 #[doc(hidden)]
31 type Inner<'a>;
32
33 #[doc(hidden)]
35 type Arg<'a>;
36
37 #[doc(hidden)]
39 type Indexed;
40
41 #[doc(hidden)]
43 type ExtendBuffer: Default + ExtendBufferTrait<Self>;
44
45 #[doc(hidden)]
50 fn element_type_string() -> String {
51 builtin_type_string::<Self>()
52 }
53
54 #[doc(hidden)]
58 unsafe fn ffi_to_variant(
59 type_ptr: sys::GDExtensionConstTypePtr,
60 variant_ptr: sys::GDExtensionVariantPtr,
61 );
62
63 #[doc(hidden)]
64 unsafe fn ffi_from_variant(
65 variant_ptr: sys::GDExtensionConstVariantPtr,
66 type_ptr: sys::GDExtensionTypePtr,
67 );
68
69 #[doc(hidden)]
70 unsafe fn ffi_default(type_ptr: sys::GDExtensionTypePtr);
71
72 #[doc(hidden)]
73 unsafe fn ffi_copy(src_ptr: sys::GDExtensionConstTypePtr, dst_ptr: sys::GDExtensionTypePtr);
74
75 #[doc(hidden)]
76 unsafe fn ffi_destroy(type_ptr: sys::GDExtensionTypePtr);
77
78 #[doc(hidden)]
79 unsafe fn ffi_equals(
80 left_ptr: sys::GDExtensionConstTypePtr,
81 right_ptr: sys::GDExtensionConstTypePtr,
82 ) -> bool;
83
84 #[doc(hidden)]
85 unsafe fn ffi_index_const(
86 type_ptr: sys::GDExtensionConstTypePtr,
87 index: i64,
88 ) -> *const Self::Indexed;
89
90 #[doc(hidden)]
91 unsafe fn ffi_index_mut(type_ptr: sys::GDExtensionTypePtr, index: i64) -> *mut Self::Indexed;
92
93 #[doc(hidden)]
97 fn op_has(inner: Self::Inner<'_>, value: CowArg<'_, Self>) -> bool;
98
99 #[doc(hidden)]
100 fn op_count(inner: Self::Inner<'_>, value: CowArg<'_, Self>) -> i64;
101
102 #[doc(hidden)]
103 fn op_size(inner: Self::Inner<'_>) -> i64;
104
105 #[doc(hidden)]
106 fn op_is_empty(inner: Self::Inner<'_>) -> bool;
107
108 #[doc(hidden)]
109 fn op_clear(inner: Self::Inner<'_>);
110
111 #[doc(hidden)]
112 fn op_push_back(inner: Self::Inner<'_>, value: CowArg<'_, Self>);
113
114 #[doc(hidden)]
115 fn op_insert(inner: Self::Inner<'_>, index: i64, value: CowArg<'_, Self>);
116
117 #[doc(hidden)]
118 fn op_remove_at(inner: Self::Inner<'_>, index: i64);
119
120 #[doc(hidden)]
121 fn op_fill(inner: Self::Inner<'_>, value: CowArg<'_, Self>);
122
123 #[doc(hidden)]
124 fn op_resize(inner: Self::Inner<'_>, size: i64);
125
126 #[doc(hidden)]
127 fn op_append_array(inner: Self::Inner<'_>, other: &PackedArray<Self>);
128
129 #[doc(hidden)]
130 fn op_slice(inner: Self::Inner<'_>, range: impl SignedRange) -> PackedArray<Self>;
131
132 #[doc(hidden)]
133 fn op_find(inner: Self::Inner<'_>, value: CowArg<'_, Self>, from: i64) -> i64;
134
135 #[doc(hidden)]
136 fn op_rfind(inner: Self::Inner<'_>, value: CowArg<'_, Self>, from: i64) -> i64;
137
138 #[doc(hidden)]
139 fn op_bsearch(inner: Self::Inner<'_>, value: CowArg<'_, Self>, before: bool) -> i64;
140
141 #[doc(hidden)]
142 fn op_reverse(inner: Self::Inner<'_>);
143
144 #[doc(hidden)]
145 fn op_sort(inner: Self::Inner<'_>);
146
147 #[doc(hidden)]
148 fn inner<'a>(array: &PackedArray<Self>) -> Self::Inner<'a>;
149
150 #[doc(hidden)]
155 fn with_arg<F, R>(value: CowArg<'_, Self>, f: F) -> R
156 where
157 F: FnOnce(Self::Arg<'_>) -> R;
158}
159
160const fn const_max(a: usize, b: usize) -> usize {
162 if a > b {
163 a
164 } else {
165 b
166 }
167}
168
169macro_rules! impl_packed_array_element {
173 (
174 element_type: $Element:ty,
175 argument_type: $Arg:ty,
176 argument_pass: $ArgPass:ident,
177 indexed_type: $IndexRetType:ty,
178 variant_type: $VariantType:ident,
179 inner_type: $Inner:ident,
180 default_fn: $default_fn:ident,
181 copy_fn: $copy_fn:ident,
182 destroy_fn: $destroy_fn:ident,
183 to_variant_fn: $to_variant_fn:ident,
184 from_variant_fn: $from_variant_fn:ident,
185 equals_fn: $equals_fn:ident,
186 index_mut_fn: $index_mut_fn:ident,
187 index_const_fn: $index_const_fn:ident,
188 ) => {
189 impl PackedArrayElement for $Element {
190 const VARIANT_TYPE: sys::VariantType = sys::VariantType::$VariantType;
191
192 type Inner<'a> = crate::builtin::inner::$Inner<'a>;
193 type Arg<'a> = $Arg;
194 type Indexed = $IndexRetType;
195 type ExtendBuffer = ExtendBuffer<$Element, {
196 const_max(1, 2048 / std::mem::size_of::<$Element>())
197 }>;
198
199 unsafe fn ffi_default(type_ptr: sys::GDExtensionTypePtr) {
200 let constructor = sys::builtin_fn!($default_fn);
201 constructor(SysPtr::as_uninit(type_ptr), std::ptr::null_mut());
202 }
203
204 unsafe fn ffi_copy(src_ptr: sys::GDExtensionConstTypePtr, dst_ptr: sys::GDExtensionTypePtr) {
205 let constructor = sys::builtin_fn!($copy_fn);
206 let args = [src_ptr];
207 constructor(SysPtr::as_uninit(dst_ptr), args.as_ptr());
208 }
209
210 unsafe fn ffi_destroy(type_ptr: sys::GDExtensionTypePtr) {
211 let destructor = sys::builtin_fn!($destroy_fn @1);
212 destructor(type_ptr);
213 }
214
215 unsafe fn ffi_to_variant(type_ptr: sys::GDExtensionConstTypePtr, variant_ptr: sys::GDExtensionVariantPtr) {
216 let converter = sys::builtin_fn!($to_variant_fn);
217 converter(SysPtr::as_uninit(variant_ptr), SysPtr::force_mut(type_ptr));
218 }
219
220 unsafe fn ffi_from_variant(variant_ptr: sys::GDExtensionConstVariantPtr, type_ptr: sys::GDExtensionTypePtr) {
221 let converter = sys::builtin_fn!($from_variant_fn);
222 converter(SysPtr::as_uninit(type_ptr), SysPtr::force_mut(variant_ptr));
223 }
224
225 unsafe fn ffi_equals(left_ptr: sys::GDExtensionConstTypePtr, right_ptr: sys::GDExtensionConstTypePtr) -> bool {
226 let mut result = false;
227 sys::builtin_call! {
228 $equals_fn(left_ptr, right_ptr, result.sys_mut())
229 };
230 result
231 }
232
233 unsafe fn ffi_index_const(type_ptr: sys::GDExtensionConstTypePtr, index: i64) -> *const Self::Indexed {
234 unsafe {
235 interface_fn!($index_const_fn)(type_ptr, index)
236 }
237 }
238
239 unsafe fn ffi_index_mut(type_ptr: sys::GDExtensionTypePtr, index: i64) -> *mut Self::Indexed {
240 unsafe {
241 interface_fn!($index_mut_fn)(type_ptr, index)
242 }
243 }
244
245 fn op_has(inner: Self::Inner<'_>, value: CowArg<'_, Self>) -> bool {
246 Self::with_arg(value, |arg| inner.has(arg))
247 }
248
249 fn op_count(inner: Self::Inner<'_>, value: CowArg<'_, Self>) -> i64 {
250 Self::with_arg(value, |arg| inner.count(arg))
251 }
252
253 fn op_size(inner: Self::Inner<'_>) -> i64 {
254 inner.size()
255 }
256
257 fn op_is_empty(inner: Self::Inner<'_>) -> bool {
258 inner.is_empty()
259 }
260
261 fn op_clear(mut inner: Self::Inner<'_>) {
262 inner.clear();
263 }
264
265 fn op_push_back(mut inner: Self::Inner<'_>, value: CowArg<'_, Self>) {
266 Self::with_arg(value, |arg| inner.push_back(arg));
267 }
268
269 fn op_insert(mut inner: Self::Inner<'_>, index: i64, value: CowArg<'_, Self>) {
270 Self::with_arg(value, |arg| inner.insert(index, arg));
271 }
272
273 fn op_remove_at(mut inner: Self::Inner<'_>, index: i64) {
274 inner.remove_at(index);
275 }
276
277 fn op_fill(mut inner: Self::Inner<'_>, value: CowArg<'_, Self>) {
278 Self::with_arg(value, |arg| inner.fill(arg));
279 }
280
281 fn op_resize(mut inner: Self::Inner<'_>, size: i64) {
282 inner.resize(size);
283 }
284
285 fn op_append_array(mut inner: Self::Inner<'_>, other: &PackedArray<Self>) {
286 inner.append_array(other);
287 }
288
289 fn op_slice(inner: Self::Inner<'_>, range: impl $crate::meta::signed_range::SignedRange) -> PackedArray<Self> {
290 let (begin, end) = range.signed();
291 inner.slice(begin, end.unwrap_or(i32::MAX as i64))
292 }
293
294 fn op_find(inner: Self::Inner<'_>, value: CowArg<'_, Self>, from: i64) -> i64 {
295 Self::with_arg(value, |arg| inner.find(arg, from))
296 }
297
298 fn op_rfind(inner: Self::Inner<'_>, value: CowArg<'_, Self>, from: i64) -> i64 {
299 Self::with_arg(value, |arg| inner.rfind(arg, from))
300 }
301
302 fn op_bsearch(mut inner: Self::Inner<'_>, value: CowArg<'_, Self>, before: bool) -> i64 {
303 Self::with_arg(value, |arg| inner.bsearch(arg, before))
304 }
305
306 fn op_reverse(mut inner: Self::Inner<'_>) {
307 inner.reverse()
308 }
309
310 fn op_sort(mut inner: Self::Inner<'_>) {
311 inner.sort()
312 }
313
314 fn inner<'a>(array: &PackedArray<$Element>) -> Self::Inner<'a> {
315 crate::builtin::inner::$Inner::from_outer(array)
316 }
317
318 impl_packed_array_element!(@with_arg $ArgPass);
319 }
320 };
321
322 (@with_arg ByValue) => {
324 fn with_arg<F, R>(value: CowArg<'_, Self>, f: F) -> R
325 where
326 F: FnOnce(Self::Arg<'_>) -> R,
327 {
328 f(value.cow_into_owned().into())
330 }
331 };
332
333 (@with_arg ByRef) => {
334 fn with_arg<F, R>(value: CowArg<'_, Self>, f: F) -> R
335 where
336 F: FnOnce(Self::Arg<'_>) -> R,
337 {
338 f(value.cow_as_ref())
339 }
340 };
341}
342
343impl_packed_array_element!(
347 element_type: u8,
348 argument_type: i64,
349 argument_pass: ByValue,
350 indexed_type: u8,
351 variant_type: PACKED_BYTE_ARRAY,
352 inner_type: InnerPackedByteArray,
353 default_fn: packed_byte_array_construct_default,
354 copy_fn: packed_byte_array_construct_copy,
355 destroy_fn: packed_byte_array_destroy,
356 to_variant_fn: packed_byte_array_to_variant,
357 from_variant_fn: packed_byte_array_from_variant,
358 equals_fn: packed_byte_array_operator_equal,
359 index_mut_fn: packed_byte_array_operator_index,
360 index_const_fn: packed_byte_array_operator_index_const,
361);
362
363impl_packed_array_element!(
364 element_type: i32,
365 argument_type: i64,
366 argument_pass: ByValue,
367 indexed_type: i32,
368 variant_type: PACKED_INT32_ARRAY,
369 inner_type: InnerPackedInt32Array,
370 default_fn: packed_int32_array_construct_default,
371 copy_fn: packed_int32_array_construct_copy,
372 destroy_fn: packed_int32_array_destroy,
373 to_variant_fn: packed_int32_array_to_variant,
374 from_variant_fn: packed_int32_array_from_variant,
375 equals_fn: packed_int32_array_operator_equal,
376 index_mut_fn: packed_int32_array_operator_index,
377 index_const_fn: packed_int32_array_operator_index_const,
378);
379
380impl_packed_array_element!(
381 element_type: i64,
382 argument_type: i64,
383 argument_pass: ByValue,
384 indexed_type: i64,
385 variant_type: PACKED_INT64_ARRAY,
386 inner_type: InnerPackedInt64Array,
387 default_fn: packed_int64_array_construct_default,
388 copy_fn: packed_int64_array_construct_copy,
389 destroy_fn: packed_int64_array_destroy,
390 to_variant_fn: packed_int64_array_to_variant,
391 from_variant_fn: packed_int64_array_from_variant,
392 equals_fn: packed_int64_array_operator_equal,
393 index_mut_fn: packed_int64_array_operator_index,
394 index_const_fn: packed_int64_array_operator_index_const,
395);
396
397impl_packed_array_element!(
398 element_type: f32,
399 argument_type: f64,
400 argument_pass: ByValue,
401 indexed_type: f32,
402 variant_type: PACKED_FLOAT32_ARRAY,
403 inner_type: InnerPackedFloat32Array,
404 default_fn: packed_float32_array_construct_default,
405 copy_fn: packed_float32_array_construct_copy,
406 destroy_fn: packed_float32_array_destroy,
407 to_variant_fn: packed_float32_array_to_variant,
408 from_variant_fn: packed_float32_array_from_variant,
409 equals_fn: packed_float32_array_operator_equal,
410 index_mut_fn: packed_float32_array_operator_index,
411 index_const_fn: packed_float32_array_operator_index_const,
412);
413
414impl_packed_array_element!(
415 element_type: f64,
416 argument_type: f64,
417 argument_pass: ByValue,
418 indexed_type: f64,
419 variant_type: PACKED_FLOAT64_ARRAY,
420 inner_type: InnerPackedFloat64Array,
421 default_fn: packed_float64_array_construct_default,
422 copy_fn: packed_float64_array_construct_copy,
423 destroy_fn: packed_float64_array_destroy,
424 to_variant_fn: packed_float64_array_to_variant,
425 from_variant_fn: packed_float64_array_from_variant,
426 equals_fn: packed_float64_array_operator_equal,
427 index_mut_fn: packed_float64_array_operator_index,
428 index_const_fn: packed_float64_array_operator_index_const,
429);
430
431impl_packed_array_element!(
432 element_type: builtin::Vector2,
433 argument_type: builtin::Vector2,
434 argument_pass: ByValue,
435 indexed_type: sys::__GdextType,
436 variant_type: PACKED_VECTOR2_ARRAY,
437 inner_type: InnerPackedVector2Array,
438 default_fn: packed_vector2_array_construct_default,
439 copy_fn: packed_vector2_array_construct_copy,
440 destroy_fn: packed_vector2_array_destroy,
441 to_variant_fn: packed_vector2_array_to_variant,
442 from_variant_fn: packed_vector2_array_from_variant,
443 equals_fn: packed_vector2_array_operator_equal,
444 index_mut_fn: packed_vector2_array_operator_index,
445 index_const_fn: packed_vector2_array_operator_index_const,
446);
447
448impl_packed_array_element!(
449 element_type: builtin::Vector3,
450 argument_type: builtin::Vector3,
451 argument_pass: ByValue,
452 indexed_type: sys::__GdextType,
453 variant_type: PACKED_VECTOR3_ARRAY,
454 inner_type: InnerPackedVector3Array,
455 default_fn: packed_vector3_array_construct_default,
456 copy_fn: packed_vector3_array_construct_copy,
457 destroy_fn: packed_vector3_array_destroy,
458 to_variant_fn: packed_vector3_array_to_variant,
459 from_variant_fn: packed_vector3_array_from_variant,
460 equals_fn: packed_vector3_array_operator_equal,
461 index_mut_fn: packed_vector3_array_operator_index,
462 index_const_fn: packed_vector3_array_operator_index_const,
463);
464
465#[cfg(since_api = "4.3")] #[cfg_attr(published_docs, doc(cfg(since_api = "4.3")))]
466impl_packed_array_element!(
467 element_type: builtin::Vector4,
468 argument_type: builtin::Vector4,
469 argument_pass: ByValue,
470 indexed_type: sys::__GdextType,
471 variant_type: PACKED_VECTOR4_ARRAY,
472 inner_type: InnerPackedVector4Array,
473 default_fn: packed_vector4_array_construct_default,
474 copy_fn: packed_vector4_array_construct_copy,
475 destroy_fn: packed_vector4_array_destroy,
476 to_variant_fn: packed_vector4_array_to_variant,
477 from_variant_fn: packed_vector4_array_from_variant,
478 equals_fn: packed_vector4_array_operator_equal,
479 index_mut_fn: packed_vector4_array_operator_index,
480 index_const_fn: packed_vector4_array_operator_index_const,
481);
482
483impl_packed_array_element!(
484 element_type: builtin::Color,
485 argument_type: builtin::Color,
486 argument_pass: ByValue,
487 indexed_type: sys::__GdextType,
488 variant_type: PACKED_COLOR_ARRAY,
489 inner_type: InnerPackedColorArray,
490 default_fn: packed_color_array_construct_default,
491 copy_fn: packed_color_array_construct_copy,
492 destroy_fn: packed_color_array_destroy,
493 to_variant_fn: packed_color_array_to_variant,
494 from_variant_fn: packed_color_array_from_variant,
495 equals_fn: packed_color_array_operator_equal,
496 index_mut_fn: packed_color_array_operator_index,
497 index_const_fn: packed_color_array_operator_index_const,
498);
499
500impl_packed_array_element!(
501 element_type: builtin::GString,
502 argument_type: &'a builtin::GString,
503 argument_pass: ByRef,
504 indexed_type: sys::__GdextString,
505 variant_type: PACKED_STRING_ARRAY,
506 inner_type: InnerPackedStringArray,
507 default_fn: packed_string_array_construct_default,
508 copy_fn: packed_string_array_construct_copy,
509 destroy_fn: packed_string_array_destroy,
510 to_variant_fn: packed_string_array_to_variant,
511 from_variant_fn: packed_string_array_from_variant,
512 equals_fn: packed_string_array_operator_equal,
513 index_mut_fn: packed_string_array_operator_index,
514 index_const_fn: packed_string_array_operator_index_const,
515);