public int ReadInt32()
        {
            var buffer = new byte[sizeof(int)];

            base.Read(buffer, 0, sizeof(int));

            return(SerializerCore.DeserializeInt32(buffer));
        }
        public BackendMessage Deserialize(Stream stream)
        {
            var messageTypeId = (byte)stream.ReadByte();

            Type messageType = null;

            foreach (var customType in CustomTypes)
            {
                var field = customType.GetField("MessageTypeId");
                if (field == null)
                {
                    continue;
                }

                if ((byte)field.GetValue(null) == messageTypeId)
                {
                    messageType = customType;
                    break;
                }
            }

            if (messageType == null)
            {
                throw new ArgumentException("invalid message type", nameof(stream));
            }

            var payloadSizeField = new byte[sizeof(int)];

            stream.Read(payloadSizeField, 0, sizeof(int));

            var payloadSize = SerializerCore.DeserializeInt32(payloadSizeField) - sizeof(int);

            if (payloadSize < 0)
            {
                throw new ArgumentException("invalid payload size", nameof(stream));
            }

            var payload  = new byte[payloadSize];
            var readSize = stream.Read(payload, 0, payloadSize);

            if (readSize != payloadSize)
            {
                throw new ArgumentException("invalid payload size", nameof(stream));
            }

            return(Deserialize(payload, messageType));
        }