void _parse()

in lib/src/bound_multipart_stream.dart [166:386]


  void _parse() {
    // Number of boundary bytes to artificially place before the supplied data.
    // The data to parse might be 'artificially' prefixed with a
    // partial match of the boundary.
    var boundaryPrefix = _boundaryIndex;
    // Position where content starts. Will be null if no known content
    // start exists. Will be negative of the content starts in the
    // boundary prefix. Will be zero or position if the content starts
    // in the current buffer.
    var contentStartIndex =
        _state == _contentCode && _boundaryIndex == 0 ? 0 : null;

    // Function to report content data for the current part. The data
    // reported is from the current content start index up til the
    // current index. As the data can be artificially prefixed with a
    // prefix of the boundary both the content start index and index
    // can be negative.
    void reportData() {
      if (contentStartIndex! < 0) {
        var contentLength = boundaryPrefix + _index - _boundaryIndex;
        if (contentLength <= boundaryPrefix) {
          _multipartController!.add(_boundary.sublist(0, contentLength));
        } else {
          _multipartController!.add(_boundary.sublist(0, boundaryPrefix));
          _multipartController!
              .add(_buffer.sublist(0, contentLength - boundaryPrefix));
        }
      } else {
        var contentEndIndex = _index - _boundaryIndex;
        _multipartController!
            .add(_buffer.sublist(contentStartIndex, contentEndIndex));
      }
    }

    while (
        _index < _buffer.length && _state != _failCode && _state != _doneCode) {
      var byte =
          _index < 0 ? _boundary[boundaryPrefix + _index] : _buffer[_index];
      switch (_state) {
        case _startCode:
          if (byte == _boundary[_boundaryIndex]) {
            _boundaryIndex++;
            if (_boundaryIndex == _boundary.length) {
              _state = _boundaryEndingCode;
              _boundaryIndex = 0;
            }
          } else {
            // Restart matching of the boundary.
            _index = _index - _boundaryIndex;
            _boundaryIndex = 0;
          }
          break;

        case _boundaryEndingCode:
          if (byte == char_code.cr) {
            _state = _boundaryEndCode;
          } else if (byte == char_code.dash) {
            _state = _lastBoundaryDash2Code;
          } else {
            _expectWhitespace(byte);
          }
          break;

        case _boundaryEndCode:
          _expectByteValue(byte, char_code.lf);
          _multipartController?.close();
          if (_multipartController != null) {
            _multipartController = null;
            _tryPropagateControllerState();
          }
          _state = _headerStartCode;
          break;

        case _headerStartCode:
          _headers = <String, String>{};
          if (byte == char_code.cr) {
            _state = _headerEndingCode;
          } else {
            // Start of new header field.
            _headerField.add(_toLowerCase(byte));
            _state = _headerFieldCode;
          }
          break;

        case _headerFieldCode:
          if (byte == char_code.colon) {
            _state = _headerValueStartCode;
          } else {
            if (!_isTokenChar(byte)) {
              throw MimeMultipartException('Invalid header field name');
            }
            _headerField.add(_toLowerCase(byte));
          }
          break;

        case _headerValueStartCode:
          if (byte == char_code.cr) {
            _state = _headerValueFoldingOrEndingCode;
          } else if (byte != char_code.sp && byte != char_code.ht) {
            // Start of new header value.
            _headerValue.add(byte);
            _state = _headerValueCode;
          }
          break;

        case _headerValueCode:
          if (byte == char_code.cr) {
            _state = _headerValueFoldingOrEndingCode;
          } else {
            _headerValue.add(byte);
          }
          break;

        case _headerValueFoldingOrEndingCode:
          _expectByteValue(byte, char_code.lf);
          _state = _headerValueFoldOrEndCode;
          break;

        case _headerValueFoldOrEndCode:
          if (byte == char_code.sp || byte == char_code.ht) {
            _state = _headerValueStartCode;
          } else {
            var headerField = utf8.decode(_headerField);
            var headerValue = utf8.decode(_headerValue);
            _headers![headerField.toLowerCase()] = headerValue;
            _headerField.clear();
            _headerValue.clear();
            if (byte == char_code.cr) {
              _state = _headerEndingCode;
            } else {
              // Start of new header field.
              _headerField.add(_toLowerCase(byte));
              _state = _headerFieldCode;
            }
          }
          break;

        case _headerEndingCode:
          _expectByteValue(byte, char_code.lf);
          _multipartController = StreamController(
              sync: true,
              onListen: () {
                if (_subscription.isPaused) _subscription.resume();
              },
              onPause: _subscription.pause,
              onResume: _subscription.resume);
          _controller
              .add(_MimeMultipart(_headers!, _multipartController!.stream));
          _headers = null;
          _state = _contentCode;
          contentStartIndex = _index + 1;
          break;

        case _contentCode:
          if (byte == _boundary[_boundaryIndex]) {
            _boundaryIndex++;
            if (_boundaryIndex == _boundary.length) {
              if (contentStartIndex != null) {
                _index++;
                reportData();
                _index--;
              }
              _multipartController!.close();
              _multipartController = null;
              _tryPropagateControllerState();
              _boundaryIndex = 0;
              _state = _boundaryEndingCode;
            }
          } else {
            // Restart matching of the boundary.
            _index = _index - _boundaryIndex;
            contentStartIndex ??= _index;
            _boundaryIndex = 0;
          }
          break;

        case _lastBoundaryDash2Code:
          _expectByteValue(byte, char_code.dash);
          _state = _lastBoundaryEndingCode;
          break;

        case _lastBoundaryEndingCode:
          if (byte == char_code.cr) {
            _state = _lastBoundaryEndCode;
          } else {
            _expectWhitespace(byte);
          }
          break;

        case _lastBoundaryEndCode:
          _expectByteValue(byte, char_code.lf);
          _multipartController?.close();
          if (_multipartController != null) {
            _multipartController = null;
            _tryPropagateControllerState();
          }
          _state = _doneCode;
          break;

        default:
          // Should be unreachable.
          assert(false);
          break;
      }

      // Move to the next byte.
      _index++;
    }

    // Report any known content.
    if (_state == _contentCode && contentStartIndex != null) {
      reportData();
    }

    // Resume if at end.
    if (_index == _buffer.length) {
      _buffer = _placeholderBuffer;
      _index = 0;
      _subscription.resume();
    }
  }