CommandApdu constructor

CommandApdu({
  1. required int instructionClass,
  2. required int instructionCode,
  3. required int p1Parameter,
  4. required int p2Parameter,
  5. Uint8List? data,
  6. int? expectedResponseLength,
  7. bool forceExtended = false,
})

Constructs a command, rejecting values that cannot be encoded.

Every range is checked here rather than at toBytes, so a command that could never reach a card fails where it was written instead of inside a reader session.

Implementation

factory CommandApdu({
  required int instructionClass,
  required int instructionCode,
  required int p1Parameter,
  required int p2Parameter,
  Uint8List? data,
  int? expectedResponseLength,
  bool forceExtended = false,
}) {
  _checkByte(instructionClass, 'instructionClass');
  _checkByte(instructionCode, 'instructionCode');
  _checkByte(p1Parameter, 'p1Parameter');
  _checkByte(p2Parameter, 'p2Parameter');

  // An empty data field is the same as none: the wire has no Lc of zero, in either form,
  // so a caller who passes an empty list means case 1 or case 2 whether they know it or not.
  final body = (data == null || data.isEmpty) ? null : data;
  if (body != null && body.length > 65535) {
    throw ArgumentError.value(body.length, 'data', 'does not fit the two-byte extended Lc field');
  }
  if (expectedResponseLength != null && (expectedResponseLength < 1 || expectedResponseLength > 65536)) {
    throw ArgumentError.value(
      expectedResponseLength,
      'expectedResponseLength',
      'must be between 1 and 65536; pass null for a command that asks for no response data',
    );
  }

  return CommandApdu._(
    instructionClass: instructionClass,
    instructionCode: instructionCode,
    p1Parameter: p1Parameter,
    p2Parameter: p2Parameter,
    data: body,
    expectedResponseLength: expectedResponseLength,
    forceExtended: forceExtended,
  );
}