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#>&lt;T&gt;.</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#>&lt;T&gt;.</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*&lt;T&gt; can only be equal to another FixedList*N*&lt;T&gt; 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#>&lt;T&gt;. 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#>&lt;T&gt;. 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}