read method

Uint8List read(
  1. int handle,
  2. NativeMessageBytePart part, {
  3. required Pointer<Uint8> borrowed,
  4. required int length,
})

Exports part while the caller still owns handle.

borrowed and length must come from that handle's native message info, not a remote address. They permit safe copying on legacy runtimes and verify the slice selected by a new runtime. Cross-isolate receivers must first acquire their own handle; an expired handle must fail closed.

Implementation

Uint8List read(
  int handle,
  NativeMessageBytePart part, {
  required ffi.Pointer<ffi.Uint8> borrowed,
  required int length,
}) {
  if (messageHandleAbi == NativeMessageHandleAbi.legacy) {
    checkedLegacyMessageHandle(handle);
  }
  if (handle <= 0 || length < 0 || (length > 0 && borrowed == ffi.nullptr)) {
    throw ArgumentError('Invalid native message byte view');
  }
  if (length == 0) return Uint8List(0);
  final export = _export;
  if (export == null) return Uint8List.fromList(borrowed.asTypedList(length));
  final output = calloc<_MessageByteView>();
  try {
    final status = export(handle, part.index, output);
    if (status != 0) {
      throw StateError('Native message byte export failed ($status)');
    }
    final view = output.ref;
    if (view.owner == ffi.nullptr ||
        view.data != borrowed ||
        view.length != length) {
      _free!(view.owner);
      throw StateError(
        'Native message byte export disagrees with message info',
      );
    }
    try {
      return view.data.asTypedList(
        view.length,
        finalizer: _finalizer,
        token: view.owner,
      );
    } catch (_) {
      _free!(view.owner);
      rethrow;
    }
  } finally {
    calloc.free(output);
  }
}