A game about forced loneliness, made by TACStudios
1<#/*THIS IS A T4 FILE - see t4_text_templating.md for what it is and how to run codegen*/#>
2<#@ template debug="True" #>
3<#@ output extension=".gen.cs" encoding="utf-8" #>
4<#@ assembly name="System.Core" #>
5<#@ import namespace="System.Globalization" #>
6<#@ import namespace="System.Security.Cryptography" #>
7
8//------------------------------------------------------------------------------
9// <auto-generated>
10// This code was generated by a tool.
11//
12// TextTransform Samples/Packages/com.unity.collections/Unity.Collections/FixedList.tt
13//
14// Changes to this file may cause incorrect behavior and will be lost if
15// the code is regenerated.
16// </auto-generated>
17//------------------------------------------------------------------------------
18
19using System.Collections.Generic;
20using System.Collections;
21using System.Diagnostics;
22using System.Runtime.CompilerServices;
23using System.Runtime.InteropServices;
24using System;
25using Unity.Collections.LowLevel.Unsafe;
26using Unity.Mathematics;
27using UnityEngine.Internal;
28using UnityEngine;
29using Unity.Properties;
30
31namespace Unity.Collections
32{
33 [GenerateTestsForBurstCompatibility(GenericTypeArguments = new [] { typeof(int), typeof(FixedBytes32Align8) })]
34 [Serializable]
35 internal struct FixedList<T,U>
36 : INativeList<T>
37 where T : unmanaged
38 where U : unmanaged
39 {
40 [SerializeField] internal U data;
41
42 internal ushort length
43 {
44 [MethodImpl(MethodImplOptions.AggressiveInlining)]
45 readonly get
46 {
47 unsafe
48 {
49 fixed(void* ptr = &data)
50 return *((ushort*)ptr);
51 }
52 }
53
54 [MethodImpl(MethodImplOptions.AggressiveInlining)]
55 set
56 {
57 unsafe
58 {
59 fixed (void* ptr = &data)
60 *((ushort*)ptr) = value;
61 }
62 }
63 }
64
65 internal readonly unsafe byte* buffer
66 {
67 [MethodImpl(MethodImplOptions.AggressiveInlining)]
68 get
69 {
70 unsafe
71 {
72 fixed (void* ptr = &data)
73 return ((byte*)ptr) + UnsafeUtility.SizeOf<ushort>();
74 }
75 }
76 }
77
78 /// <summary>
79 /// The current number of items in this list.
80 /// </summary>
81 /// <value>The current number of items in this list.</value>
82 [CreateProperty]
83 public int Length
84 {
85 [MethodImpl(MethodImplOptions.AggressiveInlining)]
86 readonly get => length;
87
88 set
89 {
90 FixedList.CheckResize<U,T>(value);
91 length = (ushort)value;
92 }
93 }
94
95 /// <summary>
96 /// A property in order to display items in the Entity Inspector.
97 /// </summary>
98 [CreateProperty] IEnumerable<T> Elements => this.ToArray();
99
100 /// <summary>
101 /// Whether the list is empty.
102 /// </summary>
103 /// <value>True if this string has no characters or if the container has not been constructed.</value>
104 public readonly bool IsEmpty
105 {
106 [MethodImpl(MethodImplOptions.AggressiveInlining)]
107 get => Length == 0;
108 }
109
110 internal readonly int LengthInBytes => Length * UnsafeUtility.SizeOf<T>();
111
112 internal readonly unsafe byte* Buffer
113 {
114 [MethodImpl(MethodImplOptions.AggressiveInlining)]
115 get
116 {
117 return buffer + FixedList.PaddingBytes<T>();
118 }
119 }
120
121 /// <summary>
122 /// The number of elements that can fit in this list.
123 /// </summary>
124 /// <value>The number of elements that can fit in this list.</value>
125 /// <remarks>The capacity of a FixedList cannot be changed. The setter is included only for conformity with <see cref="INativeList{T}"/>.</remarks>
126 /// <exception cref="ArgumentOutOfRangeException">Thrown if the new value does not match the current capacity.</exception>
127 public int Capacity
128 {
129 [MethodImpl(MethodImplOptions.AggressiveInlining)]
130 readonly get
131 {
132 return FixedList.Capacity<U,T>();
133 }
134
135 set
136 {
137 CollectionHelper.CheckCapacityInRange(value, Length);
138 }
139 }
140
141 /// <summary>
142 /// The element at a given index.
143 /// </summary>
144 /// <param name="index">An index.</param>
145 /// <value>The value to store at the index.</value>
146 /// <exception cref="IndexOutOfRangeException">Thrown if the index is out of bounds.</exception>
147 public T this[int index]
148 {
149 [MethodImpl(MethodImplOptions.AggressiveInlining)]
150 readonly get
151 {
152 CollectionHelper.CheckIndexInRange(index, length);
153 unsafe
154 {
155 return UnsafeUtility.ReadArrayElement<T>(Buffer, CollectionHelper.AssumePositive(index));
156 }
157 }
158
159 [MethodImpl(MethodImplOptions.AggressiveInlining)]
160 set
161 {
162 CollectionHelper.CheckIndexInRange(index, length);
163 unsafe
164 {
165 UnsafeUtility.WriteArrayElement<T>(Buffer, CollectionHelper.AssumePositive(index), value);
166 }
167 }
168 }
169
170 /// <summary>
171 /// Returns the element at a given index.
172 /// </summary>
173 /// <param name="index">An index.</param>
174 /// <returns>A reference to the element at the index.</returns>
175 [MethodImpl(MethodImplOptions.AggressiveInlining)]
176 public ref T ElementAt(int index)
177 {
178 CollectionHelper.CheckIndexInRange(index, length);
179 unsafe
180 {
181 return ref UnsafeUtility.ArrayElementAsRef<T>(Buffer, index);
182 }
183 }
184
185 /// <summary>
186 /// Returns the hash code of this list.
187 /// </summary>
188 /// <remarks>
189 /// Only the content of the list (the bytes of the elements) are included in the hash. Any bytes beyond the length are not part of the hash.</remarks>
190 /// <returns>The hash code of this list.</returns>
191 public override int GetHashCode()
192 {
193 unsafe
194 {
195 return (int)CollectionHelper.Hash(Buffer, LengthInBytes);
196 }
197 }
198
199 /// <summary>
200 /// Appends an element to the end of this list. Increments the length by 1.
201 /// </summary>
202 /// <remarks>
203 /// The same as <see cref="AddNoResize"/>. Included only for consistency with the other list types.
204 /// If the element exceeds the capacity, throws cref="IndexOutOfRangeException", and the list is unchanged.
205 /// </remarks>
206 /// <param name="item">The element to append at the end of the list.</param>
207 /// <exception cref="IndexOutOfRangeException">Thrown if the append exceeds the capacity.</exception>
208 public void Add(in T item) => AddNoResize(in item);
209
210 /// <summary>
211 /// Appends elements from a buffer to the end of this list. Increments the length by the number of appended elements.
212 /// </summary>
213 /// <remarks>
214 /// The same as <see cref="AddRangeNoResize"/>. Included only for consistency with the other list types.
215 /// If the elements exceeds the capacity, throws cref="IndexOutOfRangeException", and the list is unchanged.
216 /// </remarks>
217 /// <param name="ptr">A buffer.</param>
218 /// <param name="length">The number of elements from the buffer to append.</param>
219 /// <exception cref="IndexOutOfRangeException">Thrown if the append exceeds the capacity.</exception>
220 public unsafe void AddRange(void* ptr, int length) => AddRangeNoResize(ptr, length);
221
222 /// <summary>
223 /// Appends an element to the end of this list. Increments the length by 1.
224 /// </summary>
225 /// <remarks>
226 /// If the element exceeds the capacity, throws cref="IndexOutOfRangeException", and the list is unchanged.
227 /// </remarks>
228 /// <param name="item">The element to append at the end of the list.</param>
229 /// <exception cref="IndexOutOfRangeException">Thrown if the append exceeds the capacity.</exception>
230 [MethodImpl(MethodImplOptions.AggressiveInlining)]
231 public void AddNoResize(in T item)
232 {
233 this[Length++] = item;
234 }
235
236 /// <summary>
237 /// Appends elements from a buffer to the end of this list. Increments the length by the number of appended elements.
238 /// </summary>
239 /// <remarks>
240 /// If the elements exceeds the capacity, throws cref="IndexOutOfRangeException", and the list is unchanged.
241 /// </remarks>
242 /// <param name="ptr">A buffer.</param>
243 /// <param name="length">The number of elements from the buffer to append.</param>
244 /// <exception cref="IndexOutOfRangeException">Thrown if the append exceeds the capacity.</exception>
245 public unsafe void AddRangeNoResize(void* ptr, int length)
246 {
247 var idx = Length;
248 Length += length;
249 UnsafeUtility.MemCpy((T*)Buffer + idx, ptr, UnsafeUtility.SizeOf<T>() * length);
250 }
251
252 /// <summary>
253 /// Appends value count times to the end of this list.
254 /// </summary>
255 /// <remarks>
256 /// If the elements exceeds the capacity, throws cref="IndexOutOfRangeException", and the list is unchanged.
257 /// </remarks>
258 /// <param name="value">The value to add to the end of this list.</param>
259 /// <param name="count">The number of times to replicate the value.</param>
260 /// <exception cref="IndexOutOfRangeException">Thrown if the append exceeds the capacity.</exception>
261 public unsafe void AddReplicate(in T value, int count)
262 {
263 var idx = Length;
264 Length += count;
265 fixed (T* ptr = &value)
266 UnsafeUtility.MemCpyReplicate((T*)Buffer + idx, ptr, UnsafeUtility.SizeOf<T>(), count);
267 }
268
269 /// <summary>
270 /// Sets the length to 0.
271 /// </summary>
272 /// <remarks> Does *not* zero out the bytes.</remarks>
273 public void Clear()
274 {
275 Length = 0;
276 }
277
278 /// <summary>
279 /// Shifts elements toward the end of this list, increasing its length.
280 /// </summary>
281 /// <remarks>
282 /// Right-shifts elements in the list so as to create 'free' slots at the beginning or in the middle.
283 ///
284 /// The length is increased by `end - begin`.
285 ///
286 /// If `end` equals `begin`, the method does nothing.
287 ///
288 /// The element at index `begin` will be copied to index `end`, the element at index `begin + 1` will be copied to `end + 1`, and so forth.
289 ///
290 /// The indexes `begin` up to `end` are not cleared: they will contain whatever values they held prior.
291 /// </remarks>
292 /// <param name="begin">The index of the first element that will be shifted up.</param>
293 /// <param name="end">The index where the first shifted element will end up.</param>
294 /// <exception cref="IndexOutOfRangeException">Thrown if the new length exceeds the capacity.</exception>
295 public void InsertRangeWithBeginEnd(int begin, int end)
296 {
297 int items = end - begin;
298 if(items < 1)
299 return;
300 int itemsToCopy = length - begin;
301 Length += items;
302 if(itemsToCopy < 1)
303 return;
304 int bytesToCopy = itemsToCopy * UnsafeUtility.SizeOf<T>();
305 unsafe
306 {
307 byte *b = Buffer;
308 byte *dest = b + end * UnsafeUtility.SizeOf<T>();
309 byte *src = b + begin * UnsafeUtility.SizeOf<T>();
310 UnsafeUtility.MemMove(dest, src, bytesToCopy);
311 }
312 }
313
314 /// <summary>
315 /// Shifts elements toward the end of this list, increasing its length.
316 /// </summary>
317 /// <remarks>
318 /// Right-shifts elements in the list so as to create 'free' slots at the beginning or in the middle.
319 ///
320 /// The length is increased by `count`. If necessary, the capacity will be increased accordingly.
321 ///
322 /// If `count` equals `0`, the method does nothing.
323 ///
324 /// The element at index `index` will be copied to index `index + count`, the element at index `index + 1` will be copied to `index + count + 1`, and so forth.
325 ///
326 /// The indexes `index` up to `index + count` are not cleared: they will contain whatever values they held prior.
327 /// </remarks>
328 /// <param name="index">The index of the first element that will be shifted up.</param>
329 /// <param name="count">The number of elements to insert.</param>
330 /// <exception cref="ArgumentException">Thrown if `count` is negative.</exception>
331 /// <exception cref="ArgumentOutOfRangeException">Thrown if `index` is out of bounds.</exception>
332 public void InsertRange(int index, int count) => InsertRangeWithBeginEnd(index, index + count);
333
334 /// <summary>
335 /// Inserts a single element at an index. Increments the length by 1.
336 /// </summary>
337 /// <param name="index">The index at which to insert the element.</param>
338 /// <param name="item">The element to insert.</param>
339 /// <exception cref="ArgumentOutOfRangeException">Thrown if the index is out of bounds.</exception>
340 public void Insert(int index, in T item)
341 {
342 InsertRangeWithBeginEnd(index, index+1);
343 this[index] = item;
344 }
345
346 /// <summary>
347 /// Copies the last element of this list to an index. Decrements the length by 1.
348 /// </summary>
349 /// <remarks>Useful as a cheap way to remove elements from a list when you don't care about preserving order.</remarks>
350 /// <param name="index">The index to overwrite with the last element.</param>
351 /// <exception cref="ArgumentOutOfRangeException">Thrown if the index is out of bounds.</exception>
352 public void RemoveAtSwapBack(int index)
353 {
354 RemoveRangeSwapBack(index, 1);
355 }
356
357 /// <summary>
358 /// Copies the last *N* elements of this list to a range in this list. Decrements the length by *N*.
359 /// </summary>
360 /// <remarks>
361 /// Copies the last `count`-numbered elements to the range starting at `index`.
362 ///
363 /// Useful as a cheap way to remove elements from a list when you don't care about preserving order.
364 ///
365 /// Does nothing if the count is less than 1.
366 /// </remarks>
367 /// <param name="index">The first index of the destination range.</param>
368 /// <param name="count">The number of elements to copy and the amount by which to decrement the length.</param>
369 /// <exception cref="ArgumentOutOfRangeException">Thrown if the index is out of bounds.</exception>
370 public void RemoveRangeSwapBack(int index, int count)
371 {
372 if (count > 0)
373 {
374 int copyFrom = math.max(Length - count, index + count);
375
376 unsafe
377 {
378 var sizeOf = UnsafeUtility.SizeOf<T>();
379 void* dst = Buffer + index * sizeOf;
380 void* src = Buffer + copyFrom * sizeOf;
381 UnsafeUtility.MemCpy(dst, src, (Length - copyFrom) * sizeOf);
382 }
383
384 Length -= count;
385 }
386 }
387
388 /// <summary>
389 /// Removes the element at an index. Shifts everything above the index down by one and decrements the length by 1.
390 /// </summary>
391 /// <param name="index">The index of the element to remove.</param>
392 /// <remarks>
393 /// If you don't care about preserving the order of the elements, `RemoveAtSwapBack` is a more efficient way to remove an element.
394 /// </remarks>
395 /// <exception cref="ArgumentOutOfRangeException">Thrown if the index is out of bounds.</exception>
396 public void RemoveAt(int index)
397 {
398 RemoveRange(index, 1);
399 }
400
401 /// <summary>
402 /// Removes *N* elements of a range. Shifts everything above the range down by *N* and decrements the length by *N*.
403 /// </summary>
404 /// <remarks>
405 /// If you don't care about preserving the order of the elements, `RemoveAtSwapBack` is a more efficient way to remove elements.
406 /// </remarks>
407 /// <param name="index">The first index of the range to remove.</param>
408 /// <param name="count">The number of elements to remove.</param>
409 /// <exception cref="ArgumentOutOfRangeException">Thrown if the index is out of bounds.</exception>
410 public void RemoveRange(int index, int count)
411 {
412 if (count > 0)
413 {
414 int copyFrom = math.min(index + count, Length);
415
416 unsafe
417 {
418 var sizeOf = UnsafeUtility.SizeOf<T>();
419 void* dst = Buffer + index * sizeOf;
420 void* src = Buffer + copyFrom * sizeOf;
421 UnsafeUtility.MemCpy(dst, src, (Length - copyFrom) * sizeOf);
422 }
423
424 Length -= count;
425 }
426 }
427
428 /// <summary>
429 /// Returns a managed array that is a copy of this list.
430 /// </summary>
431 /// <returns>A managed array that is a copy of this list.</returns>
432 [ExcludeFromBurstCompatTesting("Returns managed array")]
433 public T[] ToArray()
434 {
435 var result = new T[Length];
436 unsafe
437 {
438 byte* s = Buffer;
439 fixed(T* d = result)
440 UnsafeUtility.MemCpy(d, s, LengthInBytes);
441 }
442 return result;
443 }
444
445 /// <summary>
446 /// Returns an array that is a copy of this list.
447 /// </summary>
448 /// <param name="allocator">The allocator to use.</param>
449 /// <returns>An array that is a copy of this list.</returns>
450 public NativeArray<T> ToNativeArray(AllocatorManager.AllocatorHandle allocator)
451 {
452 unsafe
453 {
454 var copy = CollectionHelper.CreateNativeArray<T>(Length, allocator, NativeArrayOptions.UninitializedMemory);
455 UnsafeUtility.MemCpy(copy.GetUnsafePtr(), Buffer, LengthInBytes);
456 return copy;
457 }
458 }
459 }
460
461 [GenerateTestsForBurstCompatibility]
462 struct FixedList
463 {
464 [GenerateTestsForBurstCompatibility(GenericTypeArguments = new [] { typeof(int) })]
465 [MethodImpl(MethodImplOptions.AggressiveInlining)]
466 internal static int PaddingBytes<T>() where T : unmanaged
467 {
468 return math.max(0, math.min(6, (1 << math.tzcnt(UnsafeUtility.SizeOf<T>())) - 2));
469 }
470
471 [GenerateTestsForBurstCompatibility(GenericTypeArguments = new [] { typeof(int), typeof(int) })]
472 [MethodImpl(MethodImplOptions.AggressiveInlining)]
473 internal static int StorageBytes<BUFFER,T>() where BUFFER : unmanaged where T : unmanaged
474 {
475 return UnsafeUtility.SizeOf<BUFFER>() - UnsafeUtility.SizeOf<ushort>() - PaddingBytes<T>();
476 }
477
478 [GenerateTestsForBurstCompatibility(GenericTypeArguments = new [] { typeof(int), typeof(int) })]
479 [MethodImpl(MethodImplOptions.AggressiveInlining)]
480 internal static int Capacity<BUFFER,T>() where BUFFER : unmanaged where T : unmanaged
481 {
482 return StorageBytes<BUFFER,T>() / UnsafeUtility.SizeOf<T>();
483 }
484
485 [GenerateTestsForBurstCompatibility(GenericTypeArguments = new [] { typeof(int), typeof(int) })]
486 [Conditional("ENABLE_UNITY_COLLECTIONS_CHECKS"), Conditional("UNITY_DOTS_DEBUG")]
487 internal static void CheckResize<BUFFER,T>(int newLength) where BUFFER : unmanaged where T : unmanaged
488 {
489 var Capacity = Capacity<BUFFER,T>();
490 if (newLength < 0 || newLength > Capacity)
491 throw new IndexOutOfRangeException($"NewLength {newLength} is out of range of '{Capacity}' Capacity.");
492 }
493 }
494
495<#
496var SIZES = new int[]{32,64,128,512,4096};
497for(var size = 0; size < 5; ++size)
498{
499 var BYTES = SIZES[size];
500 var BUFFER_BYTES = BYTES;
501 var TYPENAME = String.Format("FixedList{0}Bytes", BYTES);
502 var OLD_TYPENAME = String.Format("FixedList{0}", BYTES);
503
504#>
505 /// <summary>
506 /// An unmanaged, resizable list whose content is all stored directly in the <#=BYTES#>-byte struct. Useful for small lists.
507 /// </summary>
508 /// <typeparam name="T">The type of the elements.</typeparam>
509 [Serializable]
510 [DebuggerTypeProxy(typeof(<#=TYPENAME#>DebugView<>))]
511 [GenerateTestsForBurstCompatibility(GenericTypeArguments = new [] { typeof(int) })]
512 public struct <#=TYPENAME#><T>
513 : INativeList<T>
514 , IEnumerable<T> // Used by collection initializers.
515<#
516 foreach(var OTHERBYTES in SIZES)
517 {
518 var OTHERTYPENAME = String.Format("FixedList{0}Bytes", OTHERBYTES);
519 WriteLine(" , IEquatable<{0}<T>>", OTHERTYPENAME);
520 WriteLine(" , IComparable<{0}<T>>", OTHERTYPENAME);
521 }
522#> where T : unmanaged
523 {
524 [SerializeField] internal FixedBytes<#=BUFFER_BYTES#>Align8 data;
525
526 internal ushort length
527 {
528 [MethodImpl(MethodImplOptions.AggressiveInlining)]
529 readonly get
530 {
531 unsafe
532 {
533 fixed(void* ptr = &data)
534 return *((ushort*)ptr);
535 }
536 }
537
538 [MethodImpl(MethodImplOptions.AggressiveInlining)]
539 set
540 {
541 unsafe
542 {
543 fixed (void* ptr = &data)
544 *((ushort*)ptr) = value;
545 }
546 }
547 }
548
549 internal readonly unsafe byte* buffer
550 {
551 [MethodImpl(MethodImplOptions.AggressiveInlining)]
552 get
553 {
554 unsafe
555 {
556 fixed (void* ptr = &data)
557 return ((byte*)ptr) + UnsafeUtility.SizeOf<ushort>();
558 }
559 }
560 }
561
562 /// <summary>
563 /// The current number of items in this list.
564 /// </summary>
565 /// <value>The current number of items in this list.</value>
566 [CreateProperty]
567 public int Length
568 {
569 [MethodImpl(MethodImplOptions.AggressiveInlining)]
570 readonly get => length;
571 set
572 {
573 FixedList.CheckResize<FixedBytes<#=BUFFER_BYTES#>Align8,T>(value);
574 length = (ushort)value;
575 }
576 }
577
578 /// <summary>
579 /// A property in order to display items in the Entity Inspector.
580 /// </summary>
581 [CreateProperty] IEnumerable<T> Elements => this.ToArray();
582
583 /// <summary>
584 /// Whether this list is empty.
585 /// </summary>
586 /// <value>True if this string has no characters or if the container has not been constructed.</value>
587 public readonly bool IsEmpty
588 {
589 [MethodImpl(MethodImplOptions.AggressiveInlining)]
590 get => Length == 0;
591 }
592
593 internal int LengthInBytes => Length * UnsafeUtility.SizeOf<T>();
594
595 /// <summary>
596 /// Returns a pointer to the first element of the list buffer.
597 /// </summary>
598 /// <remarks>
599 /// The pointer returned by this method points into the internals of the target list object. It is the
600 /// caller's responsibility to ensure that the pointer is not used after the list is destroyed or goes
601 /// out of scope.
602 /// </remarks>
603 /// <returns>A pointer to the first element of the list buffer.</returns>
604 internal readonly unsafe byte* Buffer
605 {
606 [MethodImpl(MethodImplOptions.AggressiveInlining)]
607 get
608 {
609 return buffer + FixedList.PaddingBytes<T>();
610 }
611 }
612
613 /// <summary>
614 /// The number of elements that can fit in this list.
615 /// </summary>
616 /// <value>The number of elements that can fit in this list.</value>
617 /// <remarks>The capacity of a FixedList cannot be changed. The setter is included only for conformity with <see cref="INativeList{T}"/>.</remarks>
618 /// <exception cref="ArgumentOutOfRangeException">Thrown if the new value does not match the current capacity.</exception>
619 public int Capacity
620 {
621 [MethodImpl(MethodImplOptions.AggressiveInlining)]
622 readonly get
623 {
624 return FixedList.Capacity<FixedBytes<#=BUFFER_BYTES#>Align8,T>();
625 }
626
627 set
628 {
629 CollectionHelper.CheckCapacityInRange(value, Length);
630 }
631 }
632
633 /// <summary>
634 /// The element at a given index.
635 /// </summary>
636 /// <param name="index">An index.</param>
637 /// <value>The value to store at the index.</value>
638 /// <exception cref="IndexOutOfRangeException">Thrown if the index is out of bounds.</exception>
639 public T this[int index]
640 {
641 [MethodImpl(MethodImplOptions.AggressiveInlining)]
642 readonly get
643 {
644 CollectionHelper.CheckIndexInRange(index, length);
645 unsafe
646 {
647 return UnsafeUtility.ReadArrayElement<T>(Buffer, CollectionHelper.AssumePositive(index));
648 }
649 }
650
651 [MethodImpl(MethodImplOptions.AggressiveInlining)]
652 set
653 {
654 CollectionHelper.CheckIndexInRange(index, length);
655 unsafe
656 {
657 UnsafeUtility.WriteArrayElement<T>(Buffer, CollectionHelper.AssumePositive(index), value);
658 }
659 }
660 }
661
662 /// <summary>
663 /// Returns the element at a given index.
664 /// </summary>
665 /// <param name="index">An index.</param>
666 /// <returns>The list element at the index.</returns>
667 [MethodImpl(MethodImplOptions.AggressiveInlining)]
668 public ref T ElementAt(int index)
669 {
670 CollectionHelper.CheckIndexInRange(index, length);
671 unsafe
672 {
673 return ref UnsafeUtility.ArrayElementAsRef<T>(Buffer, index);
674 }
675 }
676
677 /// <summary>
678 /// Returns the hash code of this list.
679 /// </summary>
680 /// <remarks>
681 /// Only the content of the list (the bytes of the elements) are included in the hash. Any bytes beyond the length are not part of the hash.</remarks>
682 /// <returns>The hash code of this list.</returns>
683 public override int GetHashCode()
684 {
685 unsafe
686 {
687 return (int)CollectionHelper.Hash(Buffer, LengthInBytes);
688 }
689 }
690
691 /// <summary>
692 /// Appends an element to the end of this list. Increments the length by 1.
693 /// </summary>
694 /// <remarks>
695 /// The same as <see cref="AddNoResize"/>. Included only for consistency with the other list types.
696 /// If the element exceeds the capacity, throws cref="IndexOutOfRangeException", and the list is unchanged.
697 /// </remarks>
698 /// <param name="item">The element to append at the end of the list.</param>
699 /// <exception cref="IndexOutOfRangeException">Thrown if the append exceeds the capacity.</exception>
700 public void Add(in T item) => AddNoResize(in item);
701
702 /// <summary>
703 /// Appends elements from a buffer to the end of this list. Increments the length by the number of appended elements.
704 /// </summary>
705 /// <remarks>
706 /// The same as <see cref="AddRangeNoResize"/>. Included only for consistency with the other list types.
707 /// If the elements exceeds the capacity, throws cref="IndexOutOfRangeException", and the list is unchanged.
708 /// </remarks>
709 /// <param name="ptr">A buffer.</param>
710 /// <param name="length">The number of elements from the buffer to append.</param>
711 /// <exception cref="IndexOutOfRangeException">Thrown if the append exceeds the capacity.</exception>
712 public unsafe void AddRange(void* ptr, int length) => AddRangeNoResize(ptr, length);
713
714 /// <summary>
715 /// Appends an element to the end of this list. Increments the length by 1.
716 /// </summary>
717 /// <remarks>
718 /// If the element exceeds the capacity, throws cref="IndexOutOfRangeException", and the list is unchanged.
719 /// </remarks>
720 /// <param name="item">The element to append at the end of the list.</param>
721 /// <exception cref="IndexOutOfRangeException">Thrown if the append exceeds the capacity.</exception>
722 [MethodImpl(MethodImplOptions.AggressiveInlining)]
723 public void AddNoResize(in T item)
724 {
725 this[Length++] = item;
726 }
727
728 /// <summary>
729 /// Appends elements from a buffer to the end of this list. Increments the length by the number of appended elements.
730 /// </summary>
731 /// <remarks>
732 /// If the elements exceeds the capacity, throws cref="IndexOutOfRangeException", and the list is unchanged.
733 /// </remarks>
734 /// <param name="ptr">A buffer.</param>
735 /// <param name="length">The number of elements from the buffer to append.</param>
736 /// <exception cref="IndexOutOfRangeException">Thrown if the append exceeds the capacity.</exception>
737 public unsafe void AddRangeNoResize(void* ptr, int length)
738 {
739 var idx = Length;
740 Length += length;
741 UnsafeUtility.MemCpy((T*)Buffer + idx, ptr, UnsafeUtility.SizeOf<T>() * length);
742 }
743
744 /// <summary>
745 /// Appends value count times to the end of this list.
746 /// </summary>
747 /// <param name="value">The value to add to the end of this list.</param>
748 /// <param name="count">The number of times to replicate the value.</param>
749 /// <exception cref="IndexOutOfRangeException">Thrown if the append exceeds the capacity.</exception>
750 public unsafe void AddReplicate(in T value, int count)
751 {
752 var idx = Length;
753 Length += count;
754 fixed (T* ptr = &value)
755 UnsafeUtility.MemCpyReplicate((T*)Buffer + idx, ptr, UnsafeUtility.SizeOf<T>(), count);
756 }
757
758 /// <summary>
759 /// Sets the length to 0.
760 /// </summary>
761 /// <remarks> Does *not* zero out the bytes.</remarks>
762 public void Clear()
763 {
764 Length = 0;
765 }
766
767 /// <summary>
768 /// Shifts elements toward the end of this list, increasing its length.
769 /// </summary>
770 /// <remarks>
771 /// Right-shifts elements in the list so as to create 'free' slots at the beginning or in the middle.
772 ///
773 /// The length is increased by `end - begin`.
774 ///
775 /// If `end` equals `begin`, the method does nothing.
776 ///
777 /// The element at index `begin` will be copied to index `end`, the element at index `begin + 1` will be copied to `end + 1`, and so forth.
778 ///
779 /// The indexes `begin` up to `end` are not cleared: they will contain whatever values they held prior.
780 /// </remarks>
781 /// <param name="begin">The index of the first element that will be shifted up.</param>
782 /// <param name="end">The index where the first shifted element will end up.</param>
783 /// <exception cref="IndexOutOfRangeException">Thrown if the new length exceeds the capacity.</exception>
784 public void InsertRangeWithBeginEnd(int begin, int end)
785 {
786 int items = end - begin;
787 if(items < 1)
788 return;
789 int itemsToCopy = length - begin;
790 Length += items;
791 if(itemsToCopy < 1)
792 return;
793 int bytesToCopy = itemsToCopy * UnsafeUtility.SizeOf<T>();
794 unsafe
795 {
796 byte *b = Buffer;
797 byte *dest = b + end * UnsafeUtility.SizeOf<T>();
798 byte *src = b + begin * UnsafeUtility.SizeOf<T>();
799 UnsafeUtility.MemMove(dest, src, bytesToCopy);
800 }
801 }
802
803 /// <summary>
804 /// Shifts elements toward the end of this list, increasing its length.
805 /// </summary>
806 /// <remarks>
807 /// Right-shifts elements in the list so as to create 'free' slots at the beginning or in the middle.
808 ///
809 /// The length is increased by `count`. If necessary, the capacity will be increased accordingly.
810 ///
811 /// If `count` equals `0`, the method does nothing.
812 ///
813 /// The element at index `index` will be copied to index `index + count`, the element at index `index + 1` will be copied to `index + count + 1`, and so forth.
814 ///
815 /// The indexes `index` up to `index + count` are not cleared: they will contain whatever values they held prior.
816 /// </remarks>
817 /// <param name="index">The index of the first element that will be shifted up.</param>
818 /// <param name="count">The number of elements to insert.</param>
819 /// <exception cref="ArgumentException">Thrown if `count` is negative.</exception>
820 /// <exception cref="ArgumentOutOfRangeException">Thrown if `index` is out of bounds.</exception>
821 public void InsertRange(int index, int count) => InsertRangeWithBeginEnd(index, index + count);
822
823 /// <summary>
824 /// Inserts a single element at an index. Increments the length by 1.
825 /// </summary>
826 /// <param name="index">The index at which to insert the element.</param>
827 /// <param name="item">The element to insert.</param>
828 /// <exception cref="ArgumentOutOfRangeException">Thrown if the index is out of bounds.</exception>
829 public void Insert(int index, in T item)
830 {
831 InsertRangeWithBeginEnd(index, index+1);
832 this[index] = item;
833 }
834
835 /// <summary>
836 /// Copies the last element of this list to an index. Decrements the length by 1.
837 /// </summary>
838 /// <remarks>Useful as a cheap way to remove elements from a list when you don't care about preserving order.</remarks>
839 /// <param name="index">The index to overwrite with the last element.</param>
840 /// <exception cref="ArgumentOutOfRangeException">Thrown if the index is out of bounds.</exception>
841 public void RemoveAtSwapBack(int index)
842 {
843 RemoveRangeSwapBack(index, 1);
844 }
845
846 /// <summary>
847 /// Copies the last *N* elements of this list to a range in this list. Decrements the length by *N*.
848 /// </summary>
849 /// <remarks>
850 /// Copies the last `count`-numbered elements to the range starting at `index`.
851 ///
852 /// Useful as a cheap way to remove elements from a list when you don't care about preserving order.
853 ///
854 /// Does nothing if the count is less than 1.
855 /// </remarks>
856 /// <param name="index">The first index of the destination range.</param>
857 /// <param name="count">The number of elements to copy and the amount by which to decrement the length.</param>
858 /// <exception cref="ArgumentOutOfRangeException">Thrown if the index is out of bounds.</exception>
859 public void RemoveRangeSwapBack(int index, int count)
860 {
861 if (count > 0)
862 {
863 int copyFrom = math.max(Length - count, index + count);
864
865 unsafe
866 {
867 var sizeOf = UnsafeUtility.SizeOf<T>();
868 void* dst = Buffer + index * sizeOf;
869 void* src = Buffer + copyFrom * sizeOf;
870 UnsafeUtility.MemCpy(dst, src, (Length - copyFrom) * sizeOf);
871 }
872
873 Length -= count;
874 }
875 }
876
877 /// <summary>
878 /// Removes the element at an index. Shifts everything above the index down by one and decrements the length by 1.
879 /// </summary>
880 /// <param name="index">The index of the element to remove.</param>
881 /// <remarks>
882 /// If you don't care about preserving the order of the elements, `RemoveAtSwapBack` is a more efficient way to remove an element.
883 /// </remarks>
884 /// <exception cref="ArgumentOutOfRangeException">Thrown if the index is out of bounds.</exception>
885 public void RemoveAt(int index)
886 {
887 RemoveRange(index, 1);
888 }
889
890 /// <summary>
891 /// Removes *N* elements of a range. Shifts everything above the range down by *N* and decrements the length by *N*.
892 /// </summary>
893 /// <remarks>
894 /// If you don't care about preserving the order of the elements, `RemoveAtSwapBack` is a more efficient way to remove elements.
895 /// </remarks>
896 /// <param name="index">The first index of the range to remove.</param>
897 /// <param name="count">The number of elements to remove.</param>
898 /// <exception cref="ArgumentOutOfRangeException">Thrown if the index is out of bounds.</exception>
899 public void RemoveRange(int index, int count)
900 {
901 if (count > 0)
902 {
903 int copyFrom = math.min(index + count, Length);
904
905 unsafe
906 {
907 var sizeOf = UnsafeUtility.SizeOf<T>();
908 void* dst = Buffer + index * sizeOf;
909 void* src = Buffer + copyFrom * sizeOf;
910 UnsafeUtility.MemCpy(dst, src, (Length - copyFrom) * sizeOf);
911 }
912
913 Length -= count;
914 }
915 }
916
917 /// <summary>
918 /// Returns a managed array that is a copy of this list.
919 /// </summary>
920 /// <returns>A managed array that is a copy of this list.</returns>
921 [ExcludeFromBurstCompatTesting("Returns managed array")]
922 public T[] ToArray()
923 {
924 var result = new T[Length];
925 unsafe
926 {
927 byte* s = Buffer;
928 fixed(T* d = result)
929 UnsafeUtility.MemCpy(d, s, LengthInBytes);
930 }
931 return result;
932 }
933
934 /// <summary>
935 /// Returns an array that is a copy of this list.
936 /// </summary>
937 /// <param name="allocator">The allocator to use.</param>
938 /// <returns>An array that is a copy of this list.</returns>
939 public NativeArray<T> ToNativeArray(AllocatorManager.AllocatorHandle allocator)
940 {
941 unsafe
942 {
943 var copy = CollectionHelper.CreateNativeArray<T>(Length, allocator, NativeArrayOptions.UninitializedMemory);
944 UnsafeUtility.MemCpy(copy.GetUnsafePtr(), Buffer, LengthInBytes);
945 return copy;
946 }
947 }
948
949<#
950 foreach(var OTHERBYTES in SIZES)
951 {
952 var OTHER_BUFFER_BYTES = OTHERBYTES;
953 var OTHERTYPENAME = String.Format("FixedList{0}Bytes", OTHERBYTES);
954#>
955
956 /// <summary>
957 /// Returns true if two lists are equal.
958 /// </summary>
959 /// <remarks>Two lists are equal if their length and bytes are equal.</remarks>
960 /// <param name="a">The first list to compare for equality.</param>
961 /// <param name="b">The second list to compare for equality.</param>
962 /// <returns>True if the two lists are equal.</returns>
963 public static bool operator ==(in <#=TYPENAME#><T> a, in <#=OTHERTYPENAME#><T> b)
964 {
965 unsafe
966 {
967 if(a.length != b.length)
968 return false;
969 return UnsafeUtility.MemCmp(a.Buffer, b.Buffer, a.LengthInBytes) == 0;
970 }
971 }
972
973 /// <summary>
974 /// Returns true if two lists are unequal.
975 /// </summary>
976 /// <remarks>Two lists are equal if their length and bytes are equal.</remarks>
977 /// <param name="a">The first list to compare for inequality.</param>
978 /// <param name="b">The second list to compare for inequality.</param>
979 /// <returns>True if the two lists are unequal.</returns>
980 public static bool operator !=(in <#=TYPENAME#><T> a, in <#=OTHERTYPENAME#><T> b)
981 {
982 return !(a == b);
983 }
984
985 /// <summary>
986 /// Returns a number denoting whether this list should be placed before or after another list in a sort.
987 /// </summary>
988 /// <param name="other">A list to to compare with.</param>
989 /// <returns>An integer denoting the respective sort position of the list relative to the other:
990 ///
991 /// 0 denotes that both lists should have the same position in a sort.
992 /// -1 denotes that this list should precede the other list in a sort.
993 /// +1 denotes that this list should follow the other list in a sort.
994 /// </returns>
995 public int CompareTo(<#=OTHERTYPENAME#><T> other)
996 {
997 unsafe
998 {
999 byte* a = buffer;
1000 byte* b = other.buffer;
1001 var aa = a + FixedList.PaddingBytes<T>();
1002 var bb = b + FixedList.PaddingBytes<T>();
1003 var mini = math.min(Length, other.Length);
1004 for(var i = 0; i < mini; ++i)
1005 {
1006 var j = UnsafeUtility.MemCmp(aa + sizeof(T) * i, bb + sizeof(T) * i, sizeof(T));
1007 if(j != 0)
1008 return j;
1009 }
1010 return Length.CompareTo(other.Length);
1011 }
1012 }
1013
1014 /// <summary>
1015 /// Returns true if this list and another list are equal.
1016 /// </summary>
1017 /// <remarks>Two lists are equal if their length and bytes are equal.</remarks>
1018 /// <param name="other">The list to compare for equality.</param>
1019 /// <returns>True if the two lists are equal.</returns>
1020 public bool Equals(<#=OTHERTYPENAME#><T> other)
1021 {
1022 return CompareTo(other) == 0;
1023 }
1024
1025<#
1026 if(BYTES != OTHERBYTES)
1027 {
1028#>
1029
1030 /// <summary>
1031 /// Initializes and returns an instance of <#=TYPENAME#> with content copied from another list.
1032 /// </summary>
1033 /// <param name="other">The list to copy.</param>
1034 /// <exception cref="IndexOutOfRangeException">Throws if the other list's length exceeds the capacity of <#=TYPENAME#><T>.</exception>
1035 public <#=TYPENAME#>(in <#=OTHERTYPENAME#><T> other)
1036 {
1037 this = default;
1038 var error = Initialize(other);
1039 if(error != 0)
1040 FixedList.CheckResize<FixedBytes<#=BUFFER_BYTES#>Align8,T>(other.Length);
1041 }
1042
1043 /// <summary>
1044 /// Initializes an instance of <#=TYPENAME#> with content copied from another list.
1045 /// </summary>
1046 /// <param name="other">The list to copy.</param>
1047 /// <returns>zero on success, or non-zero on error.</returns>
1048 internal int Initialize(in <#=OTHERTYPENAME#><T> other)
1049 {
1050 if(other.Length > Capacity)
1051 return (int)CopyError.Truncation;
1052 length = other.length;
1053 unsafe
1054 {
1055 UnsafeUtility.MemCpy(Buffer, other.Buffer, LengthInBytes);
1056 }
1057 return 0;
1058 }
1059
1060 /// <summary>
1061 /// Returns a new list that is a copy of another list.
1062 /// </summary>
1063 /// <param name="other">The list to copy.</param>
1064 /// <returns>A new list that is a copy of the other.</returns>
1065 /// <exception cref="IndexOutOfRangeException">Throws if the other list's length exceeds the capacity of <#=TYPENAME#><T>.</exception>
1066 public static implicit operator <#=TYPENAME#><T>(in <#=OTHERTYPENAME#><T> other)
1067 {
1068 return new <#=TYPENAME#><T>(other);
1069 }
1070<#
1071 }
1072 }
1073#>
1074
1075 /// <summary>
1076 /// Returns true if the list is equal to an object.
1077 /// </summary>
1078 /// <remarks>Two lists are equal if their length and bytes are equal.
1079 ///
1080 /// A FixedList*N*<T> can only be equal to another FixedList*N*<T> with the same *N* and T.
1081 /// </remarks>
1082 /// <param name="obj">An object to compare for equality.</param>
1083 /// <returns>True if the list is equal to the object.</returns>
1084 [ExcludeFromBurstCompatTesting("Takes managed object")]
1085 public override bool Equals(object obj)
1086 {
1087<#
1088 foreach(var OTHERBYTES in SIZES)
1089 {
1090 var OTHERTYPENAME = String.Format("FixedList{0}Bytes", OTHERBYTES);
1091 WriteLine(" if(obj is {0}<T> a{0}) return Equals(a{0});", OTHERTYPENAME);
1092 }
1093#>
1094 return false;
1095 }
1096
1097 /// <summary>
1098 /// An enumerator over the elements of a <#=TYPENAME#><T>.
1099 /// </summary>
1100 /// <remarks>
1101 /// In an enumerator's initial state, `Current` cannot be read. The first <see cref="MoveNext"/> call advances the enumerator to the first element.
1102 /// </remarks>
1103 public struct Enumerator : IEnumerator<T>
1104 {
1105 <#=TYPENAME#><T> m_List;
1106 int m_Index;
1107
1108 /// <summary>
1109 /// Initializes and returns an instance of <#=TYPENAME#><T>.
1110 /// </summary>
1111 /// <param name="list">The list for which to create an enumerator.</param>
1112 public Enumerator(ref <#=TYPENAME#><T> list)
1113 {
1114 m_List = list;
1115 m_Index = -1;
1116 }
1117
1118 /// <summary>
1119 /// Does nothing.
1120 /// </summary>
1121 public void Dispose()
1122 {
1123 }
1124
1125 /// <summary>
1126 /// Advances the enumerator to the next element.
1127 /// </summary>
1128 /// <returns>True if <see cref="Current"/> is valid to read after the call.</returns>
1129 [MethodImpl(MethodImplOptions.AggressiveInlining)]
1130 public bool MoveNext()
1131 {
1132 m_Index++;
1133 return m_Index < m_List.Length;
1134 }
1135
1136 /// <summary>
1137 /// Resets the enumerator to its initial state.
1138 /// </summary>
1139 public void Reset()
1140 {
1141 m_Index = -1;
1142 }
1143
1144 /// <summary>
1145 /// The current element.
1146 /// </summary>
1147 /// <value>The current element.</value>
1148 public T Current
1149 {
1150 [MethodImpl(MethodImplOptions.AggressiveInlining)]
1151 get => m_List[m_Index]; // Let <#=TYPENAME#><T> indexer check for out of range.
1152 }
1153
1154 object IEnumerator.Current => Current;
1155 }
1156
1157 /// <summary>
1158 /// Returns an enumerator for iterating over the elements of this list.
1159 /// </summary>
1160 /// <returns>An enumerator for iterating over the elements of this list.</returns>
1161 public Enumerator GetEnumerator()
1162 {
1163 return new Enumerator(ref this);
1164 }
1165
1166 /// <summary>
1167 /// This method is not implemented. Use <see cref="GetEnumerator"/> instead.
1168 /// </summary>
1169 /// <returns>Nothing because it always throws <see cref="NotImplementedException"/>.</returns>
1170 /// <exception cref="NotImplementedException">Method is not implemented.</exception>
1171 IEnumerator IEnumerable.GetEnumerator()
1172 {
1173 throw new NotImplementedException();
1174 }
1175
1176 /// <summary>
1177 /// This method is not implemented. Use <see cref="GetEnumerator"/> instead.
1178 /// </summary>
1179 /// <returns>Nothing because it always throws <see cref="NotImplementedException"/>.</returns>
1180 /// <exception cref="NotImplementedException">Method is not implemented.</exception>
1181 IEnumerator<T> IEnumerable<T>.GetEnumerator()
1182 {
1183 throw new NotImplementedException();
1184 }
1185 }
1186
1187 /// <summary>
1188 /// Provides extension methods for <#=TYPENAME#>.
1189 /// </summary>
1190 [GenerateTestsForBurstCompatibility]
1191 public unsafe static class <#=TYPENAME#>Extensions
1192 {
1193 /// <summary>
1194 /// Finds the index of the first occurrence of a particular value in this list.
1195 /// </summary>
1196 /// <typeparam name="T">The type of elements in this list.</typeparam>
1197 /// <typeparam name="U">The value type.</typeparam>
1198 /// <param name="list">The list to search.</param>
1199 /// <param name="value">The value to locate.</param>
1200 /// <returns>The index of the first occurrence of the value. Returns -1 if no occurrence is found.</returns>
1201 [GenerateTestsForBurstCompatibility(GenericTypeArguments = new [] { typeof(int), typeof(int) })]
1202 public static int IndexOf<T, U>(this ref <#=TYPENAME#><T> list, U value) where T : unmanaged, IEquatable<U>
1203 {
1204 return NativeArrayExtensions.IndexOf<T, U>(list.Buffer, list.Length, value);
1205 }
1206
1207 /// <summary>
1208 /// Returns true if a particular value is present in this list.
1209 /// </summary>
1210 /// <typeparam name="T">The type of elements in this list.</typeparam>
1211 /// <typeparam name="U">The value type.</typeparam>
1212 /// <param name="list">The list to search.</param>
1213 /// <param name="value">The value to locate.</param>
1214 /// <returns>True if the value is present in this list.</returns>
1215 [GenerateTestsForBurstCompatibility(GenericTypeArguments = new [] { typeof(int), typeof(int) })]
1216 public static bool Contains<T, U>(this ref <#=TYPENAME#><T> list, U value) where T : unmanaged, IEquatable<U>
1217 {
1218 return list.IndexOf(value) != -1;
1219 }
1220
1221 /// <summary>
1222 /// Removes the first occurrence of a particular value in this list.
1223 /// </summary>
1224 /// <remarks>
1225 /// If a value is removed, all elements after it are shifted down by one, and the list's length is decremented by one.
1226 ///
1227 /// If you don't need to preserve the order of the remaining elements, <see cref="Unity.Collections.<#=TYPENAME#>Extensions.RemoveSwapBack{T, U}"/> is a cheaper alternative.
1228 /// </remarks>
1229 /// <typeparam name="T">The type of elements in this list.</typeparam>
1230 /// <typeparam name="U">The value type.</typeparam>
1231 /// <param name="list">The list to search.</param>
1232 /// <param name="value">The value to locate and remove.</param>
1233 /// <returns>True if the value was found and removed.</returns>
1234 [GenerateTestsForBurstCompatibility(GenericTypeArguments = new [] { typeof(int), typeof(int) })]
1235 public static bool Remove<T, U>(this ref <#=TYPENAME#><T> list, U value) where T : unmanaged, IEquatable<U>
1236 {
1237 int index = list.IndexOf(value);
1238 if (index < 0)
1239 {
1240 return false;
1241 }
1242
1243 list.RemoveAt(index);
1244
1245 return true;
1246 }
1247
1248 /// <summary>
1249 /// Removes the first occurrence of a particular value in this list.
1250 /// </summary>
1251 /// <remarks>
1252 /// If a value is removed, the last element of the list is copied to overwrite the removed value, and the list's length is decremented by one.
1253 ///
1254 /// This is cheaper than <see cref="Remove"/>, but the order of the remaining elements is not preserved.
1255 /// </remarks>
1256 /// <typeparam name="T">The type of elements in this list.</typeparam>
1257 /// <typeparam name="U">The value type.</typeparam>
1258 /// <param name="list">The list to search.</param>
1259 /// <param name="value">The value to locate and remove.</param>
1260 /// <returns>Returns true if the item is removed.</returns>
1261 [GenerateTestsForBurstCompatibility(GenericTypeArguments = new [] { typeof(int), typeof(int) })]
1262 public static bool RemoveSwapBack<T, U>(this ref <#=TYPENAME#><T> list, U value) where T : unmanaged, IEquatable<U>
1263 {
1264 var index = list.IndexOf(value);
1265 if (index == -1)
1266 {
1267 return false;
1268 }
1269
1270 list.RemoveAtSwapBack(index);
1271
1272 return true;
1273 }
1274 }
1275
1276 sealed class <#=TYPENAME#>DebugView<T> where T : unmanaged
1277 {
1278 <#=TYPENAME#><T> m_List;
1279 public <#=TYPENAME#>DebugView(<#=TYPENAME#><T> list)
1280 {
1281 m_List = list;
1282 }
1283 public T[] Items => m_List.ToArray();
1284 }
1285<#
1286}
1287#>
1288
1289<#
1290var TYPES = new string[]{"byte","int","float"};
1291var TYPESIZES = new int[]{1,4,4};
1292for(var type = 0; type < 3; ++type)
1293for(var size = 0; size < 5; ++size)
1294{
1295 var BYTES = SIZES[size];
1296 var TYPE = TYPES[type];
1297 var TYPESIZE = TYPESIZES[type];
1298 var BUFFER_BYTES = BYTES;
1299 var TYPENAME = String.Format("FixedList{0}{1}", new CultureInfo("en-US").TextInfo.ToTitleCase(TYPE), BYTES);
1300 var NEW_TYPENAME = $"FixedList{BYTES}Bytes<{TYPE}>";
1301#>
1302
1303
1304<#
1305}
1306#>
1307 /// <summary>
1308 /// Provides extension methods for FixedList*N*.
1309 /// </summary>
1310 public static class FixedListExtensions
1311 {
1312<#
1313for(var size = 0; size < 5; ++size)
1314{
1315 var BYTES = SIZES[size];
1316 var BUFFER_BYTES = BYTES;
1317 var TYPENAME = String.Format("FixedList{0}Bytes", BYTES);
1318#>
1319
1320 /// <summary>
1321 /// Sorts the elements in this list in ascending order.
1322 /// </summary>
1323 /// <typeparam name="T">The type of the elements.</typeparam>
1324 /// <param name="list">The list to sort.</param>
1325 [GenerateTestsForBurstCompatibility(GenericTypeArguments = new [] { typeof(int) })]
1326 public static void Sort<T>(this ref <#=TYPENAME#><T> list)
1327 where T : unmanaged, IComparable<T>
1328 {
1329 unsafe
1330 {
1331 var c = list.buffer + FixedList.PaddingBytes<T>();
1332 NativeSortExtension.Sort((T*)c, list.Length);
1333 }
1334 }
1335
1336 /// <summary>
1337 /// Sorts the elements in this list using a custom comparison.
1338 /// </summary>
1339 /// <typeparam name="T">The type of the elements.</typeparam>
1340 /// <typeparam name="U">The type of the comparer.</typeparam>
1341 /// <param name="list">The list to sort.</param>
1342 /// <param name="comp">The comparison function used to determine the relative order of the elements.</param>
1343 [GenerateTestsForBurstCompatibility(GenericTypeArguments = new [] { typeof(int), typeof(NativeSortExtension.DefaultComparer<int>) })]
1344 public static void Sort<T, U>(this ref <#=TYPENAME#><T> list, U comp)
1345 where T : unmanaged, IComparable<T>
1346 where U : IComparer<T>
1347 {
1348 unsafe
1349 {
1350 var c = list.buffer + FixedList.PaddingBytes<T>();
1351 NativeSortExtension.Sort((T*)c, list.Length, comp);
1352 }
1353 }
1354
1355<#
1356}
1357#>
1358 }
1359}