public void Write(int nbits, uint value)
                {
                    while (nbits != 0)
                    {
                        int nb = Math.Min(MaxBitBufferCount - _bitBufferCount, nbits);
                        _bitBuffer     <<= nb;
                        value           &= Bitmask(nbits);
                        _bitBuffer      |= value >> (nbits - nb);
                        _bitBufferCount += nb;
                        nbits           -= nb;

                        int byteCount = (_bitBufferCount / 8);

                        if (byteCount != 0)
                        {
                            fixed(byte *buffer = _bufferWriter.GetSpan(byteCount))
                            {
                                for (int i = 0; i < byteCount; i++)
                                {
                                    buffer[i]        = (byte)((_bitBuffer >> (_bitBufferCount - 8)) & Bitmask(8));
                                    _bitBufferCount -= 8;
                                    _bitBuffer      &= Bitmask(_bitBufferCount);
                                }
                            }

                            _bufferWriter.Advance(byteCount);
                        }
                    }
                }
Esempio n. 2
0
        /// <summary>
        /// Writes contents of <paramref name="source"/> to <paramref name="bufferWriter"/>
        /// </summary>
        public static void Write <T>(this IBufferWriter <T> bufferWriter, ReadOnlySpan <T> source)
        {
            Span <T> destination = bufferWriter.GetSpan();

            // Fast path, try copying to the available memory directly
            if (source.Length <= destination.Length)
            {
                source.CopyTo(destination);
                bufferWriter.Advance(source.Length);
                return;
            }

            while (source.Length > 0)
            {
                int writeSize = destination.Length;

                if (destination.Length == 0)
                {
                    writeSize   = Math.Min(source.Length, bufferWriter.MaxBufferSize);
                    destination = bufferWriter.GetSpan(writeSize);
                }

                source.Slice(0, writeSize).CopyTo(destination);
                bufferWriter.Advance(writeSize);
                source      = source.Slice(writeSize);
                destination = default;
            }
        }
            private void EncodeLiteralRow(ReadOnlySpan <byte> pixels)
            {
                int         index = 0;
                Span <byte> span  = _writer.GetSpan(1 + (pixels.Length + 3) / 4);

                span[index++] = 0x00;

                while (pixels.Length >= 4)
                {
                    span[index++] = (byte)((pixels[0] & 0b11000000) | ((pixels[1] & 0b11000000) >> 2) | ((pixels[2] & 0b11000000) >> 4) | ((pixels[3] & 0b11000000) >> 6));
                    pixels        = pixels.Slice(4);
                }

                switch (pixels.Length)
                {
                case 1:
                    span[index++] = (byte)((pixels[0] & 0b11000000));
                    break;

                case 2:
                    span[index++] = (byte)((pixels[0] & 0b11000000) | ((pixels[1] & 0b11000000) >> 2));
                    break;

                case 3:
                    span[index++] = (byte)((pixels[0] & 0b11000000) | ((pixels[1] & 0b11000000) >> 2) | ((pixels[2] & 0b11000000) >> 4));
                    break;
                }

                _writer.Advance(index);
            }
Esempio n. 4
0
        private int EncodeFragment(IBufferWriter <byte> writer, byte opCode, int expectedHeadLength, int fragmentSize, ReadOnlySpan <char> text, Encoder encoder, out int charsUsed)
        {
            charsUsed = 0;

            var head = writer.GetSpan(expectedHeadLength);

            writer.Advance(expectedHeadLength);

            var buffer = writer.GetSpan(fragmentSize).Slice(0, fragmentSize);

            encoder.Convert(text, buffer, false, out charsUsed, out int bytesUsed, out bool completed);
            writer.Advance(bytesUsed);

            var totalBytes = bytesUsed;
            var isFinal    = completed && text.Length == charsUsed;

            if (isFinal)
            {
                opCode = (byte)(opCode | 0x80);
            }

            WriteHead(ref head, opCode, totalBytes);

            return(totalBytes + expectedHeadLength);
        }
Esempio n. 5
0
    private protected static void EncodeItemHeader(SecsFormat format, int count, IBufferWriter <byte> buffer)
    {
        var lengthSpan = Unsafe.AsRef(count).AsBytes();

        var formatByte = (int)format << 2;

        if (count <= 0xff)
        {//	1 byte
            var span = buffer.GetSpan(sizeHint: 2);
            span.DangerousGetReferenceAt(0) = (byte)(formatByte | 1);
            span.DangerousGetReferenceAt(1) = lengthSpan.DangerousGetReferenceAt(0);
            buffer.Advance(2);
            return;
        }
        if (count <= 0xffff)
        {//	2 byte
            var span = buffer.GetSpan(sizeHint: 3);
            span.DangerousGetReferenceAt(0) = (byte)(formatByte | 2);
            span.DangerousGetReferenceAt(1) = lengthSpan.DangerousGetReferenceAt(1);
            span.DangerousGetReferenceAt(2) = lengthSpan.DangerousGetReferenceAt(0);
            buffer.Advance(3);
            return;
        }
        if (count <= 0xffffff)
        {//	3 byte
            var span = buffer.GetSpan(sizeHint: 4);
            span.DangerousGetReferenceAt(0) = (byte)(formatByte | 3);
            span.DangerousGetReferenceAt(1) = lengthSpan.DangerousGetReferenceAt(2);
            span.DangerousGetReferenceAt(2) = lengthSpan.DangerousGetReferenceAt(1);
            span.DangerousGetReferenceAt(3) = lengthSpan.DangerousGetReferenceAt(0);
            buffer.Advance(4);
            return;
        }

        ThrowHelper(count);
Esempio n. 6
0
        private void GrowAndEnsure()
        {
            Flush();
            int previousSpanLength = _buffer.Length;

            Debug.Assert(previousSpanLength < DefaultGrowthSize);
            _buffer = _output.GetSpan(DefaultGrowthSize);
            if (_buffer.Length <= previousSpanLength)
            {
                ThrowHelper.ThrowArgumentException(ExceptionResource.FailedToGetLargerSpan);
            }
        }
Esempio n. 7
0
        public void WriteMessage(AddIntegerRequest message, IBufferWriter <byte> output)
        {
            int size    = sizeof(int);
            var memoryA = output.GetSpan(size);

            BinaryPrimitives.WriteInt32BigEndian(memoryA, message.A);
            output.Advance(size);
            var memoryB = output.GetSpan(size);

            BinaryPrimitives.WriteInt32BigEndian(memoryB, message.B);
            output.Advance(size);
        }
Esempio n. 8
0
        public static void SetUInt32(uint value, IBufferWriter <byte> writer)
        {
            unchecked
            {
                if (value <= MaxInt7)
                {
                    var span = writer.GetSpan(1);
                    span[0] = (byte)value;

                    writer.Advance(1);
                }
                else if (value <= byte.MaxValue)
                {
                    var span = writer.GetSpan(2);
                    span[0] = Int8Code;
                    span[1] = (byte)value;

                    writer.Advance(2);
                }
                else if (value <= ushort.MaxValue)
                {
                    var span = writer.GetSpan(3);

                    fixed(byte *p = span)
                    {
                        p[0] = Int16Code;

                        ushort *uint_p = (ushort *)(p + 1);

                        *uint_p = (ushort)value;
                    }

                    writer.Advance(3);
                }
                else
                {
                    var span = writer.GetSpan(5);

                    fixed(byte *p = span)
                    {
                        span[0] = Int32Code;

                        uint *uint_p = (uint *)(p + 1);

                        *uint_p = (uint)value;
                    }

                    writer.Advance(5);
                }
            }
        }
Esempio n. 9
0
        private void EnsureBuffer()
        {
            if (_writer is null)
            {
                throw new InvalidOperationException("Writer is not initialized.");
            }

            if (_buffer.IsEmpty)
            {
                Flush();

                _buffer = _writer.GetSpan();
            }
        }
Esempio n. 10
0
        public void Serialize(IBufferWriter <byte> writer, Transaction transaction)
        {
            if (!this.serializers.TryGetValue(transaction.Id, out var serializer))
            {
                throw new ArgumentException("The transaction is not supported.", nameof(transaction));
            }

            BinaryPrimitives.WriteUInt16BigEndian(writer.GetSpan(2), Convert.ToUInt16(transaction.Version));
            writer.Advance(2);

            BinaryPrimitives.WriteUInt16BigEndian(writer.GetSpan(2), Convert.ToUInt16(transaction.Id));
            writer.Advance(2);

            serializer.Serialize(writer, transaction);
        }
Esempio n. 11
0
    /// <summary>
    /// Encodes a hash bucket into the buffer.
    /// </summary>
    /// <param name="bucket">The bucket.</param>
    /// <param name="bufferWriter">The buffer.</param>
    public static void EncodeHashBucket(int bucket, IBufferWriter <byte> bufferWriter)
    {
        Span <byte> span = bufferWriter.GetSpan(4);

        BinaryPrimitives.WriteInt32BigEndian(span, bucket);
        bufferWriter.Advance(4);
    }
        public static int WriteUInt(this IBufferWriter <byte> writer, uint value, bool isBigEndian = false)
        {
            const int size = 4;

            if (isBigEndian)
            {
                BinaryPrimitives.WriteUInt32BigEndian(writer.GetSpan(size), value);
            }
            else
            {
                BinaryPrimitives.WriteUInt32LittleEndian(writer.GetSpan(size), value);
            }

            writer.Advance(size);
            return(size);
        }
        public static int WriteLong(this IBufferWriter <byte> writer, long value, bool isBigEndian = false)
        {
            const int size = 8;

            if (isBigEndian)
            {
                BinaryPrimitives.WriteInt64BigEndian(writer.GetSpan(size), value);
            }
            else
            {
                BinaryPrimitives.WriteInt64LittleEndian(writer.GetSpan(size), value);
            }

            writer.Advance(size);
            return(size);
        }
Esempio n. 14
0
        private void DecodeCore(ReadOnlySpan <char> chars, IBufferWriter <byte> output)
        {
            var size = chars.Length & 3;

            if (size > 0)
            {
                // size of the rest
                size = chars.Length - size;
                var rest = chars.Slice(size);
                rest.CopyTo(ReservedChars);
                reservedBufferSize = rest.Length; // keep the number of chars, not bytes
                chars = chars.Slice(0, size);
            }
            else
            {
                reservedBufferSize = 0;
            }

            // 4 characters => 3 bytes
            var buffer = output.GetSpan(chars.Length);

            if (!Convert.TryFromBase64Chars(chars, buffer, out size))
            {
                throw new FormatException(ExceptionMessages.MalformedBase64);
            }
            output.Advance(size);
        }
Esempio n. 15
0
        /// <summary>
        /// 转换编码
        /// </summary>
        /// <param name="srcEncoding"></param>
        /// <param name="dstEncoding">目标编码</param>
        /// <param name="buffer">源内容</param>
        /// <param name="writer">目标写入器</param>
        public static void Convert(this Encoding srcEncoding, Encoding dstEncoding, ReadOnlySpan <byte> buffer, IBufferWriter <byte> writer)
        {
            var decoder   = srcEncoding.GetDecoder();
            var charCount = decoder.GetCharCount(buffer, false);
            var charArray = charCount > 1024 ? ArrayPool <char> .Shared.Rent(charCount) : null;

            var chars = charArray == null ? stackalloc char[charCount] : charArray.AsSpan().Slice(0, charCount);

            try
            {
                decoder.Convert(buffer, chars, true, out _, out var charsUsed, out _);
                Debug.Assert(charCount == charsUsed);

                var encoder   = dstEncoding.GetEncoder();
                var byteCount = encoder.GetByteCount(chars, false);
                var bytes     = writer.GetSpan(byteCount);

                encoder.Convert(chars, bytes, true, out _, out var byteUsed, out _);
                Debug.Assert(byteCount == byteUsed);
                writer.Advance(byteUsed);
            }
            finally
            {
                if (charArray != null)
                {
                    ArrayPool <char> .Shared.Return(charArray);
                }
            }
        }
Esempio n. 16
0
        /// <summary>
        /// Writes single element to the buffer.
        /// </summary>
        /// <param name="writer">The buffer writer.</param>
        /// <param name="value">The value to add.</param>
        /// <typeparam name="T">The type of elements in the buffer.</typeparam>
        public static void Write <T>(this IBufferWriter <T> writer, T value)
        {
            const int count = 1;

            writer.GetSpan(count)[0] = value;
            writer.Advance(count);
        }
Esempio n. 17
0
 public static void SerializePropertyId(IBufferWriter <byte> writer, PropertyId?value)
 {
     BinaryPrimitives.WriteUInt32BigEndian(
         writer.GetSpan(4),
         (value != null) ? Convert.ToUInt32(value.Value) : 0);
     writer.Advance(4);
 }
        private static Span <byte> GetSpanForValue(IBufferWriter <byte> writer, byte code, int size)
        {
            var span = writer.GetSpan(size + 1);

            span[0] = code;
            return(span.Slice(1));
        }
        /// <summary>
        /// Writes a <see cref="System.Boolean"/> value.
        /// </summary>
        /// <param name="value">Value to write.</param>
        /// <param name="writer">Buffer writer to write the value to.</param>
        internal void WritePrimitive_Boolean(bool value, IBufferWriter <byte> writer)
        {
            var buffer = writer.GetSpan(1);

            buffer[0] = (byte)(value ? PayloadType.BooleanTrue : PayloadType.BooleanFalse);
            writer.Advance(1);
        }
Esempio n. 20
0
        /// <summary>
        /// Uri编码
        /// </summary>
        /// <param name="chars"></param>
        /// <param name="bufferWriter"></param>
        public static void UrlEncode(ReadOnlySpan <char> chars, IBufferWriter <byte> bufferWriter)
        {
            if (chars.IsEmpty)
            {
                return;
            }

            var byteCount = Encoding.UTF8.GetByteCount(chars);
            var source    = chars.Length > 1024 ? new byte[byteCount] : stackalloc byte[byteCount];

            Encoding.UTF8.GetBytes(chars, source);

            var destLength = 0;

            if (UrlEncodeTest(source, ref destLength) == false)
            {
                bufferWriter.Write(source);
            }
            else
            {
                var destination = bufferWriter.GetSpan(destLength);
                UrlEncodeCore(source, destination);
                bufferWriter.Advance(destLength);
            }
        }
Esempio n. 21
0
        public static void WriteByte(this IBufferWriter <byte> writer, byte x)
        {
            var span = writer.GetSpan(1);

            span[0] = x;
            writer.Advance(1);
        }
        /// <summary>
        /// Encodes the specified <see cref="ReadOnlySpan{Char}"/> to <see langword="byte"/>s using the specified <see cref="Encoding"/>
        /// and writes the result to <paramref name="writer"/>.
        /// </summary>
        /// <param name="encoding">The <see cref="Encoding"/> which represents how the data in <paramref name="chars"/> should be encoded.</param>
        /// <param name="chars">The <see cref="ReadOnlySequence{Char}"/> to encode to <see langword="byte"/>s.</param>
        /// <param name="writer">The buffer to which the encoded bytes will be written.</param>
        /// <exception cref="EncoderFallbackException">Thrown if <paramref name="chars"/> contains data that cannot be encoded and <paramref name="encoding"/> is configured
        /// to throw an exception when such data is seen.</exception>
        public static long GetBytes(this Encoding encoding, ReadOnlySpan <char> chars, IBufferWriter <byte> writer)
        {
            if (encoding is null)
            {
                throw new ArgumentNullException(nameof(encoding));
            }

            if (writer is null)
            {
                throw new ArgumentNullException(nameof(writer));
            }

            if (chars.Length <= MaxInputElementsPerIteration)
            {
                // The input span is small enough where we can one-shot this.

                int         byteCount     = encoding.GetByteCount(chars);
                Span <byte> scratchBuffer = writer.GetSpan(byteCount);

                int actualBytesWritten = encoding.GetBytes(chars, scratchBuffer);

                writer.Advance(actualBytesWritten);
                return(actualBytesWritten);
            }
            else
            {
                // Allocate a stateful Encoder instance and chunk this.

                Convert(encoding.GetEncoder(), chars, writer, flush: true, out long totalBytesWritten, out bool completed);
                return(totalBytesWritten);
            }
        }
Esempio n. 23
0
        /// <summary>
        /// Writes the given <typeparamref name="TNodeId"/> to the specified buffer writer.
        /// </summary>
        /// <param name="self"></param>
        /// <param name="writer"></param>
        public static void Write(TNodeId self, IBufferWriter <byte> writer)
        {
            var s = SizeOf;

            Write(self, writer.GetSpan(s));
            writer.Advance(s);
        }
Esempio n. 24
0
        private static void Write(IBufferWriter <byte> writer, byte[] buffer)
        {
            var span = writer.GetSpan(buffer.Length);

            buffer.AsSpan().CopyTo(span);
            writer.Advance(buffer.Length);
        }
Esempio n. 25
0
        public static bool TryWrite(uint version, ReadOnlySequence <byte> sequence, IBufferWriter <byte> writer)
        {
            Varint.SetUInt32(version, writer);
            Varint.SetUInt32((uint)ConvertCompressionAlgorithm.Brotli, writer);

            using var encoder = new BrotliEncoder(0, 10);

            var reader = new SequenceReader <byte>(sequence);

            for (; ;)
            {
                var status = encoder.Compress(reader.UnreadSpan, writer.GetSpan(), out var bytesConsumed, out var bytesWritten, false);

                if (status == OperationStatus.InvalidData)
                {
                    _logger.Warn("invalid data");
                    return(false);
                }

                reader.Advance(bytesConsumed);
                writer.Advance(bytesWritten);

                if (status == OperationStatus.Done)
                {
                    return(true);
                }
            }
        }
Esempio n. 26
0
        public static int Write(this IBufferWriter <byte> writer, ReadOnlySpan <char> text, Encoding encoding)
        {
            var encoder    = encoding.GetEncoder();
            var completed  = false;
            var totalBytes = 0;

            var minSpanSizeHint = encoding.GetMaxByteCount(1);

            while (!completed)
            {
                var span = writer.GetSpan(minSpanSizeHint);

                encoder.Convert(text, span, false, out int charsUsed, out int bytesUsed, out completed);

                if (charsUsed > 0)
                {
                    text = text.Slice(charsUsed);
                }

                totalBytes += bytesUsed;
                writer.Advance(bytesUsed);
            }

            return(totalBytes);
        }
        private static bool TryDecompress(ref MessagePackReader reader, IBufferWriter <byte> writer)
        {
            if (!reader.End && reader.NextMessagePackType == MessagePackType.Extension)
            {
                var peekReader = reader.CreatePeekReader();
                var header     = peekReader.ReadExtensionFormatHeader();
                if (header.TypeCode == ExtensionTypeCode)
                {
                    // Read the extension using the original reader, so we "consume" it.
                    var extension = reader.ReadExtensionFormat();
                    var extReader = new MessagePackReader(extension.Data);

                    // The first part of the extension payload is a MessagePack-encoded Int32 that
                    // tells us the length the data will be AFTER decompression.
                    int uncompressedLength = extReader.ReadInt32();

                    // The rest of the payload is the compressed data itself.
                    var compressedData = extReader.Sequence.Slice(extReader.Position);

                    var uncompressedSpan         = writer.GetSpan(uncompressedLength).Slice(0, uncompressedLength);
                    int actualUncompressedLength = LZ4Operation(compressedData, uncompressedSpan, LZ4Codec.Decode);
                    Debug.Assert(actualUncompressedLength == uncompressedLength);
                    writer.Advance(actualUncompressedLength);
                    return(true);
                }
            }

            return(false);
        }
Esempio n. 28
0
        public static void WriteStringWithEncoding(this IBufferWriter <byte> writer, string s, Encoding encoding)
        {
            var chunk = writer.GetSpan(encoding.GetByteCount(s));
            var count = encoding.GetBytes(s.AsSpan(), chunk);

            writer.Advance(count);
        }
Esempio n. 29
0
    public static void WriteRecordSeparator(IBufferWriter <byte> output)
    {
        var buffer = output.GetSpan(1);

        buffer[0] = RecordSeparator;
        output.Advance(1);
    }
Esempio n. 30
0
        /// <summary>
        /// Writes the given <typeparamref name="KIpEndpoint"/> to the specified buffer writer.
        /// </summary>
        /// <param name="self"></param>
        /// <param name="writer"></param>
        public static void Write(KIpEndpoint self, IBufferWriter <byte> writer)
        {
            var s = Unsafe.SizeOf <KIpEndpoint>();

            Write(self, writer.GetSpan(s));
            writer.Advance(s);
        }