Skip to content

Commit 7a488a1

Browse files
committed
Fixed compatibility with unsigned 7-bit encoding
1 parent 1fac512 commit 7a488a1

File tree

9 files changed

+21
-20
lines changed

9 files changed

+21
-20
lines changed

src/DotNext.IO/Buffers/Binary/Leb128Reader.cs renamed to src/DotNext.IO/Buffers/Binary/SevenBitEncodedIntReader.cs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,16 +5,15 @@
55
namespace DotNext.Buffers.Binary;
66

77
[StructLayout(LayoutKind.Auto)]
8-
internal struct Leb128Reader<T>() : IBufferReader, ISupplier<T>
9-
where T : struct, IBinaryInteger<T>
8+
internal struct SevenBitEncodedIntReader() : IBufferReader, ISupplier<int>
109
{
11-
private Leb128<T> decoder;
10+
private Leb128<uint> decoder;
1211
private bool incompleted = true;
1312

1413
readonly int IBufferReader.RemainingBytes => Unsafe.BitCast<bool, byte>(incompleted);
1514

1615
void IReadOnlySpanConsumer<byte>.Invoke(ReadOnlySpan<byte> source)
1716
=> incompleted = decoder.Append(MemoryMarshal.GetReference(source));
1817

19-
readonly T ISupplier<T>.Invoke() => decoder.Value;
18+
readonly int ISupplier<int>.Invoke() => (int)decoder.Value;
2019
}

src/DotNext.IO/Buffers/BufferWriter.cs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ namespace DotNext.Buffers;
77

88
using EncodingContext = DotNext.Text.EncodingContext;
99
using LengthFormat = IO.LengthFormat;
10-
using SevenBitEncodedInt = Binary.Leb128<int>;
10+
using SevenBitEncodedInt = Binary.Leb128<uint>;
1111

1212
/// <summary>
1313
/// Represents extension methods for writing typed data into buffer.
@@ -44,15 +44,17 @@ static void WriteSlow(IBufferWriter<T> writer, in ReadOnlySequence<T> value)
4444

4545
internal static unsafe int WriteLength(this ref SpanWriter<byte> destination, int value, LengthFormat lengthFormat)
4646
{
47-
delegate*<ref SpanWriter<byte>, int, int> writer = lengthFormat switch
47+
Debug.Assert(value >= 0);
48+
49+
delegate*<ref SpanWriter<byte>, uint, int> writer = lengthFormat switch
4850
{
4951
LengthFormat.LittleEndian => &ByteBuffer.WriteLittleEndian,
5052
LengthFormat.BigEndian => &ByteBuffer.WriteBigEndian,
51-
LengthFormat.Compressed => &ByteBuffer.WriteLeb128<int>,
53+
LengthFormat.Compressed => &ByteBuffer.WriteLeb128<uint>,
5254
_ => throw new ArgumentOutOfRangeException(nameof(lengthFormat)),
5355
};
5456

55-
return writer(ref destination, value);
57+
return writer(ref destination, (uint)value);
5658
}
5759

5860
internal static int WriteLength(this IBufferWriter<byte> buffer, int length, LengthFormat lengthFormat)

src/DotNext.IO/IO/FileReader.Binary.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,7 @@ ValueTask<TReader> IAsyncBinaryReader.ReadAsync<TReader>(TReader reader, Cancell
127127
{
128128
LengthFormat.LittleEndian => ReadLittleEndianAsync<int>(token),
129129
LengthFormat.BigEndian => ReadBigEndianAsync<int>(token),
130-
LengthFormat.Compressed => ReadAsync<int, Leb128Reader<int>>(new(), token),
130+
LengthFormat.Compressed => ReadAsync<int, SevenBitEncodedIntReader>(new(), token),
131131
_ => ValueTask.FromException<int>(new ArgumentOutOfRangeException(nameof(lengthFormat))),
132132
};
133133

src/DotNext.IO/IO/FileWriter.Binary.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,7 @@ private int WriteLength(int length, LengthFormat lengthFormat)
142142
/// <exception cref="OperationCanceledException">The operation has been canceled.</exception>
143143
public async ValueTask WriteAsync(ReadOnlyMemory<byte> input, LengthFormat lengthFormat, CancellationToken token = default)
144144
{
145-
if (FreeCapacity < Leb128<int>.MaxSizeInBytes)
145+
if (FreeCapacity < Leb128<uint>.MaxSizeInBytes)
146146
await FlushAsync(token).ConfigureAwait(false);
147147

148148
WriteLength(input.Length, lengthFormat);
@@ -164,7 +164,7 @@ public async ValueTask<long> EncodeAsync(ReadOnlyMemory<char> chars, EncodingCon
164164
long result;
165165
if (lengthFormat.HasValue)
166166
{
167-
if (FreeCapacity < Leb128<int>.MaxSizeInBytes)
167+
if (FreeCapacity < Leb128<uint>.MaxSizeInBytes)
168168
await FlushAsync(token).ConfigureAwait(false);
169169

170170
result = WriteLength(context.Encoding.GetByteCount(chars.Span), lengthFormat.GetValueOrDefault());
@@ -256,7 +256,7 @@ private bool TryFormat<T>(T value, LengthFormat? lengthFormat, ReadOnlySpan<char
256256
{
257257
null => 0,
258258
LengthFormat.BigEndian or LengthFormat.LittleEndian => sizeof(int),
259-
LengthFormat.Compressed => Leb128<int>.MaxSizeInBytes,
259+
LengthFormat.Compressed => Leb128<uint>.MaxSizeInBytes,
260260
_ => throw new ArgumentOutOfRangeException(nameof(lengthFormat)),
261261
};
262262

@@ -289,7 +289,7 @@ private async ValueTask<int> FormatSlowAsync<T>(T value, LengthFormat? lengthFor
289289
if (!TryFormat(value, lengthFormat, format, provider, out var bytesWritten))
290290
{
291291
const int maxBufferSize = int.MaxValue / 2;
292-
for (var bufferSize = MaxBufferSize + Leb128<int>.MaxSizeInBytes; ; bufferSize = bufferSize <= maxBufferSize ? bufferSize << 1 : throw new InsufficientMemoryException())
292+
for (var bufferSize = MaxBufferSize + Leb128<uint>.MaxSizeInBytes; ; bufferSize = bufferSize <= maxBufferSize ? bufferSize << 1 : throw new InsufficientMemoryException())
293293
{
294294
using var buffer = allocator.AllocateAtLeast(bufferSize);
295295
if (value.TryFormat(buffer.Span, out bytesWritten, format, provider))

src/DotNext.IO/IO/IAsyncBinaryReader.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ private async ValueTask<TResult> ReadAsync<TResult, TReader>(TReader reader, Can
9999
{
100100
LengthFormat.LittleEndian => ReadLittleEndianAsync<int>(token),
101101
LengthFormat.BigEndian => ReadBigEndianAsync<int>(token),
102-
LengthFormat.Compressed => ReadAsync<int, Leb128Reader<int>>(new(), token),
102+
LengthFormat.Compressed => ReadAsync<int, SevenBitEncodedIntReader>(new(), token),
103103
_ => ValueTask.FromException<int>(new ArgumentOutOfRangeException(nameof(lengthFormat))),
104104
};
105105

src/DotNext.IO/IO/Pipelines/PipeExtensions.Readers.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,7 @@ public static ValueTask<T> ReadBigEndianAsync<T>(this PipeReader reader, Cancell
154154
{
155155
LengthFormat.LittleEndian => reader.ReadLittleEndianAsync<int>(token),
156156
LengthFormat.BigEndian => reader.ReadBigEndianAsync<int>(token),
157-
LengthFormat.Compressed => ReadAsync<int, Leb128Reader<int>>(reader, new(), token),
157+
LengthFormat.Compressed => ReadAsync<int, SevenBitEncodedIntReader>(reader, new(), token),
158158
_ => ValueTask.FromException<int>(new ArgumentOutOfRangeException(nameof(lengthFormat))),
159159
};
160160

src/DotNext.IO/IO/SequenceReader.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -271,8 +271,8 @@ public MemoryOwner<byte> ReadBlock(LengthFormat lengthFormat, MemoryAllocator<by
271271

272272
private int Read7BitEncodedInt32()
273273
{
274-
var parser = new Leb128Reader<int>();
275-
return Read<int, Leb128Reader<int>>(ref parser);
274+
var parser = new SevenBitEncodedIntReader();
275+
return Read<int, SevenBitEncodedIntReader>(ref parser);
276276
}
277277

278278
private int ReadLength(LengthFormat lengthFormat) => lengthFormat switch

src/DotNext.IO/IO/StreamExtensions.Readers.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ private static unsafe ValueTask<int> ReadLengthAsync(this Stream stream, LengthF
118118
return reader(stream, buffer, token);
119119

120120
static ValueTask<int> Read7BitEncodedIntAsync(Stream stream, Memory<byte> buffer, CancellationToken token)
121-
=> ReadAsync<int, Leb128Reader<int>>(stream, new(), buffer, token);
121+
=> ReadAsync<int, SevenBitEncodedIntReader>(stream, new(), buffer, token);
122122
}
123123

124124
/// <summary>
@@ -136,7 +136,7 @@ public static async ValueTask<MemoryOwner<byte>> ReadBlockAsync(this Stream stre
136136
{
137137
MemoryOwner<byte> result;
138138
int length;
139-
using (result = allocator.AllocateExactly(Leb128<int>.MaxSizeInBytes))
139+
using (result = allocator.AllocateExactly(Leb128<uint>.MaxSizeInBytes))
140140
{
141141
length = await stream.ReadLengthAsync(lengthFormat, result.Memory, token).ConfigureAwait(false);
142142
}

src/DotNext.IO/IO/StreamExtensions.Writers.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -191,7 +191,7 @@ public static async ValueTask<int> FormatAsync<T>(this Stream stream, T value, L
191191
Memory<byte> bufferForLength;
192192
if (lengthFormat.HasValue)
193193
{
194-
bufferForLength = buffer.Slice(0, Leb128<int>.MaxSizeInBytes);
194+
bufferForLength = buffer.Slice(0, Leb128<uint>.MaxSizeInBytes);
195195
buffer = buffer.Slice(bufferForLength.Length);
196196
}
197197
else

0 commit comments

Comments
 (0)