refusalOf method
Why value is not the shape this field takes, or null when it is.
Null is always taken: an absent field is what every optional field means by "not set". A number outside min and max is taken too; see isInside.
Implementation
String? refusalOf(Object? value) {
if (value == null) return null;
bool numbers(int count) =>
value is List &&
value.length == count &&
value.every((Object? e) => e is num && e.isFinite);
final fits = switch (kind) {
FieldKind.number => value is num && value.isFinite,
FieldKind.integer => value is int || (value is num && value % 1 == 0),
FieldKind.toggle => value is bool,
FieldKind.choice => value is String && choices.contains(value),
FieldKind.color => numbers(3) || numbers(4),
FieldKind.vector3 => numbers(3),
FieldKind.text || FieldKind.entity => value is String,
FieldKind.asset =>
value is String &&
(suffixes.isEmpty ||
suffixes.any(
(String s) => value.toLowerCase().endsWith(s.toLowerCase()),
)),
// A kind this build does not know takes what a document can hold.
_ => true,
};
if (fits) return null;
return switch (kind) {
FieldKind.choice => '"$key" is one of ${choices.join(', ')}, not $value',
FieldKind.color =>
'"$key" is a colour, three or four numbers, not $value',
FieldKind.vector3 => '"$key" is three numbers, not $value',
FieldKind.asset when suffixes.isNotEmpty =>
'"$key" is a path ending in ${suffixes.join(' or ')}, not $value',
_ => '"$key" is ${_article(kind.name)}, not $value',
};
}