private static bool TryReadStringImpl(ReadOnlySequence <byte> sequence, out string value, ref int readSize, Decoder decoder) { value = ReadStringImpl(sequence, decoder); readSize += sequence.GetIntLength(); return(true); }
private static string ReadStringImpl(ReadOnlySequence <byte> sequence, Decoder decoder) { if (sequence.IsSingleSegment) { return(ReadStringImpl(sequence.First.Span, decoder)); } var safeDecoder = decoder.GetThreadStatic(); using (var rentedBuffer = MemoryPool <char> .Shared.Rent(sequence.GetIntLength())) { var chars = rentedBuffer.Memory.Span; var length = 0; var leftOver = ReadOnlySpan <byte> .Empty; foreach (var memory in sequence) { if (memory.IsEmpty) { continue; } var bytes = memory.Span; using (var rentedBytes = GetMemoryOwner(leftOver, bytes)) { safeDecoder.Convert( rentedBytes != null ? rentedBytes.Memory.Span : bytes, chars, false, out var bytesUsed, out var charsUsed, out var completed); chars = chars.Slice(charsUsed); length += charsUsed; leftOver = completed ? ReadOnlySpan <byte> .Empty : bytes.Slice(bytesUsed - leftOver.Length); } } if (!leftOver.IsEmpty) { throw GetInvalidStringException(); } return(rentedBuffer.Memory.Span.Slice(0, length).ToString()); } IMemoryOwner <byte> GetMemoryOwner(ReadOnlySpan <byte> leftOver, ReadOnlySpan <byte> bytes) { if (leftOver.IsEmpty) { return(null); } var owner = FixedLengthMemoryPool <byte> .Shared.Rent(leftOver.Length + bytes.Length); var span = owner.Memory.Span; leftOver.CopyTo(span); bytes.CopyTo(span.Slice(leftOver.Length)); return(owner); } }