fromJson static method

RmlCommitDiff fromJson(
  1. String report,
  2. Uint8List? changes
)

Reads the report JSON native sends across FFI/wasm, pairing it with the ChangeSet bytes sent alongside (null on failure). Never throws: text that is not the expected JSON shape becomes one error, as in RmlCompileError.listFromJson.

Implementation

static RmlCommitDiff fromJson(String report, Uint8List? changes) {
  try {
    final decoded = jsonDecode(report);
    if (decoded is! Map<String, dynamic>) {
      throw const FormatException('not a JSON object');
    }
    if (decoded.containsKey('errors')) {
      final errors = RmlCompileError.listFromJson(
        jsonEncode(decoded['errors']),
      );
      // An empty list would read as success.
      if (errors.isEmpty) {
        throw const FormatException('an error report with no errors');
      }
      final document = decoded['document'];
      if (document != 'base' && document != 'sandbox') {
        throw const FormatException('an error report with no document');
      }
      return RmlCommitDiff.failure(errors, baseFailed: document == 'base');
    }
    // A success report always carries all four fields; anything less is
    // not the contract this reads, so it fails closed rather than
    // silently substituting empty defaults.
    if (!decoded.containsKey('idsUsed') ||
        !decoded.containsKey('entries') ||
        !decoded.containsKey('skipped') ||
        !decoded.containsKey('orders')) {
      throw const FormatException('missing a required success field');
    }
    final entries = (decoded['entries'] as List<dynamic>)
        .cast<Map<String, dynamic>>()
        .map(RmlCommitEntry.fromJson)
        .toList();
    if (changes == null) {
      throw const FormatException('a success with no ChangeSet bytes');
    }
    return RmlCommitDiff.success(
      changes: changes,
      idsUsed: decoded['idsUsed'] as int,
      entries: entries,
      skipped: (decoded['skipped'] as List<dynamic>)
          .cast<Map<String, dynamic>>()
          .map(RmlCommitSkip.fromJson)
          .toList(),
      orders: (decoded['orders'] as List<dynamic>)
          .cast<Map<String, dynamic>>()
          .map(RmlOrderGroup.fromJson)
          .toList(),
    );
  } catch (_) {
    return RmlCommitDiff.failure([
      RmlCompileError(line: 0, message: report.trim()),
    ]);
  }
}