private static void Write(IBufferWriter <T> writer, IReadOnlyList <T> values)
                {
                    Span <T> span = writer.GetSpan(values.Count);

                    for (int i = 0; i < values.Count; i++)
                    {
                        span[i] = values[i];
                    }

                    writer.Advance(values.Count);
                }
예제 #2
0
        private void EnsureBuffer()
        {
            // We need at least enough bytes to encode a single UTF-8 character, or Encoder.Convert will throw.
            // Normally, if there isn't enough space to write every character of a char buffer, Encoder.Convert just
            // writes what it can. However, if it can't even write a single character, it throws. So if the buffer has only
            // 2 bytes left and the next character to write is 3 bytes in UTF-8, an exception is thrown.
            var remaining = _memory.Length - _memoryUsed;

            if (remaining < MaximumBytesPerUtf8Char)
            {
                // Used up the memory from the buffer writer so advance and get more
                if (_memoryUsed > 0)
                {
                    _bufferWriter.Advance(_memoryUsed);
                }

                _memory     = _bufferWriter.GetMemory(MaximumBytesPerUtf8Char);
                _memoryUsed = 0;
            }
        }
예제 #3
0
        public static void Write(this IBufferWriter <byte> bufferWriter, Stream stream)
        {
            long remain = stream.Length - stream.Position;

            while (remain > 0)
            {
                var span       = bufferWriter.GetSpan();
                int readLength = stream.Read(span);
                bufferWriter.Advance(readLength);
            }
        }
예제 #4
0
        public void Commit()
        {
            if (this.buffered <= 0)
            {
                return;
            }

            var oldBuffered = this.buffered;

            this.MigrateToSequence();

            bytesCommitted += oldBuffered;
            this.buffered   = 0;
#if CSHARP_8_OR_NEWER
            output !.Advance(oldBuffered);
#else
            output.Advance(oldBuffered);
#endif
            innerSpan = default;
        }
예제 #5
0
        static void Write(IBufferWriter <byte> writer, string message1, string message2)
        {
            var memory = writer.GetMemory(Encoding.UTF8.GetMaxByteCount(message1.Length + message2.Length));

            if (MemoryMarshal.TryGetArray <byte>(memory, out var array) && array.Array != null)
            {
                var written1 = Encoding.UTF8.GetBytes(message1, 0, message1.Length, array.Array, array.Offset);
                var written2 = Encoding.UTF8.GetBytes(message2, 0, message2.Length, array.Array, array.Offset + written1);
                writer.Advance(written1 + written2);
            }
        }
예제 #6
0
        /// <summary>
        /// Commits the JSON text written so far which makes it visible to the output destination.
        /// </summary>
        /// <remarks>
        /// In the case of IBufferWriter, this advances the underlying <see cref="IBufferWriter{Byte}" /> based on what has been written so far.
        /// In the case of Stream, this writes the data to the stream and flushes it.
        /// </remarks>
        /// <exception cref="ObjectDisposedException">
        ///   The instance of <see cref="Utf8JsonWriter"/> has been disposed.
        /// </exception>
        public void Flush()
        {
            CheckNotDisposed();

            _memory = default;

            if (_stream != null)
            {
                Debug.Assert(_arrayBufferWriter != null);
                if (BytesPending != 0)
                {
                    _arrayBufferWriter.Advance(BytesPending);
                    BytesPending = 0;

#if BUILDING_INBOX_LIBRARY
                    _stream.Write(_arrayBufferWriter.WrittenSpan);
#else
                    Debug.Assert(_arrayBufferWriter.WrittenMemory.Length == _arrayBufferWriter.WrittenCount);
                    bool result = MemoryMarshal.TryGetArray(_arrayBufferWriter.WrittenMemory, out ArraySegment <byte> underlyingBuffer);
                    Debug.Assert(result);
                    Debug.Assert(underlyingBuffer.Offset == 0);
                    Debug.Assert(_arrayBufferWriter.WrittenCount == underlyingBuffer.Count);
                    _stream.Write(underlyingBuffer.Array, underlyingBuffer.Offset, underlyingBuffer.Count);
#endif

                    BytesCommitted += _arrayBufferWriter.WrittenCount;
                    _arrayBufferWriter.Clear();
                }
                _stream.Flush();
            }
            else
            {
                Debug.Assert(_output != null);
                if (BytesPending != 0)
                {
                    _output.Advance(BytesPending);
                    BytesCommitted += BytesPending;
                    BytesPending    = 0;
                }
            }
        }
        /// <summary>Compresses input buffer into self-contained package.</summary>
        /// <param name="source">Input buffer.</param>
        /// <param name="writer">Where the compressed data is written.</param>
        /// <param name="level">Compression level.</param>
        /// <returns>Output buffer.</returns>
        public static void Pickle(
            ReadOnlySpan <byte> source, IBufferWriter <byte> writer,
            LZ4Level level = LZ4Level.L00_FAST)
        {
            if (writer is null)
            {
                throw new ArgumentNullException(nameof(writer));
            }

            var sourceLength = source.Length;

            if (sourceLength == 0)
            {
                return;
            }

            // this might be an argument at some point
            const int version = 0;

            // number of bytes is not decided on diff but rather of full length
            // although, diff would never be greater than full length
            var headerSize = GetPessimisticHeaderSize(version, sourceLength);
            var target     = writer.GetSpan(headerSize + sourceLength);

            var encodedLength = LZ4Codec.Encode(
                source, target.Slice(headerSize, sourceLength), level);

            if (encodedLength <= 0 || encodedLength >= sourceLength)
            {
                var offset = EncodeUncompressedHeader(target, version, sourceLength);
                source.CopyTo(target.Slice(offset));
                writer.Advance(offset + sourceLength);
            }
            else
            {
                var offset = EncodeCompressedHeader(
                    target, version, headerSize, sourceLength, encodedLength);
                Debug.Assert(headerSize == offset, "Unexpected header size");
                writer.Advance(offset + encodedLength);
            }
        }
예제 #8
0
        public void WriteMessage(Message message, IBufferWriter <byte> output)
        {
            var header = output.GetSpan(HeaderSize);

            BinaryPrimitives.WriteUInt32BigEndian(header, (uint)message.Payload.Length);
            output.Advance(HeaderSize);

            foreach (var msg in message.Payload)
            {
                output.Write(msg.Span);
            }
        }
예제 #9
0
    public static bool TryWrite(this IBufferWriter writer, ReadOnlySpan <byte> value)
    {
        var span = writer.GetSpan(value.Length);

        if (value.TryCopyTo(span))
        {
            writer.Advance(value.Length);
            return(true);
        }

        return(false);
    }
예제 #10
0
        private int EncodeSingleFragment(IBufferWriter <byte> writer, byte opCode, int expectedHeadLength, ReadOnlySpan <char> text)
        {
            var head = writer.GetSpan(expectedHeadLength);

            writer.Advance(expectedHeadLength);

            var totalBytes = text.Length > 0 ? writer.Write(text, _textEncoding) : 0;

            WriteHead(ref head, (byte)(opCode | 0x80), totalBytes);

            return(totalBytes + expectedHeadLength);
        }
        /// <summary>
        /// Writes a <see cref="System.SByte"/> value.
        /// </summary>
        /// <param name="value">Value to write.</param>
        /// <param name="writer">Buffer writer to write the value to.</param>
        internal void WritePrimitive_SByte(sbyte value, IBufferWriter <byte> writer)
        {
            var buffer = writer.GetSpan(2);

            unchecked
            {
                buffer[0] = (byte)PayloadType.SByte;
                buffer[1] = (byte)value;
            }

            writer.Advance(2);
        }
예제 #12
0
파일: Varint.cs 프로젝트: lulzzz/omnix
        public static void SetUInt8(byte value, IBufferWriter <byte> writer)
        {
            unchecked
            {
                if (value <= MaxInt7)
                {
                    var span = writer.GetSpan(1);
                    span[0] = value;

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

                    writer.Advance(2);
                }
            }
        }
        public static int WriteVarString(this IBufferWriter <byte> writer, string?value)
        {
            int stringLength = value?.Length ?? 0;
            int size         = WriteVarInt(writer, (ulong)stringLength);

            if (stringLength > 0)
            {
                Encoding.ASCII.GetBytes(value.AsSpan(), writer.GetSpan(stringLength));
                writer.Advance(stringLength);
            }
            return(size + stringLength);
        }
예제 #14
0
        public void Commit()
        {
            var buffered = _buffered;

            if (buffered > 0)
            {
                _bytesCommitted += buffered;
                _buffered        = 0;
                _output.Advance(buffered);
                _span = default;
            }
        }
예제 #15
0
 public static void Transliterate(this Rune r, IBufferWriter <byte> writer)
 {
     if (r.IsAscii)
     {
         writer.GetSpan(1)[0] = (byte)r.Value;
         writer.Advance(1);
     }
     else
     {
         writer.Write(Transliterate(r));
     }
 }
        /// <inheritdoc />
        public void Compress(TiffCompressionContext context, ReadOnlyMemory <byte> input, IBufferWriter <byte> outputWriter)
        {
            if (context is null)
            {
                throw new ArgumentNullException(nameof(context));
            }

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

            var deflater = new Deflater((int)_compressionLevel, noZlibHeaderOrFooter: false);

            int bytesWritten = deflater.Deflate(outputWriter.GetSpan());

            outputWriter.Advance(bytesWritten);

            deflater.SetInput(input);

            while (true)
            {
                bytesWritten = deflater.Deflate(outputWriter.GetSpan());

                if (bytesWritten != 0)
                {
                    outputWriter.Advance(bytesWritten);
                }

                if (deflater.IsFinished)
                {
                    break;
                }

                if (deflater.IsNeedingInput)
                {
                    deflater.Finish();
                }
            }
        }
예제 #17
0
        /// <summary>
        /// Uri编码
        /// </summary>
        /// <param name="str"></param>
        /// <param name="bufferWriter"></param>
        public static void UrlEncode(string?str, IBufferWriter <byte> bufferWriter)
        {
            if (string.IsNullOrEmpty(str))
            {
                return;
            }

            var source = Encoding.UTF8.GetBytes(str).AsSpan();

            if (UrlEncodeTest(source, out var destLength) == false)
            {
                var destination = bufferWriter.GetSpan(destLength);
                source.CopyTo(destination);
                bufferWriter.Advance(destLength);
            }
            else
            {
                var destination = bufferWriter.GetSpan(destLength);
                UrlEncodeCore(source, destination);
                bufferWriter.Advance(destLength);
            }
        }
예제 #18
0
    public static void Write(this IBufferWriter writer, ReadOnlySpan <byte> value)
    {
        var span = writer.GetSpan(value.Length);

        if (value.TryCopyTo(span))
        {
            writer.Advance(value.Length);
        }
        else
        {
            throw new InvalidOperationException("Can not copy value into buffer.");
        }
    }
예제 #19
0
        public void Commit()
        {
            var buffered = _buffered;
            if (buffered > 0)
            {
                this.MigrateToSequence();

                _bytesCommitted += buffered;
                _buffered = 0;
                _output.Advance(buffered);
                _span = default;
            }
        }
예제 #20
0
        internal static void WriteTrailers(IHeaderDictionary trailers, IBufferWriter <byte> output)
        {
            // Precalculate trailer size. Required for trailers header metadata
            var contentSize = CalculateHeaderSize(trailers);

            var totalSize = contentSize + HeaderSize;
            var buffer    = output.GetSpan(totalSize);

            WriteTrailersHeader(buffer, contentSize);
            WriteTrailersContent(buffer.Slice(HeaderSize), trailers);

            output.Advance(totalSize);
        }
예제 #21
0
        public int ReadMessage(ReadOnlySequence <byte> message, IBufferWriter <byte> output)
        {
            _logger.LogDebug($"Read message {message.Length} from encrypted");

            int numOfBytesRead = _reader.DecryptWithAd(null, message.ToArray(), // TODO David here we call to array should be replaced
                                                       output.GetSpan((int)message.Length));

            output.Advance(numOfBytesRead);

            KeyRecycle(_reader, _readerChainingKey);

            return(numOfBytesRead);
        }
예제 #22
0
        public void WriteMessage(MemcachedRequest message, IBufferWriter <byte> output)
        {
            Span <byte> headerSpan  = stackalloc byte[Constants.HeaderLength];
            byte        extraLength = 0;

            if (message.Flags != TypeCode.Empty)
            {
                extraLength = 8;
            }

            var messageValueLength = 0;

            if (message.Value != null)
            {
                messageValueLength = message.Value.Length;
            }

            var header = new MemcachedRequestHeader()
            {
                KeyLength       = (ushort)message.Key.Length,
                Opaque          = message.Opaque,
                TotalBodyLength = (uint)(extraLength + message.Key.Length + messageValueLength),
                ExtraLength     = extraLength
            };

            if (extraLength != 0)
            {
                header.Extras = (message.Flags, message.ExpireIn);
            }

            headerSpan[0] = MemcachedRequestHeader.Magic;
            headerSpan[1] = (byte)message.Opcode;
            BinaryPrimitives.WriteUInt16BigEndian(headerSpan.Slice(2), header.KeyLength);
            headerSpan[4] = header.ExtraLength;
            headerSpan[5] = header.DataType;
            BinaryPrimitives.WriteUInt16BigEndian(headerSpan.Slice(6), header.VBucket);
            BinaryPrimitives.WriteUInt32BigEndian(headerSpan.Slice(8), header.TotalBodyLength);
            BinaryPrimitives.WriteUInt32BigEndian(headerSpan.Slice(12), header.Opaque);
            BinaryPrimitives.WriteUInt64BigEndian(headerSpan.Slice(16), header.Cas);

            output.Write(headerSpan);

            var body = output.GetSpan((int)header.TotalBodyLength);

            BinaryPrimitives.WriteUInt32BigEndian(body.Slice(0), (uint)header.Extras.Flags);
            BinaryPrimitives.WriteUInt32BigEndian(body.Slice(4), (uint)header.Extras.Expiration.Value);

            message.Key.CopyTo(body.Slice(header.ExtraLength));
            message.Value.CopyTo(body.Slice(header.ExtraLength + message.Key.Length));
            output.Advance((int)header.TotalBodyLength);
        }
 public static int WriteVarInt(this IBufferWriter <byte> writer, ulong value)
 {
     if (value < 0xFD)
     {
         const int size = 1;
         writer.GetSpan(size)[0] = (byte)value;
         writer.Advance(size);
         return(size);
     }
     else if (value <= 0xFFFF)
     {
         const int   size = 3;
         Span <byte> span = writer.GetSpan(size);
         span[0] = 0xFD;
         BinaryPrimitives.WriteUInt16LittleEndian(span.Slice(1, size - 1), (ushort)value);
         writer.Advance(size);
         return(size);
     }
     else if (value == 0XFFFFFFFF)
     {
         const int   size = 5;
         Span <byte> span = writer.GetSpan(size);
         span[0] = 0xFE;
         BinaryPrimitives.WriteUInt32LittleEndian(span.Slice(1, size - 1), (uint)value);
         writer.Advance(size);
         return(size);
     }
     // == 0xFF
     else
     {
         const int   size = 9;
         Span <byte> span = writer.GetSpan(size);
         span[0] = 0xFF;
         BinaryPrimitives.WriteUInt64LittleEndian(span.Slice(1, size - 1), value);
         writer.Advance(size);
         return(size);
     }
 }
예제 #24
0
    public static bool TryWrite(ReadOnlySequence <byte> sequence, IBufferWriter <byte> writer)
    {
        Varint.SetUInt32((uint)FormatType.Version1, writer);
        Varint.SetUInt32((uint)CompressionAlgorithm.Brotli, writer);

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

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

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

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

            reader.Advance(bytesConsumed);

            crc32.Compute(destination.Slice(0, bytesWritten));
            writer.Advance(bytesWritten);

            if (status == OperationStatus.Done)
            {
                break;
            }
        }

        BinaryPrimitives.WriteUInt32BigEndian(writer.GetSpan(4), crc32.GetResult());
        writer.Advance(4);

        return(true);
    }
예제 #25
0
 private void Flush()
 {
     BytesCommitted += _buffered;
     if (_output == null)
     {
         Debug.Assert(_buffer.Length >= _buffered);
         _buffer = _buffer.Slice(_buffered);
     }
     else
     {
         _output.Advance(_buffered);
     }
     _buffered = 0;
 }
        /// <summary>
        /// Writes a <see cref="System.DateTime"/> object.
        /// </summary>
        /// <param name="value">DateTime object to write.</param>
        /// <param name="writer">Buffer writer to write the <see cref="System.DateTime"/> object to.</param>
        internal void WritePrimitive_DateTime(DateTime value, IBufferWriter <byte> writer)
        {
            // always use native encoding as the serialized value encodes both ticks and
            // datetime kind always resulting in a value that is too great to be encoded using
            // LEB128 with 7 bytes or less
            const int elementSize = sizeof(long);             // binary representation of a DateTime
            var       buffer      = writer.GetSpan(1 + elementSize);

            buffer[0] = (byte)PayloadType.DateTime;
            long binaryValue = value.ToBinary();

            MemoryMarshal.Write(buffer.Slice(1), ref binaryValue);
            writer.Advance(1 + elementSize);
        }
예제 #27
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;
            }

            WriteMultiSegment(bufferWriter, source, destination);
        }
        protected override void WriteData(IBufferWriter <byte> bufferWriter, int numBytes)
        {
            Span <byte> outputSpan = bufferWriter.GetSpan(numBytes);

            Assert.True(outputSpan.Length >= numBytes);
            var random = new Random(42);

            var data = new byte[numBytes];

            random.NextBytes(data);
            data.CopyTo(outputSpan);

            bufferWriter.Advance(numBytes);
        }
        public void Flush()
        {
            CheckNotDisposed();

            _memory = default;

            Debug.Assert(_output != null);
            if (BytesPending != 0)
            {
                _output.Advance(BytesPending);
                BytesCommitted += BytesPending;
                BytesPending    = 0;
            }
        }
예제 #30
0
        //TODO This might be better for one-liners to return the Memory object... Possibly better as an inlinable return value than a class reference?
        private void EnsureBuffer(int needed)
        {
            var remaining = Memory.Length - Used;

            if (remaining < needed)
            {
                if (Used > 0)
                {
                    _bufferWriter.Advance(Used);
                }
                Memory = _bufferWriter.GetMemory(needed);
                Used   = 0;
            }
        }