getDiscriminatedUnionDecoder function

Decoder<Map<String, Object?>> getDiscriminatedUnionDecoder(
  1. List<(Object?, Decoder<Object?>)> variants, {
  2. String discriminator = '__kind',
  3. Decoder<num>? size,
})

Returns a decoder for discriminated unions.

This decoder deserializes maps that follow the discriminated union pattern by reading a numerical discriminator and mapping it to the corresponding variant.

variants is a list of (discriminatorValue, decoder) pairs. discriminator is the property name used as the discriminator (defaults to '__kind'). size is the number decoder for the discriminator prefix (defaults to u8).

Implementation

Decoder<Map<String, Object?>> getDiscriminatedUnionDecoder(
  List<(Object?, Decoder<Object?>)> variants, {
  String discriminator = '__kind',
  Decoder<num>? size,
}) {
  final prefix = size ?? getU8Decoder();

  final variantDecoders = variants.map((entry) {
    final (discriminatorValue, variant) = entry;
    return transformDecoder<List<Object?>, Map<String, Object?>>(
      getTupleDecoder([prefix as Decoder<Object?>, variant]),
      (tuple, bytes, offset) {
        final value = tuple[1];
        final result = <String, Object?>{discriminator: discriminatorValue};
        if (value is Map<String, Object?>) {
          result.addAll(value);
        }
        return result;
      },
    );
  }).toList();

  // Determine fixed/variable size.
  final fixedSize = _getUnionFixedSize(variantDecoders);

  (Map<String, Object?>, int) readImpl(Uint8List bytes, int offset) {
    final (value, _) = prefix.read(bytes, offset);
    final index = value.toInt();
    _assertValidVariantIndex(variantDecoders, index);
    return variantDecoders[index].read(bytes, offset);
  }

  if (fixedSize != null) {
    return FixedSizeDecoder<Map<String, Object?>>(
      fixedSize: fixedSize,
      read: readImpl,
    );
  }

  final maxSize = _getUnionMaxSize(variantDecoders);
  return VariableSizeDecoder<Map<String, Object?>>(
    read: readImpl,
    maxSize: maxSize,
  );
}