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 #[allow(unused_mut)] fn op_bsearch(mut inner: Self::Inner<'_>, value: CowArg<'_, Self>, before: bool) -> i64 {
304 Self::with_arg(value, |arg| inner.bsearch(arg, before))
305 }
306
307 fn op_reverse(mut inner: Self::Inner<'_>) {
308 inner.reverse()
309 }
310
311 fn op_sort(mut inner: Self::Inner<'_>) {
312 inner.sort()
313 }
314
315 fn inner<'a>(array: &PackedArray<$Element>) -> Self::Inner<'a> {
316 crate::builtin::inner::$Inner::from_outer(array)
317 }
318
319 impl_packed_array_element!(@with_arg $ArgPass);
320 }
321 };
322
323 (@with_arg ByValue) => {
325 fn with_arg<F, R>(value: CowArg<'_, Self>, f: F) -> R
326 where
327 F: FnOnce(Self::Arg<'_>) -> R,
328 {
329 f(value.cow_into_owned().into())
331 }
332 };
333
334 (@with_arg ByRef) => {
335 fn with_arg<F, R>(value: CowArg<'_, Self>, f: F) -> R
336 where
337 F: FnOnce(Self::Arg<'_>) -> R,
338 {
339 f(value.cow_as_ref())
340 }
341 };
342}
343
344impl_packed_array_element!(
348 element_type: u8,
349 argument_type: i64,
350 argument_pass: ByValue,
351 indexed_type: u8,
352 variant_type: PACKED_BYTE_ARRAY,
353 inner_type: InnerPackedByteArray,
354 default_fn: packed_byte_array_construct_default,
355 copy_fn: packed_byte_array_construct_copy,
356 destroy_fn: packed_byte_array_destroy,
357 to_variant_fn: packed_byte_array_to_variant,
358 from_variant_fn: packed_byte_array_from_variant,
359 equals_fn: packed_byte_array_operator_equal,
360 index_mut_fn: packed_byte_array_operator_index,
361 index_const_fn: packed_byte_array_operator_index_const,
362);
363
364impl_packed_array_element!(
365 element_type: i32,
366 argument_type: i64,
367 argument_pass: ByValue,
368 indexed_type: i32,
369 variant_type: PACKED_INT32_ARRAY,
370 inner_type: InnerPackedInt32Array,
371 default_fn: packed_int32_array_construct_default,
372 copy_fn: packed_int32_array_construct_copy,
373 destroy_fn: packed_int32_array_destroy,
374 to_variant_fn: packed_int32_array_to_variant,
375 from_variant_fn: packed_int32_array_from_variant,
376 equals_fn: packed_int32_array_operator_equal,
377 index_mut_fn: packed_int32_array_operator_index,
378 index_const_fn: packed_int32_array_operator_index_const,
379);
380
381impl_packed_array_element!(
382 element_type: i64,
383 argument_type: i64,
384 argument_pass: ByValue,
385 indexed_type: i64,
386 variant_type: PACKED_INT64_ARRAY,
387 inner_type: InnerPackedInt64Array,
388 default_fn: packed_int64_array_construct_default,
389 copy_fn: packed_int64_array_construct_copy,
390 destroy_fn: packed_int64_array_destroy,
391 to_variant_fn: packed_int64_array_to_variant,
392 from_variant_fn: packed_int64_array_from_variant,
393 equals_fn: packed_int64_array_operator_equal,
394 index_mut_fn: packed_int64_array_operator_index,
395 index_const_fn: packed_int64_array_operator_index_const,
396);
397
398impl_packed_array_element!(
399 element_type: f32,
400 argument_type: f64,
401 argument_pass: ByValue,
402 indexed_type: f32,
403 variant_type: PACKED_FLOAT32_ARRAY,
404 inner_type: InnerPackedFloat32Array,
405 default_fn: packed_float32_array_construct_default,
406 copy_fn: packed_float32_array_construct_copy,
407 destroy_fn: packed_float32_array_destroy,
408 to_variant_fn: packed_float32_array_to_variant,
409 from_variant_fn: packed_float32_array_from_variant,
410 equals_fn: packed_float32_array_operator_equal,
411 index_mut_fn: packed_float32_array_operator_index,
412 index_const_fn: packed_float32_array_operator_index_const,
413);
414
415impl_packed_array_element!(
416 element_type: f64,
417 argument_type: f64,
418 argument_pass: ByValue,
419 indexed_type: f64,
420 variant_type: PACKED_FLOAT64_ARRAY,
421 inner_type: InnerPackedFloat64Array,
422 default_fn: packed_float64_array_construct_default,
423 copy_fn: packed_float64_array_construct_copy,
424 destroy_fn: packed_float64_array_destroy,
425 to_variant_fn: packed_float64_array_to_variant,
426 from_variant_fn: packed_float64_array_from_variant,
427 equals_fn: packed_float64_array_operator_equal,
428 index_mut_fn: packed_float64_array_operator_index,
429 index_const_fn: packed_float64_array_operator_index_const,
430);
431
432impl_packed_array_element!(
433 element_type: builtin::Vector2,
434 argument_type: builtin::Vector2,
435 argument_pass: ByValue,
436 indexed_type: sys::__GdextType,
437 variant_type: PACKED_VECTOR2_ARRAY,
438 inner_type: InnerPackedVector2Array,
439 default_fn: packed_vector2_array_construct_default,
440 copy_fn: packed_vector2_array_construct_copy,
441 destroy_fn: packed_vector2_array_destroy,
442 to_variant_fn: packed_vector2_array_to_variant,
443 from_variant_fn: packed_vector2_array_from_variant,
444 equals_fn: packed_vector2_array_operator_equal,
445 index_mut_fn: packed_vector2_array_operator_index,
446 index_const_fn: packed_vector2_array_operator_index_const,
447);
448
449impl_packed_array_element!(
450 element_type: builtin::Vector3,
451 argument_type: builtin::Vector3,
452 argument_pass: ByValue,
453 indexed_type: sys::__GdextType,
454 variant_type: PACKED_VECTOR3_ARRAY,
455 inner_type: InnerPackedVector3Array,
456 default_fn: packed_vector3_array_construct_default,
457 copy_fn: packed_vector3_array_construct_copy,
458 destroy_fn: packed_vector3_array_destroy,
459 to_variant_fn: packed_vector3_array_to_variant,
460 from_variant_fn: packed_vector3_array_from_variant,
461 equals_fn: packed_vector3_array_operator_equal,
462 index_mut_fn: packed_vector3_array_operator_index,
463 index_const_fn: packed_vector3_array_operator_index_const,
464);
465
466#[cfg(since_api = "4.3")] #[cfg_attr(published_docs, doc(cfg(since_api = "4.3")))]
467impl_packed_array_element!(
468 element_type: builtin::Vector4,
469 argument_type: builtin::Vector4,
470 argument_pass: ByValue,
471 indexed_type: sys::__GdextType,
472 variant_type: PACKED_VECTOR4_ARRAY,
473 inner_type: InnerPackedVector4Array,
474 default_fn: packed_vector4_array_construct_default,
475 copy_fn: packed_vector4_array_construct_copy,
476 destroy_fn: packed_vector4_array_destroy,
477 to_variant_fn: packed_vector4_array_to_variant,
478 from_variant_fn: packed_vector4_array_from_variant,
479 equals_fn: packed_vector4_array_operator_equal,
480 index_mut_fn: packed_vector4_array_operator_index,
481 index_const_fn: packed_vector4_array_operator_index_const,
482);
483
484impl_packed_array_element!(
485 element_type: builtin::Color,
486 argument_type: builtin::Color,
487 argument_pass: ByValue,
488 indexed_type: sys::__GdextType,
489 variant_type: PACKED_COLOR_ARRAY,
490 inner_type: InnerPackedColorArray,
491 default_fn: packed_color_array_construct_default,
492 copy_fn: packed_color_array_construct_copy,
493 destroy_fn: packed_color_array_destroy,
494 to_variant_fn: packed_color_array_to_variant,
495 from_variant_fn: packed_color_array_from_variant,
496 equals_fn: packed_color_array_operator_equal,
497 index_mut_fn: packed_color_array_operator_index,
498 index_const_fn: packed_color_array_operator_index_const,
499);
500
501impl_packed_array_element!(
502 element_type: builtin::GString,
503 argument_type: &'a builtin::GString,
504 argument_pass: ByRef,
505 indexed_type: sys::__GdextString,
506 variant_type: PACKED_STRING_ARRAY,
507 inner_type: InnerPackedStringArray,
508 default_fn: packed_string_array_construct_default,
509 copy_fn: packed_string_array_construct_copy,
510 destroy_fn: packed_string_array_destroy,
511 to_variant_fn: packed_string_array_to_variant,
512 from_variant_fn: packed_string_array_from_variant,
513 equals_fn: packed_string_array_operator_equal,
514 index_mut_fn: packed_string_array_operator_index,
515 index_const_fn: packed_string_array_operator_index_const,
516);