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