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); } } }
/// <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); }
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); }
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);
private void GrowAndEnsure() { Flush(); int previousSpanLength = _buffer.Length; Debug.Assert(previousSpanLength < DefaultGrowthSize); _buffer = _output.GetSpan(DefaultGrowthSize); if (_buffer.Length <= previousSpanLength) { ThrowHelper.ThrowArgumentException(ExceptionResource.FailedToGetLargerSpan); } }
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); }
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); } } }
private void EnsureBuffer() { if (_writer is null) { throw new InvalidOperationException("Writer is not initialized."); } if (_buffer.IsEmpty) { Flush(); _buffer = _writer.GetSpan(); } }
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); }
/// <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); }
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); }
/// <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); } } }
/// <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); }
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); }
/// <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); } }
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); } }
/// <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); }
private static void Write(IBufferWriter <byte> writer, byte[] buffer) { var span = writer.GetSpan(buffer.Length); buffer.AsSpan().CopyTo(span); writer.Advance(buffer.Length); }
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); } } }
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); }
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); }
public static void WriteRecordSeparator(IBufferWriter <byte> output) { var buffer = output.GetSpan(1); buffer[0] = RecordSeparator; output.Advance(1); }
/// <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); }