pointerPointerArray<T, RInner extends RType> static method

StructLiveList<StructLiveList<T, RInner>, RPointer<RInner>> pointerPointerArray<T, RInner extends RType>(
  1. MemoryPointer<RType>? ptrOf(),
  2. StructPointerArrayField<T, RPointer<RInner>> field,
  3. List<List<T>> initial
)

Pointer to an array of pointers: T** -> T* -> T[].

The outer list represents the array of T* pointers; every element is itself a live list over the T[] that particular T* points to, built lazily and cached in nestedCache as indices are accessed.

Implementation

static StructLiveList<StructLiveList<T, RInner>, RPointer<RInner>> pointerPointerArray<
  T,
  RInner extends RType
>(
  MemoryPointer? Function() ptrOf,
  StructPointerArrayField<T, RPointer<RInner>> field,
  List<List<T>> initial,
) {
  final outerCodec = field.codec;
  final innerCodec = outerCodec.inner as PointerCodec<T, RInner>;
  final innerAccess = _ResolvedPointerAccess<T, RInner>(innerCodec);
  final nestedCache = <StructLiveList<T, RInner>>[];

  StructLiveList<T, RInner> build(int index) {
    while (nestedCache.length <= index) {
      final i = nestedCache.length;
      final initialInner = i < initial.length ? initial[i] : const <Never>[];

      nestedCache.add(._(
        () {
          final outerFieldPtr = ptrOf()?.offsetBy(field.offset);
          if (outerFieldPtr == null) return null;
          final arrayBase = outerCodec.deref(outerFieldPtr);
          if (arrayBase.isNull) return null;
          final resolved = outerCodec.pointerElementPtr(arrayBase, i);
          return resolved.isNull ? null : resolved;
        },
        0,
        null,
        innerAccess,
        initialInner,
      ));
    }
    return nestedCache[index];
  }

  return ._(ptrOf, field.offset, null, _LazyBuiltAccess<StructLiveList<T, RInner>>(build), nestedCache);
}