public static async Task <List <Command> > DeserializeAsync(Stream stream) { Memory <byte> buffer = new byte[8192]; int bytesRead; var protocolObjectBuffer = new MessageProtocolObject[1024]; Memory <MessageProtocolObject> protocolObjects = protocolObjectBuffer; var parserIndex = 0; Memory <byte> remainingBuffer = new byte[0]; while ((bytesRead = await stream.ReadAsync(buffer).ConfigureAwait(false)) > 0) { var(currentParserIndex, remeaningBufferLength) = ParseProtocolObjects(remainingBuffer.Span, buffer.Span.Slice(0, bytesRead), protocolObjects.Slice(parserIndex), () => { Array.Resize(ref protocolObjectBuffer, protocolObjectBuffer.Length + 1024); protocolObjects = protocolObjectBuffer; }); parserIndex += currentParserIndex; remainingBuffer = buffer.Slice(bytesRead - remeaningBufferLength, remeaningBufferLength); } return(ParseCommands(protocolObjects.Slice(0, parserIndex))); }
private MessageProtocolObject ReadProtocolObject(byte firstByte) { var commandStartPosition = _currentPosition - 1; switch (firstByte) { #region Simple String case (byte)TokenType.String: { if (!ReadUntil(new[] { (byte)TokenType.Separator }, out var bytes)) { //EOB _currentPosition = commandStartPosition; return(null); } return(new StringProtocolObject() { Value = Encoding.UTF8.GetString(bytes) }); } #endregion #region Blob case (byte)TokenType.Blob: { if (!ReadInteger(out var length)) { //EOB _currentPosition = commandStartPosition; return(null); } if (!ExpectSeparator()) { //EOB _currentPosition = commandStartPosition; return(null); } if (!ReadBytes(length, out var bytes)) { //EOB _currentPosition = commandStartPosition; return(null); } if (!ExpectSeparator()) { //EOB _currentPosition = commandStartPosition; return(null); } return(new BlobProtocolObject() { Bytes = bytes.ToArray() }); } #endregion #region Error case (byte)TokenType.Error: { if (!ReadInteger(out var length)) { //EOB _currentPosition = commandStartPosition; return(null); } if (!ExpectSeparator()) { //EOB _currentPosition = commandStartPosition; return(null); } if (!ReadAsciiString(8, out var errorCode)) { //EOB _currentPosition = commandStartPosition; return(null); } if (!ExpectSeparator()) { //EOB _currentPosition = commandStartPosition; return(null); } if (!ReadUtf8String(length, out var errorMessage)) { //EOB _currentPosition = commandStartPosition; return(null); } if (!ExpectSeparator()) { //EOB _currentPosition = commandStartPosition; return(null); } return(new ErrorProtocolObject() { Code = errorCode, Message = errorMessage }); } #endregion #region Integer case (byte)TokenType.Integer: { if (!ReadInteger(out var value)) { //EOB _currentPosition = commandStartPosition; return(null); } if (!ExpectSeparator()) { //EOB _currentPosition = commandStartPosition; return(null); } return(new IntegerProtocolObject() { Value = value }); } #endregion #region Long case (byte)TokenType.Long: { if (!ReadLong(out var value)) { //EOB _currentPosition = commandStartPosition; return(null); } if (!ExpectSeparator()) { //EOB _currentPosition = commandStartPosition; return(null); } return(new LongProtocolObject() { Value = value }); } #endregion #region Double case (byte)TokenType.Double: { if (!ReadDouble(out var value)) { //EOB _currentPosition = commandStartPosition; return(null); } if (!ExpectSeparator()) { //EOB _currentPosition = commandStartPosition; return(null); } return(new DoubleProtocolObject() { Value = value }); } #endregion #region Null case (byte)TokenType.Null: { if (!ExpectSeparator()) { //EOB _currentPosition = commandStartPosition; return(null); } return(new NullProtocolObject()); } #endregion #region Boolean case (byte)TokenType.True: { if (!ExpectSeparator()) { //EOB _currentPosition = commandStartPosition; return(null); } return(new BooleanProtocolObject { Value = true }); } case (byte)TokenType.False: { if (!ExpectSeparator()) { //EOB _currentPosition = commandStartPosition; return(null); } return(new BooleanProtocolObject { Value = false }); } #endregion #region Array case (byte)TokenType.Array: { if (!ReadInteger(out var count)) { //EOB _currentPosition = commandStartPosition; return(null); } if (!ExpectSeparator()) { //EOB _currentPosition = commandStartPosition; return(null); } var items = new MessageProtocolObject[count]; for (var i = 0; i < count; i++) { if (!ReadNextByte(out var arrayItemFirstByte)) { //EOB _currentPosition = commandStartPosition; return(null); } var item = ReadProtocolObject(arrayItemFirstByte); if (item == null) { //EOB _currentPosition = commandStartPosition; return(null); } items[i] = item; } return(new ArrayProtocolObject { Items = items }); } #endregion #region Map case (byte)TokenType.Map: { if (!ReadInteger(out var count)) { //EOB _currentPosition = commandStartPosition; return(null); } if (!ExpectSeparator()) { //EOB _currentPosition = commandStartPosition; return(null); } var items = new KeyValuePair <MessageProtocolObject, MessageProtocolObject> [count]; for (var i = 0; i < count; i++) { if (!ReadNextByte(out var keyFirstByte)) { //EOB _currentPosition = commandStartPosition; return(null); } var key = ReadProtocolObject(keyFirstByte); if (key == null) { //EOB _currentPosition = commandStartPosition; return(null); } if (!ReadNextByte(out var valueFirstByte)) { //EOB _currentPosition = commandStartPosition; return(null); } var value = ReadProtocolObject(valueFirstByte); if (value == null) { //EOB _currentPosition = commandStartPosition; return(null); } items[i] = new KeyValuePair <MessageProtocolObject, MessageProtocolObject>(key, value); } return(new MapProtocolObject { Items = items }); } #endregion default: throw new SyntaxErrorException($"Invalid start character #{firstByte} at {{0}}.", _currentPosition); } }
/// <summary> /// Handles the writing of <see cref="MessageProtocolObject"/> /// </summary> /// <param name="protocolObject"></param> protected abstract void HandleWrite(MessageProtocolObject protocolObject);
/// <inheritdoc /> public virtual void Write(MessageProtocolObject protocolObject) { HandleWrite(protocolObject); }
/// <inheritdoc /> protected override void HandleWrite(MessageProtocolObject protocolObject) { _items.Add(protocolObject); }