Frame _readFrame()

in lib/src/frames/frame_reader.dart [156:274]


  Frame _readFrame(FrameHeader header, List<int> bytes, int frameOffset) {
    var frameEnd = frameOffset + header.length;

    var offset = frameOffset;
    switch (header.type) {
      case FrameType.DATA:
        var padLength = 0;
        if (_isFlagSet(header.flags, DataFrame.FLAG_PADDED)) {
          _checkFrameLengthCondition((frameEnd - offset) >= 1);
          padLength = bytes[offset++];
        }
        var dataLen = frameEnd - offset - padLength;
        _checkFrameLengthCondition(dataLen >= 0);
        var dataBytes = viewOrSublist(bytes, offset, dataLen);
        return DataFrame(header, padLength, dataBytes);

      case FrameType.HEADERS:
        var padLength = 0;
        if (_isFlagSet(header.flags, HeadersFrame.FLAG_PADDED)) {
          _checkFrameLengthCondition((frameEnd - offset) >= 1);
          padLength = bytes[offset++];
        }
        int? streamDependency;
        var exclusiveDependency = false;
        int? weight;
        if (_isFlagSet(header.flags, HeadersFrame.FLAG_PRIORITY)) {
          _checkFrameLengthCondition((frameEnd - offset) >= 5);
          exclusiveDependency = (bytes[offset] & 0x80) == 0x80;
          streamDependency = readInt32(bytes, offset) & 0x7fffffff;
          offset += 4;
          weight = bytes[offset++];
        }
        var headerBlockLen = frameEnd - offset - padLength;
        _checkFrameLengthCondition(headerBlockLen >= 0);
        var headerBlockFragment = viewOrSublist(bytes, offset, headerBlockLen);
        return HeadersFrame(header, padLength, exclusiveDependency,
            streamDependency, weight, headerBlockFragment);

      case FrameType.PRIORITY:
        _checkFrameLengthCondition(
            (frameEnd - offset) == PriorityFrame.FIXED_FRAME_LENGTH,
            message: 'Priority frame length must be exactly 5 bytes.');
        var exclusiveDependency = (bytes[offset] & 0x80) == 0x80;
        var streamDependency = readInt32(bytes, offset) & 0x7fffffff;
        var weight = bytes[offset + 4];
        return PriorityFrame(
            header, exclusiveDependency, streamDependency, weight);

      case FrameType.RST_STREAM:
        _checkFrameLengthCondition(
            (frameEnd - offset) == RstStreamFrame.FIXED_FRAME_LENGTH,
            message: 'Rst frames must have a length of 4.');
        var errorCode = readInt32(bytes, offset);
        return RstStreamFrame(header, errorCode);

      case FrameType.SETTINGS:
        _checkFrameLengthCondition((header.length % 6) == 0,
            message: 'Settings frame length must be a multiple of 6 bytes.');

        var count = header.length ~/ 6;
        var settings = <Setting>[];
        for (var i = 0; i < count; i++) {
          var identifier = readInt16(bytes, offset + 6 * i);
          var value = readInt32(bytes, offset + 6 * i + 2);
          settings.add(Setting(identifier, value));
        }
        var frame = SettingsFrame(header, settings);
        if (frame.hasAckFlag) {
          _checkFrameLengthCondition(header.length == 0,
              message: 'Settings frame length must 0 for ACKs.');
        }
        return frame;

      case FrameType.PUSH_PROMISE:
        var padLength = 0;
        if (_isFlagSet(header.flags, PushPromiseFrame.FLAG_PADDED)) {
          _checkFrameLengthCondition((frameEnd - offset) >= 1);
          padLength = bytes[offset++];
        }
        var promisedStreamId = readInt32(bytes, offset) & 0x7fffffff;
        offset += 4;
        var headerBlockLen = frameEnd - offset - padLength;
        _checkFrameLengthCondition(headerBlockLen >= 0);
        var headerBlockFragment = viewOrSublist(bytes, offset, headerBlockLen);
        return PushPromiseFrame(
            header, padLength, promisedStreamId, headerBlockFragment);

      case FrameType.PING:
        _checkFrameLengthCondition(
            (frameEnd - offset) == PingFrame.FIXED_FRAME_LENGTH,
            message: 'Ping frames must have a length of 8.');
        var opaqueData = readInt64(bytes, offset);
        return PingFrame(header, opaqueData);

      case FrameType.GOAWAY:
        _checkFrameLengthCondition((frameEnd - offset) >= 8);
        var lastStreamId = readInt32(bytes, offset);
        var errorCode = readInt32(bytes, offset + 4);
        var debugData = viewOrSublist(bytes, offset + 8, header.length - 8);
        return GoawayFrame(header, lastStreamId, errorCode, debugData);

      case FrameType.WINDOW_UPDATE:
        _checkFrameLengthCondition(
            (frameEnd - offset) == WindowUpdateFrame.FIXED_FRAME_LENGTH,
            message: 'Window update frames must have a length of 4.');
        var windowSizeIncrement = readInt32(bytes, offset) & 0x7fffffff;
        return WindowUpdateFrame(header, windowSizeIncrement);

      case FrameType.CONTINUATION:
        var headerBlockFragment =
            viewOrSublist(bytes, offset, frameEnd - offset);
        return ContinuationFrame(header, headerBlockFragment);

      default:
        // Unknown frames should be ignored according to spec.
        return UnknownFrame(
            header, viewOrSublist(bytes, offset, frameEnd - offset));
    }
  }