# How to Use Typed Arrays versus Packed Arrays in gdext-nim

> Learn when to use typed arrays Array[T] versus Packed*Array in gdext-nim. Optimize performance with homogeneous primitive storage or flexible Variant collections.

- Repository: [godot-nim 4+/gdext-nim](https://github.com/godot-nim/gdext-nim)
- Tags: how-to-guide
- Published: 2026-03-02

---

**In gdext-nim, use generic `Array[T]` (typed arrays) for flexible collections of mixed Godot Variants, and `Packed*Array` types for maximum-performance storage of homogeneous primitives.**

The gdext-nim framework provides two distinct container families for managing collections in Godot 4. Understanding when to use **typed arrays versus packed arrays in gdext** is essential for writing performant Nim game code. This guide examines the implementation details found in the `godot-nim/gdext-nim` repository to help you choose the right container for your data.

## Core Architecture: Variant Arrays vs Packed Arrays

### Typed Arrays (Array[T])

In `src/gdext/arraytools.nim`, the generic `Array[T]` type wraps Godot's native Variant array. Despite the compile-time generic `T`, the runtime storage remains a list of Godot Variants. This design allows heterogeneous content but adds per-element overhead.

The implementation uses two helper procedures for safe casting between typed and generic forms:

```nim
proc wild[T](self: Array[T]): Array[Variant] =
  when T is Variant: self 
  else: cast[ptr Array[Variant]](addr self)[]

proc specified[T](self: Array[Variant]; Type: typedesc[T]): Array[T] =
  when T is Variant: self 
  else: cast[ptr Array[T]](addr self)[]

```

### Packed Arrays

Located in `src/gdext/gen/` (e.g., `gdpackedstringarray.nim`, `gdpackedint32array.nim`, `gdpackedvector3array.nim`), these types store homogeneous primitives in contiguous C-style memory without Variant overhead. They expose the same API methods (`size`, `pushBack`, `clear`) but call Godot's native packed-array methods directly.

## Creating and Converting Typed Arrays

### Storing Custom Objects

Use `Array[T]` when you need type safety at compile time while maintaining compatibility with Godot's Variant system:

```nim
import gdext

type MyNode = ref object of Node
registerClass(MyNode)

let node = MyNode.new()
var objs = newArray[MyNode]()      # typed array with T = MyNode

objs.pushBack(node)                # stored internally as Variant

echo objs.size                     # → 1

echo objs[0].className            # → "MyNode"

```

### Converting Between Typed and Variant Arrays

You can implicitly convert typed arrays to generic Variant arrays using the `wild` cast, and return to the original type using `specified`:

```nim
var intArr = newArray[int](3)
intArr[0] = 10
intArr[1] = 20
intArr[2] = 30

let varArr: Array[Variant] = intArr   # implicit conversion via wild

let back: Array[int] = varArr.specified(int)  # cast back via specified

echo back[1]   # → 20

```

## Working with Packed Arrays

### Basic Packed String Operations

For string collections requiring maximum efficiency, use `PackedStringArray` defined in `src/gdext/gen/gdpackedstringarray.nim`:

```nim
import gdext

var pStr = newPackedStringArray()
pStr.pushBack("hello")
pStr.pushBack("world")
echo pStr.size                     # → 2

echo pStr[0]                       # → "hello"

```

### Converting Typed Arrays to Packed Arrays

When you need to transform a flexible `Array[Variant]` into an efficient packed format, use the constructor defined in `src/gdext/gen/gdpackedstringarrayconstr.nim`:

```nim
var varArr = newArray[Variant]()
varArr.pushBack("one")
varArr.pushBack("two")
varArr.pushBack("three")

let packed = newPackedStringArray(varArr)  # constructor from Variant array

echo packed.size          # → 3

echo packed[2]            # → "three"

```

This conversion attempts to cast each Variant element to the packed type and fails at runtime if a value cannot be converted.

## Integration with Godot APIs

Certain Godot methods explicitly require packed arrays for low-level data operations. For example, mesh construction requires `PackedVector3Array` for vertex data:

```nim
import gdext

var verts = newPackedVector3Array()
verts.pushBack(Vector3(0, 0, 0))
verts.pushBack(Vector3(1, 0, 0))
verts.pushBack(Vector3(0, 1, 0))

let mesh = ArrayMesh.new()
mesh.addSurfaceFromArrays(
  PrimitiveType.Triangles,
  [ArrayMesh.ArrayFormat.Vertex, verts]  # packed array passed directly

)

```

## When to Choose Which Container

- **Use `Array[T]`** when you need heterogeneous content (different object types), compatibility with Godot APIs accepting generic Variants, or storage of user-defined objects implementing `toVariant`/`fromVariant`.

- **Use `Packed*Array`** when processing large homogeneous datasets (mesh vertices, audio samples, string tables), interacting with low-level Godot methods requiring packed buffers, or when memory efficiency and cache locality are critical.

## Summary

- **Typed arrays** (`Array[T]`) in `src/gdext/arraytools.nim` provide compile-time type safety over Godot's underlying Variant array storage, using `wild` and `specified` casts for type conversion.
- **Packed arrays** (`PackedStringArray`, `PackedByteArray`, etc.) in `src/gdext/gen/` store homogeneous primitives in contiguous memory without Variant overhead.
- Convert between the two using constructors like `newPackedStringArray(from: Array[Variant])` found in `src/gdext/gen/gdpackedstringarrayconstr.nim`.
- Choose typed arrays for flexibility and packed arrays for performance-critical primitive data.

## Frequently Asked Questions

### Can I store custom Nim objects in a PackedArray?

No. Packed arrays only store homogeneous native primitives like `String`, `int32`, `float64`, or `Vector3`. Custom classes and heterogeneous collections require `Array[T]` (typed arrays), which store elements as Godot Variants internally according to the implementation in `src/gdext/arraytools.nim`.

### How do I convert between Array[int] and PackedInt32Array?

Use the constructor pattern found in `src/gdext/gen/gdpackedint32arrayconstr.nim`. First convert your typed array to `Array[Variant]` using the implicit `wild` cast, then pass it to `newPackedInt32Array(varArr)`. Note that this conversion copies data and validates that each Variant contains a compatible integer type.

### Why does Array[T] still use Variant storage internally?

Godot's engine API expects `Array` to be a single Variant type capable of holding any value. The generic `T` in gdext-nim is strictly a compile-time hint for type safety; at runtime, the array remains a Godot Variant array as implemented in `src/gdext/arraytools.nim`. This ensures seamless interoperability with Godot's dynamic scripting system.

### Which array type should I use for large datasets like mesh vertices?

Always use the appropriate `Packed*Array` type (e.g., `PackedVector3Array` for vertices) when working with large homogeneous datasets. According to `src/gdext/gen/gdpackedvector3array.nim`, these arrays avoid the per-element Variant overhead, providing contiguous memory layout that Godot's rendering and physics systems can process efficiently.