Skip to content

Commit ba4311b

Browse files
committed
Added ArrayPoolBufferWriter<T> type
Modified port from the MVVM Toolkit type
1 parent 9b6e37a commit ba4311b

File tree

1 file changed

+129
-0
lines changed

1 file changed

+129
-0
lines changed
Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
// See the LICENSE file in the project root for more information.
4+
5+
using System;
6+
using System.Buffers;
7+
using System.Diagnostics.Contracts;
8+
using System.Runtime.CompilerServices;
9+
10+
namespace Microsoft.Toolkit.Uwp.UI.Helpers.Internals
11+
{
12+
/// <summary>
13+
/// A simple buffer writer implementation using pooled arrays.
14+
/// </summary>
15+
/// <typeparam name="T">The type of items to store in the list.</typeparam>
16+
/// <remarks>
17+
/// This type is a <see langword="ref"/> <see langword="struct"/> to avoid the object allocation and to
18+
/// enable the pattern-based <see cref="IDisposable"/> support. We aren't worried with consumers not
19+
/// using this type correctly since it's private and only accessible within the parent type.
20+
/// </remarks>
21+
internal ref struct ArrayPoolBufferWriter<T>
22+
{
23+
/// <summary>
24+
/// The default buffer size to use to expand empty arrays.
25+
/// </summary>
26+
private const int DefaultInitialBufferSize = 128;
27+
28+
/// <summary>
29+
/// The underlying <typeparamref name="T"/> array.
30+
/// </summary>
31+
private T[] array;
32+
33+
/// <summary>
34+
/// The starting offset within <see cref="array"/>.
35+
/// </summary>
36+
private int index;
37+
38+
/// <summary>
39+
/// Creates a new instance of the <see cref="ArrayPoolBufferWriter{T}"/> struct.
40+
/// </summary>
41+
/// <returns>A new <see cref="ArrayPoolBufferWriter{T}"/> instance.</returns>
42+
[Pure]
43+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
44+
public static ArrayPoolBufferWriter<T> Create()
45+
{
46+
return new() { array = ArrayPool<T>.Shared.Rent(DefaultInitialBufferSize) };
47+
}
48+
49+
/// <summary>
50+
/// Gets the total number of items stored in the current instance.
51+
/// </summary>
52+
public int Count
53+
{
54+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
55+
get => this.array.Length;
56+
}
57+
58+
/// <summary>
59+
/// Gets the item at the specified offset into the current buffer in use.
60+
/// </summary>
61+
/// <param name="index">The index of the element to retrieve.</param>
62+
/// <returns>The item at the specified offset into the current buffer in use.</returns>
63+
/// <exception cref="ArgumentOutOfRangeException">Thrown when <paramref name="index"/> is out of range.</exception>
64+
public T this[int index]
65+
{
66+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
67+
get
68+
{
69+
if ((uint)index >= this.index)
70+
{
71+
static void Throw() => throw new ArgumentOutOfRangeException(nameof(index));
72+
73+
Throw();
74+
}
75+
76+
return this.array[index];
77+
}
78+
}
79+
80+
/// <summary>
81+
/// Adds a new item to the current collection.
82+
/// </summary>
83+
/// <param name="item">The item to add.</param>
84+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
85+
public void Add(T item)
86+
{
87+
if (this.index == this.array.Length)
88+
{
89+
ResizeBuffer();
90+
}
91+
92+
this.array[this.index++] = item;
93+
}
94+
95+
/// <summary>
96+
/// Resets the underlying array and the stored items.
97+
/// </summary>
98+
public void Reset()
99+
{
100+
Array.Clear(this.array, 0, this.index);
101+
102+
this.index = 0;
103+
}
104+
105+
/// <summary>
106+
/// Resizes <see cref="array"/> when there is no space left for new items.
107+
/// </summary>
108+
[MethodImpl(MethodImplOptions.NoInlining)]
109+
private void ResizeBuffer()
110+
{
111+
T[] rent = ArrayPool<T>.Shared.Rent(this.index << 2);
112+
113+
Array.Copy(this.array, 0, rent, 0, this.index);
114+
Array.Clear(this.array, 0, this.index);
115+
116+
ArrayPool<T>.Shared.Return(this.array);
117+
118+
this.array = rent;
119+
}
120+
121+
/// <inheritdoc cref="IDisposable.Dispose"/>
122+
public void Dispose()
123+
{
124+
Array.Clear(this.array, 0, this.index);
125+
126+
ArrayPool<T>.Shared.Return(this.array);
127+
}
128+
}
129+
}

0 commit comments

Comments
 (0)