registerGroup method

void registerGroup({
  1. required int extId,
  2. required void builder(
    1. MessagePackGroup group
    ),
})

Registers a group of related types under a single extId.

Each type in the group gets a unique subId (integer). The subId is automatically prepended to the encoded payload.

Benefits:

  • ID conservation: Uses only one extension ID for multiple types.
  • Performance: Grouped types use the same high-performance routing logic as standalone extensions.

Example:

mp.registerGroup(
  extId: 2,
  builder: (g) {
    g.add<Circle>(
      subId: 1,
      encoder: (c, p) => p.packDouble(c.radius),
      decoder: (u, l) => Circle(u.unpackDouble()!),
    );
    g.add<Rectangle>(
      subId: 2,
      encoder: (r, p) => p.packAll([r.w, r.h]),
      decoder: (u, l) {
        final w = u.unpackDouble()!;
        final h = u.unpackDouble()!;
        return Rectangle(w, h);
      },
    );
  },
);

Implementation

void registerGroup({
  required int extId,
  required void Function(MessagePackGroup group) builder,
}) {
  _checkExtId(extId);
  if (!_allowOverwrite && _decoders[_extIndex(extId)] != null) {
    throw MessagePackConfigurationException(
      'Extension id $extId is already registered.',
      'Use a different extId or enable allowOverwrite.',
    );
  }

  // Sub-decoder table filled by the group builder.
  final subs = HashMap<int, _Ext>();

  // Let the caller fill the group.
  builder(MessagePackGroup._(this, extId, subs));

  // Register a single routing decoder for the whole group.
  _decoders[_extIndex(extId)] = _Ext(
    id: extId,
    subId: null,
    canHandle: (_) => false,
    encode: (_, _) => throw StateError('Group encode: use concrete type.'),
    decode: (unpacker, length) {
      if (length == 0) {
        throw const MessagePackFormatException(
          'Empty group payload.',
          'A group extension payload must contain at least a subId.',
        );
      }

      final startOffset = unpacker.offset;
      final subId = unpacker.unpackInt() ?? 0;
      final sub = subs[subId];

      if (sub == null) {
        throw MessagePackConfigurationException(
          'Sub-type $subId not found in group $extId.',
          'Make sure all sub-types are registered via group.add().',
        );
      }

      final readBytes = unpacker.offset - startOffset;
      return sub.decode(unpacker, length - readBytes);
    },
  );
}