deserialize method
Deserialize a given message
Implementation
@override
AbstractMessage? deserialize(Uint8List? message) {
if (message == null) {
return null;
}
if (_readCborArrayHeader(message, 0) == null) {
_validateCompleteCborValue(message);
}
final fastPathMessage = _deserializeFastPathMessage(message);
if (fastPathMessage != null) {
return fastPathMessage;
}
final decodedMessage = cbor.decode(message.toList());
if (decodedMessage is CborList) {
validateWampMessageFieldCount(decodedMessage.length);
if (decodedMessage.isEmpty) {
throw const FormatException('WAMP message must not be empty');
}
final cborMessageId = decodedMessage[0];
if (cborMessageId is CborInt) {
final messageId = cborMessageId.toInt();
if (messageId != MessageTypes.codePublish ||
decodedMessage.length < 4) {
validateWampMessageMinimumFieldCount(
messageId,
decodedMessage.length,
);
}
if (messageId == MessageTypes.codeAbort && decodedMessage.length == 3) {
return Abort(
(decodedMessage[2] as CborString).toString(),
message:
decodedMessage[1] is CborMap &&
(decodedMessage[1] as CborMap)[CborString('message')] !=
null
? ((decodedMessage[1] as CborMap)[CborString('message')]
as CborString)
.toString()
: null,
);
}
if (messageId == MessageTypes.codeChallenge &&
decodedMessage.length == 3) {
final extraMap = _cborMapToStringMap(decodedMessage[2] as CborMap);
return Challenge(
(decodedMessage[1] as CborString).toString(),
Extra.fromMap(extraMap),
);
}
if (messageId == MessageTypes.codeHello && decodedMessage.length == 3) {
return Hello(
(decodedMessage[1] as CborString?)?.toString(),
_decodeDetailsMap(
_cborMapToStringMap(decodedMessage[2] as CborMap),
),
);
}
if (messageId == MessageTypes.codeAuthenticate &&
decodedMessage.length == 3) {
final extra = decodedMessage[2];
if (extra is! CborMap ||
extra.keys.any((key) => key is! CborString)) {
throw const FormatException(
'AUTHENTICATE.Extra must be a dictionary with string keys',
);
}
return Authenticate(
signature: (decodedMessage[1] as CborString?)?.toString(),
)..extra = Map<String, Object?>.from(_cborMapToStringMap(extra));
}
if (messageId == MessageTypes.codeWelcome &&
decodedMessage.length == 3) {
return Welcome(
(decodedMessage[1] as CborInt).toInt(),
_decodeDetailsMap(
_cborMapToStringMap(decodedMessage[2] as CborMap),
),
);
}
if (messageId == MessageTypes.codeRegister &&
decodedMessage.length == 4) {
return Register(
(decodedMessage[1] as CborInt).toInt(),
(decodedMessage[3] as CborString).toString(),
options: _decodeRegisterOptions(
_decodeRequiredOptionsMap(decodedMessage[2], 'REGISTER'),
),
);
}
if (messageId == MessageTypes.codeUnregister &&
decodedMessage.length == 3) {
return Unregister(
(decodedMessage[1] as CborInt).toInt(),
(decodedMessage[2] as CborInt).toInt(),
);
}
if (messageId == MessageTypes.codeCall && decodedMessage.length >= 4) {
return _addPayload(
Call(
(decodedMessage[1] as CborInt).toInt(),
(decodedMessage[3] as CborString).toString(),
options: _decodeCallOptions(
_decodeRequiredOptionsMap(decodedMessage[2], 'CALL'),
),
),
decodedMessage,
4,
);
}
if (messageId == MessageTypes.codeYield && decodedMessage.length >= 2) {
return _addPayload(
Yield(
(decodedMessage[1] as CborInt).toInt(),
options: _decodeYieldOptions(
_decodeRequiredOptionsMap(decodedMessage[2], 'YIELD'),
),
),
decodedMessage,
3,
);
}
if (messageId == MessageTypes.codePublish &&
decodedMessage.length >= 4) {
return _addPayload(
Publish(
(decodedMessage[1] as CborInt).toInt(),
(decodedMessage[3] as CborString).toString(),
options: _decodePublishOptions(
_decodeRequiredOptionsMap(decodedMessage[2], 'PUBLISH'),
),
),
decodedMessage,
4,
);
}
if (messageId == MessageTypes.codeInterrupt &&
decodedMessage.length >= 2) {
final optionsMap = _decodeRequiredOptionsMap(
decodedMessage[2],
'INTERRUPT',
);
final options = InterruptOptions()
..mode = optionsMap['mode'] as String?;
return Interrupt(
(decodedMessage[1] as CborInt).toInt(),
options: options,
);
}
if (messageId == MessageTypes.codeCancel &&
decodedMessage.length >= 2) {
final optionsMap = _decodeRequiredOptionsMap(
decodedMessage[2],
'CANCEL',
);
final options = CancelOptions()..mode = optionsMap['mode'] as String?;
return Cancel(
(decodedMessage[1] as CborInt).toInt(),
options: options,
);
}
if (messageId == MessageTypes.codeRegistered &&
decodedMessage.length == 3) {
return Registered(
(decodedMessage[1] as CborInt).toInt(),
(decodedMessage[2] as CborInt).toInt(),
);
}
if (messageId == MessageTypes.codeUnregistered &&
decodedMessage.length == 2) {
return Unregistered((decodedMessage[1] as CborInt).toInt());
}
if (messageId == MessageTypes.codeInvocation &&
decodedMessage.length > 3) {
final detailsMap = _cborMapToStringMap(decodedMessage[3] as CborMap);
final caller = decodeOptionalWampId(
detailsMap,
'caller',
'INVOCATION.Details.caller',
);
detailsMap.remove('caller');
decodeOptionalWampNonNegativeInteger(
detailsMap,
'trustlevel',
'INVOCATION.Details.trustlevel',
);
final procedureValue = detailsMap.remove('procedure');
final String? procedure = procedureValue as String?;
final progressValue = detailsMap.remove('progress');
final bool? progress = progressValue as bool?;
final receiveProgressValue = detailsMap.remove('receive_progress');
final bool? receiveProgress = receiveProgressValue as bool?;
final timeout = decodeOptionalWampNonNegativeInteger(
detailsMap,
'timeout',
'INVOCATION.Details.timeout',
);
detailsMap.remove('timeout');
final pptSchemeValue = detailsMap.remove('ppt_scheme');
final String? pptScheme = pptSchemeValue as String?;
final pptSerializerValue = detailsMap.remove('ppt_serializer');
final String? pptSerializer = pptSerializerValue as String?;
final pptCipherValue = detailsMap.remove('ppt_cipher');
final String? pptCipher = pptCipherValue as String?;
final pptKeyIdValue = detailsMap.remove('ppt_keyid');
final String? pptKeyId = pptKeyIdValue as String?;
return _addPayload(
Invocation(
(decodedMessage[1] as CborInt).toInt(),
(decodedMessage[2] as CborInt).toInt(),
InvocationDetails(
caller,
procedure,
receiveProgress,
pptScheme,
pptSerializer,
pptCipher,
pptKeyId,
detailsMap,
)
..progress = progress
..timeout = timeout,
),
decodedMessage,
4,
);
}
if (messageId == MessageTypes.codeResult && decodedMessage.length > 2) {
final detailsMap = _cborMapToStringMap(decodedMessage[2] as CborMap);
final progressValue = detailsMap.remove('progress');
final bool? progress = progressValue as bool?;
final pptSchemeValue = detailsMap.remove('ppt_scheme');
final String? pptScheme = pptSchemeValue as String?;
final pptSerializerValue = detailsMap.remove('ppt_serializer');
final String? pptSerializer = pptSerializerValue as String?;
final pptCipherValue = detailsMap.remove('ppt_cipher');
final String? pptCipher = pptCipherValue as String?;
final pptKeyIdValue = detailsMap.remove('ppt_keyid');
final String? pptKeyId = pptKeyIdValue as String?;
return _addPayload(
Result(
(decodedMessage[1] as CborInt).toInt(),
ResultDetails(
progress: progress,
pptScheme: pptScheme,
pptSerializer: pptSerializer,
pptCipher: pptCipher,
pptKeyId: pptKeyId,
custom: detailsMap,
),
),
decodedMessage,
3,
);
}
if (messageId == MessageTypes.codePublished &&
decodedMessage.length == 3) {
return Published(
(decodedMessage[1] as CborInt).toInt(),
(decodedMessage[2] as CborInt).toInt(),
);
}
if (messageId == MessageTypes.codeSubscribed &&
decodedMessage.length == 3) {
return Subscribed(
(decodedMessage[1] as CborInt).toInt(),
(decodedMessage[2] as CborInt).toInt(),
);
}
if (messageId == MessageTypes.codeSubscribe &&
decodedMessage.length == 4) {
return Subscribe(
(decodedMessage[1] as CborInt).toInt(),
(decodedMessage[3] as CborString).toString(),
options: _decodeSubscribeOptions(
_decodeRequiredOptionsMap(decodedMessage[2], 'SUBSCRIBE'),
),
);
}
if (messageId == MessageTypes.codeUnsubscribe &&
decodedMessage.length == 3) {
return Unsubscribe(
(decodedMessage[1] as CborInt).toInt(),
(decodedMessage[2] as CborInt).toInt(),
);
}
if (messageId == MessageTypes.codeUnsubscribed &&
decodedMessage.length > 1) {
return Unsubscribed(
(decodedMessage[1] as CborInt).toInt(),
decodedMessage.length == 2
? null
: UnsubscribedDetails(
(decodedMessage[2] as CborMap)[CborString(
'subscription',
)] ==
null
? null
: ((decodedMessage[2] as CborMap)[CborString(
'subscription',
)]
as CborInt)
.toInt(),
(decodedMessage[2] as CborMap)[CborString('reason')] == null
? null
: ((decodedMessage[2] as CborMap)[CborString('reason')]
as CborString)
.toString(),
),
);
}
if (messageId == MessageTypes.codeEvent && decodedMessage.length > 3) {
final detailsMap = _cborMapToStringMap(decodedMessage[3] as CborMap);
final publisher = decodeOptionalWampId(
detailsMap,
'publisher',
'EVENT.Details.publisher',
);
detailsMap.remove('publisher');
final trustLevel = decodeOptionalWampNonNegativeInteger(
detailsMap,
'trustlevel',
'EVENT.Details.trustlevel',
);
detailsMap.remove('trustlevel');
final topicValue = detailsMap.remove('topic');
final String? topic = topicValue as String?;
final pptSchemeValue = detailsMap.remove('ppt_scheme');
final String? pptScheme = pptSchemeValue as String?;
final pptSerializerValue = detailsMap.remove('ppt_serializer');
final String? pptSerializer = pptSerializerValue as String?;
final pptCipherValue = detailsMap.remove('ppt_cipher');
final String? pptCipher = pptCipherValue as String?;
final pptKeyIdValue = detailsMap.remove('ppt_keyid');
final String? pptKeyId = pptKeyIdValue as String?;
return _addPayload(
Event(
(decodedMessage[1] as CborInt).toInt(),
(decodedMessage[2] as CborInt).toInt(),
EventDetails(
publisher: publisher,
trustlevel: trustLevel,
topic: topic,
pptScheme: pptScheme,
pptSerializer: pptSerializer,
pptCipher: pptCipher,
pptKeyid: pptKeyId,
custom: detailsMap,
),
),
decodedMessage,
4,
);
}
if (messageId == MessageTypes.codeError && decodedMessage.length > 4) {
return _addPayload(
Error(
(decodedMessage[1] as CborInt).toInt(),
(decodedMessage[2] as CborInt).toInt(),
Map<String, Object>.from(
(decodedMessage[3] as CborMap).toObject() as Map,
),
(decodedMessage[4] as CborString).toString(),
),
decodedMessage,
5,
);
}
if (messageId == MessageTypes.codeGoodbye) {
return Goodbye(
decodedMessage.length == 1
? null
: GoodbyeMessage(
(decodedMessage[1] as CborMap)[CborString('message')] ==
null
? null
: ((decodedMessage[1] as CborMap)[CborString('message')]
as CborString)
.toString(),
),
(decodedMessage[2] as CborString).toString(),
);
}
}
}
_logger.shout(
'Could not deserialize CBOR WAMP message (${message.length} bytes)',
);
// TODO respond with an error
return null;
}