read method
document checked against this format and lifted to version.
Refuses, through refuse so the format's own exception is what a
caller catches:
- a document whose
formatnames another format; - a version newer than this build reads, naming both numbers;
- a version older than since;
- a
requiresentry this build does not understands.
The result is a fresh map: document is not changed.
Implementation
Map<String, Object?> read(
Map<String, Object?> document, {
required FormatRefusal refuse,
}) {
final said = document['format'];
if (said != null && said is! String) {
throw refuse('"format" must be a string naming the format, not $said');
}
if (said is String && said != id && !aliases.contains(said)) {
throw refuse('this is a "$said" document, not "$id"');
}
final raw =
document['version'] ??
switch (legacyVersionKey) {
final String key => document[key],
null => null,
};
if (raw != null && wholeNumber(raw) == null) {
throw refuse('"version" must be a whole number, not $raw');
}
final at = versionOf(document);
if (at < 1) throw refuse('"version" counts from 1, not $at');
if (at > version) {
throw refuse(
'$id version $at is newer than this build reads ($version): '
'update flutter3d to open it',
);
}
if (at < since) {
throw refuse(
'$id version $at is older than this build reads ($since and up): '
'open it with an earlier flutter3d and save it again',
);
}
final requires = switch (document['requires']) {
null => const <String>[],
final List<Object?> list when list.every((Object? e) => e is String) =>
list.cast<String>(),
final other => throw refuse(
'"requires" must be a list of names, not $other',
),
};
final missing = <String>[
for (final name in requires)
if (!understands.contains(name)) name,
];
if (missing.isNotEmpty) {
throw refuse(
'this $id document requires ${missing.join(', ')}, which this '
'build does not understand: install the plugin or the flutter3d '
'release that provides ${missing.length == 1 ? 'it' : 'them'}',
);
}
return lift(<String, Object?>{...document}, from: at);
}