Open RichardHightower opened 4 years ago
4:17
https://github.com/nats-io/nats.net/blob/master/src/NATS.Client/Parser.cs
src/NATS.Client/Parser.cs
// Copyright 2015-2018 The NATS Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. using System; using System.IO;
namespace NATS.Client { internal sealed class MsgArg { internal string subject; internal string reply; internal long sid; internal int size; } internal sealed class Parser { readonly Connection conn; readonly byte[] argBufBase = new byte[Defaults.defaultBufSize]; readonly MemoryStream argBufStream = null; byte[] msgBufBase = new byte[Defaults.defaultBufSize]; MemoryStream msgBufStream = null; internal Parser(Connection conn) { argBufStream = new MemoryStream(argBufBase); msgBufStream = new MemoryStream(msgBufBase); this.conn = conn; } internal int state = 0; // For performance declare these as consts - they'll be // baked into the IL code (thus faster). An enum would // be nice, but we want speed in this critical section of // message handling. private const int OP_START = 0; private const int OP_PLUS = 1; private const int OP_PLUS_O = 2; private const int OP_PLUS_OK = 3; private const int OP_MINUS = 4; private const int OP_MINUS_E = 5; private const int OP_MINUS_ER = 6; private const int OP_MINUS_ERR = 7; private const int OP_MINUS_ERR_SPC = 8; private const int MINUS_ERR_ARG = 9; private const int OP_C = 10; private const int OP_CO = 11; private const int OP_CON = 12; private const int OP_CONN = 13; private const int OP_CONNE = 14; private const int OP_CONNEC = 15; private const int OP_CONNECT = 16; private const int CONNECT_ARG = 17; private const int OP_M = 18; private const int OP_MS = 19; private const int OP_MSG = 20; private const int OP_MSG_SPC = 21; private const int MSG_ARG = 22; private const int MSG_PAYLOAD = 23; private const int MSG_END = 24; private const int OP_P = 25; private const int OP_PI = 26; private const int OP_PIN = 27; private const int OP_PING = 28; private const int OP_PO = 29; private const int OP_PON = 30; private const int OP_PONG = 31; private const int OP_I = 32; private const int OP_IN = 33; private const int OP_INF = 34; private const int OP_INFO = 35; private const int OP_INFO_SPC = 36; private const int INFO_ARG = 37; private void parseError(byte[] buffer, int position) { throw new NATSException(string.Format("Parse Error [{0}], {1}", state, buffer)); } internal void parse(byte[] buffer, int len) { int i; char b; for (i = 0; i < len; i++) { b = (char)buffer[i]; switch (state) { case OP_START: switch (b) { case 'M': case 'm': state = OP_M; break; case 'C': case 'c': state = OP_C; break; case 'P': case 'p': state = OP_P; break; case '+': state = OP_PLUS; break; case '-': state = OP_MINUS; break; case 'i': case 'I': state = OP_I; break; default: parseError(buffer,i); break; } break; case OP_M: switch (b) { case 'S': case 's': state = OP_MS; break; default: parseError(buffer, i); break; } break; case OP_MS: switch (b) { case 'G': case 'g': state = OP_MSG; break; default: parseError(buffer, i); break; } break; case OP_MSG: switch (b) { case ' ': case '\t': state = OP_MSG_SPC; break; default: parseError(buffer, i); break; } break; case OP_MSG_SPC: switch (b) { case ' ': break; case '\t': break; default: state = MSG_ARG; i--; break; } break; case MSG_ARG: switch (b) { case '\r': break; case '\n': conn.processMsgArgs(argBufBase, argBufStream.Position); argBufStream.Position = 0; if (conn.msgArgs.size > msgBufBase.Length) { // Add 2 to account for the \r\n msgBufBase = new byte[conn.msgArgs.size+2]; msgBufStream?.Dispose(); msgBufStream = new MemoryStream(msgBufBase); } state = MSG_PAYLOAD; break; default: argBufStream.WriteByte((byte)b); break; } break; case MSG_PAYLOAD: int msgSize = conn.msgArgs.size; if (msgSize == …```
https://github.com/nats-io/nats.net/blob/master/src/NATS.Client/Parser.cs