deserializeFromString method

AbstractMessage? deserializeFromString(
  1. String jsonMessage
)

Converts a string JSON message into a WAMP message object.

Implementation

AbstractMessage? deserializeFromString(String jsonMessage) {
  final singleBinaryPayload = _deserializeSingleBinaryPayloadFromString(
    jsonMessage,
  );
  if (singleBinaryPayload != null) {
    return singleBinaryPayload;
  }
  final message = _decodeJsonMessage(jsonMessage);
  if (message is List) {
    if (message.isEmpty) {
      throw const FormatException('WAMP message type must be an integer');
    }
    final Object? rawMessageId = message[0];
    if (rawMessageId is! int) {
      throw const FormatException('WAMP message type must be an integer');
    }
    final messageId = rawMessageId;
    if (messageId == MessageTypes.codeUnsubscribed && message.length == 2) {
      return Unsubscribed(message[1], null);
    }
    if (messageId != MessageTypes.codePublish || message.length < 4) {
      validateWampMessageMinimumFieldCount(messageId, message.length);
    }
    if (messageId == MessageTypes.codeHello) {
      validateWampMessageFieldCount(message.length);
      return Hello(
        message[1] as String?,
        _decodeDetailsMap(
          _normalizeJsonStringKeyMap(message[2] as Map<dynamic, dynamic>),
        ),
      );
    }
    if (messageId == MessageTypes.codeChallenge) {
      validateWampMessageFieldCount(message.length);
      final extraMap = message[2] is Map
          ? _normalizeJsonStringKeyMap(message[2] as Map<dynamic, dynamic>)
          : const <String, dynamic>{};
      return Challenge(message[1], Extra.fromMap(extraMap));
    }
    if (messageId == MessageTypes.codeAuthenticate) {
      validateWampMessageFieldCount(message.length);
      final extra = message[2];
      if (extra is! Map || extra.keys.any((key) => key is! String)) {
        throw const FormatException(
          'AUTHENTICATE.Extra must be a dictionary with string keys',
        );
      }
      return Authenticate(
        signature: message[1] as String?,
      )..extra = Map<String, Object?>.from(_normalizeJsonStringKeyMap(extra));
    }
    if (messageId == MessageTypes.codeWelcome) {
      validateWampMessageFieldCount(message.length);
      return Welcome(
        message[1],
        _decodeDetailsMap(
          _normalizeJsonStringKeyMap(message[2] as Map<dynamic, dynamic>),
        ),
      );
    }
    if (messageId == MessageTypes.codeRegister) {
      validateWampMessageFieldCount(message.length);
      return Register(
        message[1],
        message[3],
        options: _decodeRegisterOptions(
          _decodeRequiredOptionsMap(message[2], 'REGISTER'),
        ),
      );
    }
    if (messageId == MessageTypes.codeUnregister) {
      validateWampMessageFieldCount(message.length);
      return Unregister(message[1], message[2]);
    }
    if (messageId == MessageTypes.codeCall) {
      return _addPayload(
        Call(
          message[1],
          message[3],
          options: _decodeCallOptions(
            _decodeRequiredOptionsMap(message[2], 'CALL'),
          ),
        ),
        message,
        4,
      );
    }
    if (messageId == MessageTypes.codeYield) {
      return _addPayload(
        Yield(
          message[1],
          options: _decodeYieldOptions(
            _decodeRequiredOptionsMap(message[2], 'YIELD'),
          ),
        ),
        message,
        3,
      );
    }
    if (messageId == MessageTypes.codePublish) {
      return _addPayload(
        Publish(
          message[1],
          message[3],
          options: _decodePublishOptions(
            _decodeRequiredOptionsMap(message[2], 'PUBLISH'),
          ),
        ),
        message,
        4,
      );
    }
    if (messageId == MessageTypes.codeRegistered) {
      validateWampMessageFieldCount(message.length);
      return registered_msg.Registered(message[1], message[2]);
    }
    if (messageId == MessageTypes.codeUnregistered) {
      validateWampMessageFieldCount(message.length);
      return unregistered_msg.Unregistered(message[1]);
    }
    if (messageId == MessageTypes.codeInvocation) {
      final detailsMap = message[3] as Map<dynamic, dynamic>;
      return _addPayload(
        Invocation(
          message[1],
          message[2],
          _decodeInvocationDetails(detailsMap),
        ),
        message,
        4,
      );
    }
    if (messageId == MessageTypes.codeInterrupt) {
      validateWampMessageFieldCount(message.length);
      final optionsMap = _validateRequiredOptionsMap(
        message[2],
        'INTERRUPT',
      );
      return interrupt_msg.Interrupt(
        message[1],
        options: (() {
          final options = interrupt_msg.InterruptOptions();
          options.mode = optionsMap['mode'] as String?;
          return options;
        })(),
      );
    }
    if (messageId == MessageTypes.codeCancel) {
      validateWampMessageFieldCount(message.length);
      final optionsMap = _validateRequiredOptionsMap(message[2], 'CANCEL');
      return cancel_msg.Cancel(
        message[1],
        options: (() {
          final options = cancel_msg.CancelOptions();
          options.mode = optionsMap['mode'] as String?;
          return options;
        })(),
      );
    }
    if (messageId == MessageTypes.codeResult) {
      final detailsMap = message[2] as Map<dynamic, dynamic>;
      final progress = detailsMap['progress'];
      final pptScheme = detailsMap['ppt_scheme'];
      final pptSerializer = detailsMap['ppt_serializer'];
      final pptCipher = detailsMap['ppt_cipher'];
      final pptKeyId = detailsMap['ppt_keyid'];
      return _addPayload(
        Result(
          message[1],
          ResultDetails(
            progress: progress,
            pptScheme: pptScheme,
            pptSerializer: pptSerializer,
            pptCipher: pptCipher,
            pptKeyId: pptKeyId,
            custom: _extractCustomDetails(detailsMap, _resultDetailKeys),
          ),
        ),
        message,
        3,
      );
    }
    if (messageId == MessageTypes.codePublished) {
      validateWampMessageFieldCount(message.length);
      return Published(message[1], message[2]);
    }
    if (messageId == MessageTypes.codeSubscribe) {
      validateWampMessageFieldCount(message.length);
      return Subscribe(
        message[1],
        message[3],
        options: _decodeSubscribeOptions(
          _decodeRequiredOptionsMap(message[2], 'SUBSCRIBE'),
        ),
      );
    }
    if (messageId == MessageTypes.codeSubscribed) {
      validateWampMessageFieldCount(message.length);
      return Subscribed(message[1], message[2]);
    }
    if (messageId == MessageTypes.codeUnsubscribe) {
      validateWampMessageFieldCount(message.length);
      return Unsubscribe(message[1], message[2]);
    }
    if (messageId == MessageTypes.codeUnsubscribed) {
      validateWampMessageFieldCount(message.length);
      return Unsubscribed(
        message[1],
        UnsubscribedDetails(
          message[2]['subscription'],
          message[2]['reason'],
        ),
      );
    }
    if (messageId == MessageTypes.codeEvent) {
      final detailsMap = message[3] as Map<dynamic, dynamic>;
      return _addPayload(
        Event(
          message[1],
          message[2],
          _decodeEventDetails(detailsMap),
        ),
        message,
        4,
      );
    }
    if (messageId == MessageTypes.codeError) {
      return _addPayload(
        Error(
          message[1],
          message[2],
          _normalizeJsonStringKeyMap(message[3] as Map<dynamic, dynamic>),
          message[4],
        ),
        message,
        5,
      );
    }
    if (messageId == MessageTypes.codeAbort) {
      validateWampMessageFieldCount(message.length);
      final details = message.length > 1 && message[1] != null
          ? _normalizeJsonStringKeyMap(message[1] as Map<dynamic, dynamic>)
          : <String, Object?>{};
      final reason = message.length > 2 ? message[2] as String : '';
      List<dynamic>? arguments;
      Map<String, Object?>? argumentsKeywords;
      if (message.length > 3 && message[3] != null) {
        arguments = List<dynamic>.from(message[3] as List);
      }
      if (message.length > 4 && message[4] != null) {
        argumentsKeywords = Map<String, Object?>.from(
          message[4] as Map<String, dynamic>,
        );
      }
      final messageText = details['message'] as String?;
      return Abort(
        reason,
        details: details,
        message: messageText,
        arguments: arguments,
        argumentsKeywords: argumentsKeywords,
      );
    }
    if (messageId == MessageTypes.codeGoodbye) {
      validateWampMessageFieldCount(message.length);
      return Goodbye(
        _decodeGoodbyeMessage(
          message.length > 1 && message[1] is Map
              ? message[1] as Map<dynamic, dynamic>
              : null,
        ),
        message[2],
      );
    }
  }
  _logger.shout(
    'Could not deserialize JSON WAMP message (${jsonMessage.length} chars)',
  );
  // TODO respond with an error
  return null;
}