docs: def parse(self, data=b''):
          """
          Parses the wire protocol from NATS for the client
          and dispatches the subscription callbacks.
          """
          self.buf.extend(data)
          while self.buf:
              if self.state == AWAITING_CONTROL_LINE:
                  msg = MSG_RE.match(self.buf)
                  if msg:
                      try:
                          subject, sid, _, reply, needed_bytes = msg.groups()
                          self.msg_arg["subject"] = subject
                          self.msg_arg["sid"] = int(sid)
                          if reply:
                              self.msg_arg["reply"] = reply
                          else:
                              self.msg_arg["reply"] = b''
                          self.needed = int(needed_bytes)
                          del self.buf[:msg.end()]
                          self.state = AWAITING_MSG_PAYLOAD
                          continue
                      except:
                          raise ErrProtocol("nats: malformed MSG")
  
                  ok = OK_RE.match(self.buf)
                  if ok:
                      # Do nothing and just skip.
                      del self.buf[:ok.end()]
                      continue
  
                  err = ERR_RE.match(self.buf)
                  if err:
                      err_msg = err.groups()
                      yield self.nc._process_err(err_msg)
                      del self.buf[:err.end()]
                      continue
  
                  ping = PING_RE.match(self.buf)
                  if ping:
                      del self.buf[:ping.end()]
                      yield self.nc._process_ping()
                      continue
  
                  pong = PONG_RE.match(self.buf)
                  if pong:
                      del self.buf[:pong.end()]
                      yield self.nc._process_pong()
                      continue
  
                  info = INFO_RE.match(self.buf)
                  if info:
                      info_line = info.groups()[0]
                      self.nc._process_info(info_line)
                      del self.buf[:info.end()]
                      continue
  
                  # If nothing matched at this point, then probably
                  # a split buffer and need to gather more bytes,
                  # otherwise it would mean that there is an issue
                  # and we're getting malformed control lines.
                  if len(self.buf
                         ) < MAX_CONTROL_LINE_SIZE and _CRLF_ not in self.buf:
                      break
                  else:
                      raise ErrProtocol("nats: unknown protocol")
  
              elif self.state == AWAITING_MSG_PAYLOAD:
                  if len(self.buf) >= self.needed + CRLF_SIZE:
                      subject = self.msg_arg["subject"]
                      sid = self.msg_arg["sid"]
                      reply = self.msg_arg["reply"]
  
                      # Consume msg payload from buffer and set next parser state.
                      payload = bytes(self.buf[:self.needed])
                      del self.buf[:self.needed + CRLF_SIZE]
                      self.state = AWAITING_CONTROL_LINE
                      yield self.nc._process_msg(sid, subject, reply, payload)
                  else:
                      # Wait until we have enough bytes in buffer.
                      break