array.mx raw

   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