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();
}
}