-
Notifications
You must be signed in to change notification settings - Fork 9.9k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Use MessagePackReader \ MessagePackWriter to implement IHubProtocol f…
…or server-side Blazor (#8687) * Use MessagePackReader \ MessagePackWriter to implement IHubProtocol for server-side Blazor Fixes #7311
- Loading branch information
Showing
16 changed files
with
1,440 additions
and
657 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,7 @@ | ||
[submodule "googletest"] | ||
path = src/submodules/googletest | ||
url = https://github.com/google/googletest | ||
|
||
[submodule "src/submodules/MessagePack-CSharp"] | ||
path = src/submodules/MessagePack-CSharp | ||
url = https://github.com/aspnet/MessagePack-CSharp.git |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
193 changes: 193 additions & 0 deletions
193
src/Components/Server/src/BlazorPack/ArrayBufferWriter.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,193 @@ | ||
// Copyright (c) .NET Foundation. All rights reserved. | ||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. | ||
|
||
// Copied from https://github.com/dotnet/corefx/blob/b0751dcd4a419ba6731dcaa7d240a8a1946c934c/src/System.Text.Json/src/System/Text/Json/Serialization/ArrayBufferWriter.cs | ||
|
||
using System; | ||
using System.Buffers; | ||
using System.Diagnostics; | ||
|
||
namespace Microsoft.AspNetCore.Components.Server.BlazorPack | ||
{ | ||
// Note: this is currently an internal class that will be replaced with a shared version. | ||
internal sealed class ArrayBufferWriter<T> : IBufferWriter<T>, IDisposable | ||
{ | ||
private T[] _rentedBuffer; | ||
private int _index; | ||
|
||
private const int MinimumBufferSize = 256; | ||
|
||
public ArrayBufferWriter() | ||
{ | ||
_rentedBuffer = ArrayPool<T>.Shared.Rent(MinimumBufferSize); | ||
_index = 0; | ||
} | ||
|
||
public ArrayBufferWriter(int initialCapacity) | ||
{ | ||
if (initialCapacity <= 0) | ||
{ | ||
throw new ArgumentException(nameof(initialCapacity)); | ||
} | ||
|
||
_rentedBuffer = ArrayPool<T>.Shared.Rent(initialCapacity); | ||
_index = 0; | ||
} | ||
|
||
public ReadOnlyMemory<T> WrittenMemory | ||
{ | ||
get | ||
{ | ||
CheckIfDisposed(); | ||
|
||
return _rentedBuffer.AsMemory(0, _index); | ||
} | ||
} | ||
|
||
public int WrittenCount | ||
{ | ||
get | ||
{ | ||
CheckIfDisposed(); | ||
|
||
return _index; | ||
} | ||
} | ||
|
||
public int Capacity | ||
{ | ||
get | ||
{ | ||
CheckIfDisposed(); | ||
|
||
return _rentedBuffer.Length; | ||
} | ||
} | ||
|
||
public int FreeCapacity | ||
{ | ||
get | ||
{ | ||
CheckIfDisposed(); | ||
|
||
return _rentedBuffer.Length - _index; | ||
} | ||
} | ||
|
||
public void Clear() | ||
{ | ||
CheckIfDisposed(); | ||
|
||
ClearHelper(); | ||
} | ||
|
||
private void ClearHelper() | ||
{ | ||
Debug.Assert(_rentedBuffer != null); | ||
|
||
_rentedBuffer.AsSpan(0, _index).Clear(); | ||
_index = 0; | ||
} | ||
|
||
// Returns the rented buffer back to the pool | ||
public void Dispose() | ||
{ | ||
if (_rentedBuffer == null) | ||
{ | ||
return; | ||
} | ||
|
||
ClearHelper(); | ||
ArrayPool<T>.Shared.Return(_rentedBuffer); | ||
_rentedBuffer = null; | ||
} | ||
|
||
private void CheckIfDisposed() | ||
{ | ||
if (_rentedBuffer == null) | ||
{ | ||
ThrowObjectDisposedException(); | ||
} | ||
} | ||
|
||
private static void ThrowObjectDisposedException() | ||
{ | ||
throw new ObjectDisposedException(nameof(ArrayBufferWriter<T>)); | ||
} | ||
|
||
public void Advance(int count) | ||
{ | ||
CheckIfDisposed(); | ||
|
||
if (count < 0) | ||
throw new ArgumentException(nameof(count)); | ||
|
||
if (_index > _rentedBuffer.Length - count) | ||
{ | ||
ThrowInvalidOperationException(_rentedBuffer.Length); | ||
} | ||
|
||
_index += count; | ||
} | ||
|
||
public Memory<T> GetMemory(int sizeHint = 0) | ||
{ | ||
CheckIfDisposed(); | ||
|
||
CheckAndResizeBuffer(sizeHint); | ||
return _rentedBuffer.AsMemory(_index); | ||
} | ||
|
||
public Span<T> GetSpan(int sizeHint = 0) | ||
{ | ||
CheckIfDisposed(); | ||
|
||
CheckAndResizeBuffer(sizeHint); | ||
return _rentedBuffer.AsSpan(_index); | ||
} | ||
|
||
private void CheckAndResizeBuffer(int sizeHint) | ||
{ | ||
Debug.Assert(_rentedBuffer != null); | ||
|
||
if (sizeHint < 0) | ||
{ | ||
throw new ArgumentException(nameof(sizeHint)); | ||
} | ||
|
||
if (sizeHint == 0) | ||
{ | ||
sizeHint = MinimumBufferSize; | ||
} | ||
|
||
var availableSpace = _rentedBuffer.Length - _index; | ||
|
||
if (sizeHint > availableSpace) | ||
{ | ||
var growBy = Math.Max(sizeHint, _rentedBuffer.Length); | ||
|
||
var newSize = checked(_rentedBuffer.Length + growBy); | ||
|
||
var oldBuffer = _rentedBuffer; | ||
|
||
_rentedBuffer = ArrayPool<T>.Shared.Rent(newSize); | ||
|
||
Debug.Assert(oldBuffer.Length >= _index); | ||
Debug.Assert(_rentedBuffer.Length >= _index); | ||
|
||
var previousBuffer = oldBuffer.AsSpan(0, _index); | ||
previousBuffer.CopyTo(_rentedBuffer); | ||
previousBuffer.Clear(); | ||
ArrayPool<T>.Shared.Return(oldBuffer); | ||
} | ||
|
||
Debug.Assert(_rentedBuffer.Length - _index > 0); | ||
Debug.Assert(_rentedBuffer.Length - _index >= sizeHint); | ||
} | ||
|
||
private static void ThrowInvalidOperationException(int capacity) | ||
{ | ||
throw new InvalidOperationException($"Cannot advance past the end of the buffer, which has a size of {capacity}."); | ||
} | ||
} | ||
} |
Oops, something went wrong.