1 // Package array provides typed access to raw memory laid out as a contiguous
2 // array of elements by C code, the kernel, mmap, or the compiler's own type
3 // descriptors. It is an extension of unsafe: no slice header, no arena
4 // ownership, no bounds checking, no allocation. The caller supplies the base
5 // pointer and element count; Array does the offset/stride math.
6 package array
7 8 import "unsafe"
9 10 // Array is a fixed-length inline block of n elements of type T at a raw
11 // address, with an iteration cursor. It never allocates: the caller supplies
12 // the base pointer (typically the start of an mmap'd region).
13 type Array[T any] struct {
14 ptr unsafe.Pointer
15 elemSz uintptr
16 n int32
17 cur int32
18 }
19 20 // At returns an Array of n elements of type T at base, cursor at element 0.
21 func At[T any](base unsafe.Pointer, n int32) (a Array[T]) {
22 var z T
23 a.ptr = base
24 a.elemSz = unsafe.Sizeof(z)
25 a.n = n
26 a.cur = 0
27 return
28 }
29 30 // Len returns the number of elements.
31 func (a *Array[T]) Len() (n int32) { return a.n }
32 33 // Current returns a pointer to the element at the cursor. Call only when
34 // More() is true, or immediately after a Seek that returned nil.
35 func (a *Array[T]) Current() (p *T) {
36 return (*T)(unsafe.Add(a.ptr, uintptr(a.cur)*a.elemSz))
37 }
38 39 // Index returns a pointer to element i. No bounds check.
40 func (a *Array[T]) Index(i int32) (p *T) {
41 return (*T)(unsafe.Add(a.ptr, uintptr(i)*a.elemSz))
42 }
43 44 // More reports whether the cursor is at a valid element (0 <= cur < n).
45 func (a *Array[T]) More() (ok bool) { return a.cur >= 0 && a.cur < a.n }
46 47 // Next advances the cursor forward.
48 func (a *Array[T]) Next() { a.cur++ }
49 50 // Prev retreats the cursor backward.
51 func (a *Array[T]) Prev() { a.cur-- }
52 53 // Seek moves the cursor to i. No bounds check - caller is responsible.
54 func (a *Array[T]) Seek(i int32) { a.cur = i }
55 56 // First moves the cursor to the first element.
57 func (a *Array[T]) First() { a.cur = 0 }
58 59 // Last moves the cursor to the last element.
60 func (a *Array[T]) Last() { a.cur = a.n - 1 }
61 62 // Zero sets every element to the zero value.
63 func (a *Array[T]) Zero() {
64 var z T
65 for i := int32(0); i < a.n; i++ {
66 *(*T)(unsafe.Add(a.ptr, uintptr(i)*a.elemSz)) = z
67 }
68 }
69 70 // SizeOf returns the byte size of n inline elements of type T.
71 func SizeOf[T any](n int32) (sz uintptr) {
72 var z T
73 return uintptr(n) * unsafe.Sizeof(z)
74 }
75 76 // Alignof returns the byte alignment of type T.
77 func Alignof[T any]() (al uintptr) {
78 var z T
79 return unsafe.Alignof(z)
80 }
81