Example #1
0
        public override bool Write(ref DirectBuffer directBuf)
        {
            if (_lexemePos == -1)
            {
                if (_writeBuf.WriteSpaceLeft < 4)
                {
                    return(false);
                }
                _writeBuf.WriteInt32(_value.Count);
                _lexemePos = 0;
            }

            for (; _lexemePos < _value.Count; _lexemePos++)
            {
                if (_writeBuf.WriteSpaceLeft < MaxSingleLexemeBytes)
                {
                    return(false);
                }

                _writeBuf.WriteString(_value[_lexemePos].Text);
                _writeBuf.WriteByte(0);
                _writeBuf.WriteInt16(_value[_lexemePos].Count);
                for (var i = 0; i < _value[_lexemePos].Count; i++)
                {
                    _writeBuf.WriteInt16(_value[_lexemePos][i]._val);
                }
            }

            return(true);
        }
Example #2
0
        protected override async Task Write(object value, WriteBuffer buf, LengthCache lengthCache, NpgsqlParameter parameter,
                                            bool async, CancellationToken cancellationToken)
        {
            var vector = (NpgsqlTsVector)value;

            if (buf.WriteSpaceLeft < 4)
            {
                await buf.Flush(async, cancellationToken);
            }
            buf.WriteInt32(vector.Count);

            foreach (var lexeme in vector)
            {
                if (buf.WriteSpaceLeft < MaxSingleLexemeBytes)
                {
                    await buf.Flush(async, cancellationToken);
                }

                buf.WriteString(lexeme.Text);
                buf.WriteByte(0);
                buf.WriteInt16(lexeme.Count);
                for (var i = 0; i < lexeme.Count; i++)
                {
                    buf.WriteInt16(lexeme[i].Value);
                }
            }
        }
Example #3
0
        public override void Write(object value, WriteBuffer buf, NpgsqlParameter parameter)
        {
            var num = (decimal)(parameter?.ConvertedValue ?? value);

            if (num == 0M)
            {
                buf.WriteInt64(0);
            }
            else
            {
                bool negative = num < 0;
                if (negative)
                {
                    num = -num;
                }

                int numGroups, weight, fractionDigits;
                GetNumericHeader(num, out numGroups, out weight, out fractionDigits);

                buf.WriteInt16(numGroups);
                buf.WriteInt16(weight);
                buf.WriteInt16(negative ? 0x4000 : 0x0000);
                buf.WriteInt16(fractionDigits);
                for (int i = 0, pos = weight + 7; i < numGroups; i++, pos--)
                {
                    buf.WriteInt16((ushort)(num / Decimals[pos]));
                    num %= Decimals[pos];
                }
            }
        }
Example #4
0
        protected override void Write(object value, WriteBuffer buf, NpgsqlParameter parameter = null)
        {
            if (parameter?.ConvertedValue != null)
            {
                value = parameter.ConvertedValue;
            }

            var bytes = ((Guid)value).ToByteArray();

            buf.WriteInt32(BitConverter.ToInt32(bytes, 0));
            buf.WriteInt16(BitConverter.ToInt16(bytes, 4));
            buf.WriteInt16(BitConverter.ToInt16(bytes, 6));
            buf.WriteBytes(bytes, 8, 8);
        }
        internal void WriteStartup(Dictionary <string, string> parameters)
        {
            var len = sizeof(int) +  // Length
                      sizeof(int) +  // Protocol version
                      sizeof(byte);  // Trailing zero byte

            foreach (var kvp in parameters)
            {
                len += PGUtil.UTF8Encoding.GetByteCount(kvp.Key) + 1 +
                       PGUtil.UTF8Encoding.GetByteCount(kvp.Value) + 1;
            }

            // Should really never happen, just in case
            if (len > WriteBuffer.Size)
            {
                throw new Exception("Startup message bigger than buffer");
            }

            WriteBuffer.WriteInt32(len);
            WriteBuffer.WriteInt16(ProtocolVersion.MAJOR);
            WriteBuffer.WriteInt16(ProtocolVersion.MINOR);

            foreach (var kv in parameters)
            {
                WriteBuffer.WriteString(kv.Key);
                WriteBuffer.WriteByte(0);
                WriteBuffer.WriteString(kv.Value);
                WriteBuffer.WriteByte(0);
            }

            WriteBuffer.WriteByte(0);
        }
Example #6
0
 public override void Write(object value, WriteBuffer buf, NpgsqlParameter parameter)
 {
     if (parameter?.ConvertedValue != null)
     {
         value = parameter.ConvertedValue;
     }
     buf.WriteInt16((short)value);
 }
Example #7
0
        internal override async Task Write(WriteBuffer buf, bool async, CancellationToken cancellationToken)
        {
            Debug.Assert(Statement != null && Statement.All(c => c < 128));

            var queryByteLen = _encoding.GetByteCount(Query);

            if (buf.WriteSpaceLeft < 1 + 4 + Statement.Length + 1)
            {
                await buf.Flush(async, cancellationToken);
            }

            var messageLength =
                1 +                         // Message code
                4 +                         // Length
                Statement.Length +
                1 +                         // Null terminator
                queryByteLen +
                1 +                         // Null terminator
                2 +                         // Number of parameters
                ParameterTypeOIDs.Count * 4;

            buf.WriteByte(Code);
            buf.WriteInt32(messageLength - 1);
            buf.WriteNullTerminatedString(Statement);

            await buf.WriteString(Query, queryByteLen, async, cancellationToken);

            if (buf.WriteSpaceLeft < 1 + 2)
            {
                await buf.Flush(async, cancellationToken);
            }
            buf.WriteByte(0); // Null terminator for the query
            buf.WriteInt16((short)ParameterTypeOIDs.Count);

            foreach (var t in ParameterTypeOIDs)
            {
                if (buf.WriteSpaceLeft < 4)
                {
                    await buf.Flush(async, cancellationToken);
                }
                buf.WriteInt32((int)t);
            }
        }
Example #8
0
    internal async Task WriteBind(
        List <NpgsqlParameter> parameters,
        string portal,
        string statement,
        bool allResultTypesAreUnknown,
        bool[]?unknownResultTypeList,
        bool async,
        CancellationToken cancellationToken = default)
    {
        Debug.Assert(statement.All(c => c < 128));
        Debug.Assert(portal.All(c => c < 128));

        var headerLength =
            sizeof(byte) +                        // Message code
            sizeof(int) +                         // Message length
            sizeof(byte) +                        // Portal is always empty (only a null terminator)
            statement.Length + sizeof(byte) +     // Statement name plus null terminator
            sizeof(ushort);                       // Number of parameter format codes that follow

        if (WriteBuffer.WriteSpaceLeft < headerLength)
        {
            Debug.Assert(WriteBuffer.Size >= headerLength, "Write buffer too small for Bind header");
            await Flush(async, cancellationToken);
        }

        var formatCodesSum = 0;
        var paramsLength   = 0;

        for (var paramIndex = 0; paramIndex < parameters.Count; paramIndex++)
        {
            var param = parameters[paramIndex];
            formatCodesSum += (int)param.FormatCode;
            param.LengthCache?.Rewind();
            paramsLength += param.ValidateAndGetLength();
        }

        var formatCodeListLength = formatCodesSum == 0 ? 0 : formatCodesSum == parameters.Count ? 1 : parameters.Count;

        var messageLength = headerLength +
                            sizeof(short) * formatCodeListLength +                  // List of format codes
                            sizeof(short) +                                         // Number of parameters
                            sizeof(int) * parameters.Count +                        // Parameter lengths
                            paramsLength +                                          // Parameter values
                            sizeof(short) +                                         // Number of result format codes
                            sizeof(short) * (unknownResultTypeList?.Length ?? 1);   // Result format codes

        WriteBuffer.WriteByte(FrontendMessageCode.Bind);
        WriteBuffer.WriteInt32(messageLength - 1);
        Debug.Assert(portal == string.Empty);
        WriteBuffer.WriteByte(0);  // Portal is always empty

        WriteBuffer.WriteNullTerminatedString(statement);
        WriteBuffer.WriteInt16(formatCodeListLength);

        // 0 length implicitly means all-text, 1 means all-binary, >1 means mix-and-match
        if (formatCodeListLength == 1)
        {
            if (WriteBuffer.WriteSpaceLeft < 2)
            {
                await Flush(async, cancellationToken);
            }
            WriteBuffer.WriteInt16((short)FormatCode.Binary);
        }
        else if (formatCodeListLength > 1)
        {
            for (var paramIndex = 0; paramIndex < parameters.Count; paramIndex++)
            {
                if (WriteBuffer.WriteSpaceLeft < 2)
                {
                    await Flush(async, cancellationToken);
                }
                WriteBuffer.WriteInt16((short)parameters[paramIndex].FormatCode);
            }
        }

        if (WriteBuffer.WriteSpaceLeft < 2)
        {
            await Flush(async, cancellationToken);
        }

        WriteBuffer.WriteUInt16((ushort)parameters.Count);

        for (var paramIndex = 0; paramIndex < parameters.Count; paramIndex++)
        {
            var param = parameters[paramIndex];
            param.LengthCache?.Rewind();
            await param.WriteWithLength(WriteBuffer, async, cancellationToken);
        }

        if (unknownResultTypeList != null)
        {
            if (WriteBuffer.WriteSpaceLeft < 2 + unknownResultTypeList.Length * 2)
            {
                await Flush(async, cancellationToken);
            }
            WriteBuffer.WriteInt16(unknownResultTypeList.Length);
            foreach (var t in unknownResultTypeList)
            {
                WriteBuffer.WriteInt16(t ? 0 : 1);
            }
        }
        else
        {
            if (WriteBuffer.WriteSpaceLeft < 4)
            {
                await Flush(async, cancellationToken);
            }
            WriteBuffer.WriteInt16(1);
            WriteBuffer.WriteInt16(allResultTypesAreUnknown ? 0 : 1);
        }
    }
Example #9
0
        internal bool Write(WriteBuffer buf, ref DirectBuffer directBuf)
        {
            Contract.Requires(Statement != null && Statement.All(c => c < 128));
            Contract.Requires(Portal != null && Portal.All(c => c < 128));

            switch (_state)
            {
            case State.Header:
                var formatCodesSum = InputParameters.Select(p => p.FormatCode).Sum(c => (int)c);
                _formatCodeListLength = formatCodesSum == 0 ? 0 : formatCodesSum == InputParameters.Count ? 1 : InputParameters.Count;
                var headerLength =
                    1 +                            // Message code
                    4 +                            // Message length
                    Portal.Length + 1 +
                    Statement.Length + 1 +
                    2;                             // Number of parameter format codes that follow

                if (buf.WriteSpaceLeft < headerLength)
                {
                    Contract.Assume(buf.Size >= headerLength, "Buffer too small for Bind header");
                    return(false);
                }

                foreach (var c in InputParameters.Select(p => p.LengthCache).Where(c => c != null))
                {
                    c.Rewind();
                }
                var messageLength = headerLength +
                                    2 * _formatCodeListLength +                                   // List of format codes
                                    2 +                                                           // Number of parameters
                                    4 * InputParameters.Count +                                   // Parameter lengths
                                    InputParameters.Select(p => p.ValidateAndGetLength()).Sum() + // Parameter values
                                    2 +                                                           // Number of result format codes
                                    2 * (UnknownResultTypeList?.Length ?? 1);                     // Result format codes

                buf.WriteByte(Code);
                buf.WriteInt32(messageLength - 1);
                buf.WriteBytesNullTerminated(Encoding.ASCII.GetBytes(Portal));
                buf.WriteBytesNullTerminated(Encoding.ASCII.GetBytes(Statement));
                buf.WriteInt16(_formatCodeListLength);
                _paramIndex = 0;

                _state = State.ParameterFormatCodes;
                goto case State.ParameterFormatCodes;

            case State.ParameterFormatCodes:
                // 0 length implicitly means all-text, 1 means all-binary, >1 means mix-and-match
                if (_formatCodeListLength == 1)
                {
                    if (buf.WriteSpaceLeft < 2)
                    {
                        return(false);
                    }
                    buf.WriteInt16((short)FormatCode.Binary);
                }
                else if (_formatCodeListLength > 1)
                {
                    for (; _paramIndex < InputParameters.Count; _paramIndex++)
                    {
                        if (buf.WriteSpaceLeft < 2)
                        {
                            return(false);
                        }
                        buf.WriteInt16((short)InputParameters[_paramIndex].FormatCode);
                    }
                }

                if (buf.WriteSpaceLeft < 2)
                {
                    return(false);
                }

                buf.WriteInt16(InputParameters.Count);
                _paramIndex = 0;

                _state = State.ParameterValues;
                goto case State.ParameterValues;

            case State.ParameterValues:
                if (!WriteParameters(buf, ref directBuf))
                {
                    return(false);
                }
                _state = State.ResultFormatCodes;
                goto case State.ResultFormatCodes;

            case State.ResultFormatCodes:
                if (UnknownResultTypeList != null)
                {
                    if (buf.WriteSpaceLeft < 2 + UnknownResultTypeList.Length * 2)
                    {
                        return(false);
                    }
                    buf.WriteInt16(UnknownResultTypeList.Length);
                    foreach (var t in UnknownResultTypeList)
                    {
                        buf.WriteInt16(t ? 0 : 1);
                    }
                }
                else
                {
                    if (buf.WriteSpaceLeft < 4)
                    {
                        return(false);
                    }
                    buf.WriteInt16(1);
                    buf.WriteInt16(AllResultTypesAreUnknown ? 0 : 1);
                }

                _state = State.Done;
                return(true);

            default:
                throw PGUtil.ThrowIfReached();
            }
        }
Example #10
0
        internal bool Write(WriteBuffer buf, ref DirectBuffer directBuf)
        {
            Contract.Requires(Statement != null && Statement.All(c => c < 128));
            Contract.Requires(Portal != null && Portal.All(c => c < 128));

            switch (_state)
            {
                case State.Header:
                    var formatCodesSum = InputParameters.Select(p => p.FormatCode).Sum(c => (int)c);
                    _formatCodeListLength = formatCodesSum == 0 ? 0 : formatCodesSum == InputParameters.Count ? 1 : InputParameters.Count;
                    var headerLength =
                        1 +                        // Message code
                        4 +                        // Message length
                        Portal.Length + 1 +
                        Statement.Length + 1 +
                        2;                         // Number of parameter format codes that follow

                    if (buf.WriteSpaceLeft < headerLength)
                    {
                        Contract.Assume(buf.Size >= headerLength, "Buffer too small for Bind header");
                        return false;
                    }

                    foreach (var c in InputParameters.Select(p => p.LengthCache).Where(c => c != null))
                        c.Rewind();
                    var messageLength = headerLength +
                        2 * _formatCodeListLength + // List of format codes
                        2 +                         // Number of parameters
                        4 * InputParameters.Count +                                     // Parameter lengths
                        InputParameters.Select(p => p.ValidateAndGetLength()).Sum() +   // Parameter values
                        2 +                                                             // Number of result format codes
                        2 * (UnknownResultTypeList?.Length ?? 1);                       // Result format codes

                    buf.WriteByte(Code);
                    buf.WriteInt32(messageLength-1);
                    buf.WriteBytesNullTerminated(Encoding.ASCII.GetBytes(Portal));
                    buf.WriteBytesNullTerminated(Encoding.ASCII.GetBytes(Statement));
                    buf.WriteInt16(_formatCodeListLength);
                    _paramIndex = 0;

                    _state = State.ParameterFormatCodes;
                    goto case State.ParameterFormatCodes;

                case State.ParameterFormatCodes:
                    // 0 length implicitly means all-text, 1 means all-binary, >1 means mix-and-match
                    if (_formatCodeListLength == 1)
                    {
                        if (buf.WriteSpaceLeft < 2)
                            return false;
                        buf.WriteInt16((short)FormatCode.Binary);
                    }
                    else if (_formatCodeListLength > 1)
                        for (; _paramIndex < InputParameters.Count; _paramIndex++)
                        {
                            if (buf.WriteSpaceLeft < 2)
                                return false;
                            buf.WriteInt16((short)InputParameters[_paramIndex].FormatCode);
                        }
                    _state = State.ParameterCount;
                    goto case State.ParameterCount;

                case State.ParameterCount:
                    if (buf.WriteSpaceLeft < 2)
                        return false;

                    buf.WriteInt16(InputParameters.Count);
                    _paramIndex = 0;

                    _state = State.ParameterValues;
                    goto case State.ParameterValues;

                case State.ParameterValues:
                    if (!WriteParameters(buf, ref directBuf))
                        return false;
                    _state = State.ResultFormatCodes;
                    goto case State.ResultFormatCodes;

                case State.ResultFormatCodes:
                    if (UnknownResultTypeList != null)
                    {
                        if (buf.WriteSpaceLeft < 2 + UnknownResultTypeList.Length * 2)
                            return false;
                        buf.WriteInt16(UnknownResultTypeList.Length);
                        foreach (var t in UnknownResultTypeList)
                            buf.WriteInt16(t ? 0 : 1);
                    }
                    else
                    {
                        if (buf.WriteSpaceLeft < 4)
                            return false;
                        buf.WriteInt16(1);
                        buf.WriteInt16(AllResultTypesAreUnknown ? 0 : 1);
                    }

                    _state = State.Done;
                    return true;

                default:
                    throw PGUtil.ThrowIfReached();
            }
        }
Example #11
0
        internal override bool Write(WriteBuffer buf)
        {
            Contract.Requires(Statement != null);

            switch (_state)
            {
            case State.WroteNothing:
                _statementNameBytes = Statement.Length == 0 ? PGUtil.EmptyBuffer : _encoding.GetBytes(Statement);
                _queryLen           = _encoding.GetByteCount(Query);
                if (buf.WriteSpaceLeft < 1 + 4 + _statementNameBytes.Length + 1)
                {
                    return(false);
                }

                var messageLength =
                    1 +                             // Message code
                    4 +                             // Length
                    _statementNameBytes.Length +
                    1 +                             // Null terminator
                    _queryLen +
                    1 +                             // Null terminator
                    2 +                             // Number of parameters
                    ParameterTypeOIDs.Count * 4;

                buf.WriteByte(Code);
                buf.WriteInt32(messageLength - 1);
                buf.WriteBytesNullTerminated(_statementNameBytes);
                goto case State.WroteHeader;

            case State.WroteHeader:
                _state = State.WroteHeader;

                if (_queryLen <= buf.WriteSpaceLeft)
                {
                    buf.WriteString(Query);
                    goto case State.WroteQuery;
                }

                if (_queryLen <= buf.Size)
                {
                    // String can fit entirely in an empty buffer. Flush and retry rather than
                    // going into the partial writing flow below (which requires ToCharArray())
                    return(false);
                }

                _queryChars = Query.ToCharArray();
                _charPos    = 0;
                goto case State.WritingQuery;

            case State.WritingQuery:
                _state = State.WritingQuery;
                int  charsUsed;
                bool completed;
                buf.WriteStringChunked(_queryChars, _charPos, _queryChars.Length - _charPos, true,
                                       out charsUsed, out completed);
                if (!completed)
                {
                    _charPos += charsUsed;
                    return(false);
                }
                goto case State.WroteQuery;

            case State.WroteQuery:
                _state = State.WroteQuery;
                if (buf.WriteSpaceLeft < 1 + 2)
                {
                    return(false);
                }
                buf.WriteByte(0);     // Null terminator for the query
                buf.WriteInt16((short)ParameterTypeOIDs.Count);
                goto case State.WritingParameterTypes;

            case State.WritingParameterTypes:
                _state = State.WritingParameterTypes;
                for (; _parameterTypePos < ParameterTypeOIDs.Count; _parameterTypePos++)
                {
                    if (buf.WriteSpaceLeft < 4)
                    {
                        return(false);
                    }
                    buf.WriteInt32((int)ParameterTypeOIDs[_parameterTypePos]);
                }

                _state = State.WroteAll;
                return(true);

            default:
                throw PGUtil.ThrowIfReached();
            }
        }
Example #12
0
        internal override bool Write(WriteBuffer buf)
        {
            Contract.Requires(Statement != null);

            switch (_state)
            {
                case State.WroteNothing:
                    _statementNameBytes = Statement.Length == 0 ? PGUtil.EmptyBuffer : _encoding.GetBytes(Statement);
                    _queryLen = _encoding.GetByteCount(Query);
                    if (buf.WriteSpaceLeft < 1 + 4 + _statementNameBytes.Length + 1) {
                        return false;
                    }

                    var messageLength =
                        1 +                         // Message code
                        4 +                         // Length
                        _statementNameBytes.Length +
                        1 +                         // Null terminator
                        _queryLen +
                        1 +                         // Null terminator
                        2 +                         // Number of parameters
                        ParameterTypeOIDs.Count * 4;

                    buf.WriteByte(Code);
                    buf.WriteInt32(messageLength - 1);
                    buf.WriteBytesNullTerminated(_statementNameBytes);
                    goto case State.WroteHeader;

                case State.WroteHeader:
                    _state = State.WroteHeader;

                    if (_queryLen <= buf.WriteSpaceLeft) {
                        buf.WriteString(Query);
                        goto case State.WroteQuery;
                    }

                    if (_queryLen <= buf.Size) {
                        // String can fit entirely in an empty buffer. Flush and retry rather than
                        // going into the partial writing flow below (which requires ToCharArray())
                        return false;
                    }

                    _queryChars = Query.ToCharArray();
                    _charPos = 0;
                    goto case State.WritingQuery;

                case State.WritingQuery:
                    _state = State.WritingQuery;
                    int charsUsed;
                    bool completed;
                    buf.WriteStringChunked(_queryChars, _charPos, _queryChars.Length - _charPos, true,
                                           out charsUsed, out completed);
                    if (!completed)
                    {
                        _charPos += charsUsed;
                        return false;
                    }
                    goto case State.WroteQuery;

                case State.WroteQuery:
                    _state = State.WroteQuery;
                    if (buf.WriteSpaceLeft < 1 + 2) {
                        return false;
                    }
                    buf.WriteByte(0); // Null terminator for the query
                    buf.WriteInt16((short)ParameterTypeOIDs.Count);
                    goto case State.WritingParameterTypes;

                case State.WritingParameterTypes:
                    _state = State.WritingParameterTypes;
                    for (; _parameterTypePos < ParameterTypeOIDs.Count; _parameterTypePos++)
                    {
                        if (buf.WriteSpaceLeft < 4)
                        {
                            return false;
                        }
                        buf.WriteInt32((int)ParameterTypeOIDs[_parameterTypePos]);
                    }

                    _state = State.WroteAll;
                    return true;

                default:
                    throw PGUtil.ThrowIfReached();
            }
        }
Example #13
0
        internal override async Task Write(WriteBuffer buf, bool async, CancellationToken cancellationToken)
        {
            Debug.Assert(Statement != null && Statement.All(c => c < 128));
            Debug.Assert(Portal != null && Portal.All(c => c < 128));

            var headerLength =
                1 +                        // Message code
                4 +                        // Message length
                1 +                        // Portal is always empty (only a null terminator)
                Statement.Length + 1 +
                2;                         // Number of parameter format codes that follow

            if (buf.WriteSpaceLeft < headerLength)
            {
                Debug.Assert(buf.Size >= headerLength, "Buffer too small for Bind header");
                await buf.Flush(async, cancellationToken);
            }

            var formatCodesSum = 0;
            var paramsLength   = 0;

            foreach (var p in InputParameters)
            {
                formatCodesSum += (int)p.FormatCode;
                p.LengthCache?.Rewind();
                paramsLength += p.ValidateAndGetLength();
            }

            var formatCodeListLength = formatCodesSum == 0 ? 0 : formatCodesSum == InputParameters.Count ? 1 : InputParameters.Count;

            var messageLength = headerLength +
                                2 * formatCodeListLength +                // List of format codes
                                2 +                                       // Number of parameters
                                4 * InputParameters.Count +               // Parameter lengths
                                paramsLength +                            // Parameter values
                                2 +                                       // Number of result format codes
                                2 * (UnknownResultTypeList?.Length ?? 1); // Result format codes

            buf.WriteByte(Code);
            buf.WriteInt32(messageLength - 1);
            Debug.Assert(Portal == string.Empty);
            buf.WriteByte(0);  // Portal is always empty

            buf.WriteNullTerminatedString(Statement);
            buf.WriteInt16(formatCodeListLength);

            // 0 length implicitly means all-text, 1 means all-binary, >1 means mix-and-match
            if (formatCodeListLength == 1)
            {
                if (buf.WriteSpaceLeft < 2)
                {
                    await buf.Flush(async, cancellationToken);
                }
                buf.WriteInt16((short)FormatCode.Binary);
            }
            else if (formatCodeListLength > 1)
            {
                foreach (NpgsqlParameter p in InputParameters)
                {
                    if (buf.WriteSpaceLeft < 2)
                    {
                        await buf.Flush(async, cancellationToken);
                    }
                    buf.WriteInt16((short)p.FormatCode);
                }
            }

            if (buf.WriteSpaceLeft < 2)
            {
                await buf.Flush(async, cancellationToken);
            }

            buf.WriteInt16(InputParameters.Count);

            foreach (var param in InputParameters)
            {
                param.LengthCache?.Rewind();
                await param.WriteWithLength(buf, async, cancellationToken);
            }

            if (UnknownResultTypeList != null)
            {
                if (buf.WriteSpaceLeft < 2 + UnknownResultTypeList.Length * 2)
                {
                    await buf.Flush(async, cancellationToken);
                }
                buf.WriteInt16(UnknownResultTypeList.Length);
                foreach (var t in UnknownResultTypeList)
                {
                    buf.WriteInt16(t ? 0 : 1);
                }
            }
            else
            {
                if (buf.WriteSpaceLeft < 4)
                {
                    await buf.Flush(async, cancellationToken);
                }
                buf.WriteInt16(1);
                buf.WriteInt16(AllResultTypesAreUnknown ? 0 : 1);
            }
        }