decodeModelBytes function

Future<ModelDocument> decodeModelBytes(
  1. ModelLoadRequest request,
  2. Uint8List bytes,
  3. AssetUriResolver resolveUri
)

Decodes already-read bytes with an explicit resolver.

The seam the isolate path uses: bytes and a resolver are both sendable-friendly, while an AssetSource that reaches for the asset bundle is not usable off the UI isolate.

Implementation

Future<ModelDocument> decodeModelBytes(
  ModelLoadRequest request,
  Uint8List bytes,
  AssetUriResolver resolveUri,
) {
  // An application's own decoders first, so it can add a format and replace one.
  // Asked before the format is resolved at all: a decoder that recognises its
  // own file is a better authority than a suffix table this package wrote.
  for (final decoder in request.decoders) {
    if (!decoder.handles(
      ModelProbe(fileName: request.source.fileName.toLowerCase(), bytes: bytes),
    )) {
      continue;
    }
    final task = developer.TimelineTask()
      ..start(
        'decode ${decoder.runtimeType}',
        arguments: <String, Object?>{'bytes': bytes.length},
      );
    return decoder
        .decode(
          ModelDecodeContext(
            bytes: bytes,
            request: request,
            resolveUri: resolveUri,
          ),
        )
        .whenComplete(task.finish);
  }

  final format = _resolveFormat(request, bytes);
  // Named after the format so the background isolate's span says which decoder
  // the time went into, rather than just "decode".
  final task = developer.TimelineTask()
    ..start(
      'decode ${format.name}',
      arguments: <String, Object?>{'bytes': bytes.length},
    );

  return builtInModelDecoder(format, request)
      .decode(
        ModelDecodeContext(
          bytes: bytes,
          request: request,
          resolveUri: resolveUri,
        ),
      )
      .whenComplete(task.finish);
}