A game about forced loneliness, made by TACStudios
at master 6556 lines 278 kB view raw
1 2//------------------------------------------------------------------------------ 3// <auto-generated> 4// This code was generated by a tool. 5// 6// TextTransform Samples/Packages/com.unity.collections/Unity.Collections/FixedList.tt 7// 8// Changes to this file may cause incorrect behavior and will be lost if 9// the code is regenerated. 10// </auto-generated> 11//------------------------------------------------------------------------------ 12 13using System.Collections.Generic; 14using System.Collections; 15using System.Diagnostics; 16using System.Runtime.CompilerServices; 17using System.Runtime.InteropServices; 18using System; 19using Unity.Collections.LowLevel.Unsafe; 20using Unity.Mathematics; 21using UnityEngine.Internal; 22using UnityEngine; 23using Unity.Properties; 24 25namespace Unity.Collections 26{ 27 [GenerateTestsForBurstCompatibility(GenericTypeArguments = new [] { typeof(int), typeof(FixedBytes32Align8) })] 28 [Serializable] 29 internal struct FixedList<T,U> 30 : INativeList<T> 31 where T : unmanaged 32 where U : unmanaged 33 { 34 [SerializeField] internal U data; 35 36 internal ushort length 37 { 38 [MethodImpl(MethodImplOptions.AggressiveInlining)] 39 readonly get 40 { 41 unsafe 42 { 43 fixed(void* ptr = &data) 44 return *((ushort*)ptr); 45 } 46 } 47 48 [MethodImpl(MethodImplOptions.AggressiveInlining)] 49 set 50 { 51 unsafe 52 { 53 fixed (void* ptr = &data) 54 *((ushort*)ptr) = value; 55 } 56 } 57 } 58 59 internal readonly unsafe byte* buffer 60 { 61 [MethodImpl(MethodImplOptions.AggressiveInlining)] 62 get 63 { 64 unsafe 65 { 66 fixed (void* ptr = &data) 67 return ((byte*)ptr) + UnsafeUtility.SizeOf<ushort>(); 68 } 69 } 70 } 71 72 /// <summary> 73 /// The current number of items in this list. 74 /// </summary> 75 /// <value>The current number of items in this list.</value> 76 [CreateProperty] 77 public int Length 78 { 79 [MethodImpl(MethodImplOptions.AggressiveInlining)] 80 readonly get => length; 81 82 set 83 { 84 FixedList.CheckResize<U,T>(value); 85 length = (ushort)value; 86 } 87 } 88 89 /// <summary> 90 /// A property in order to display items in the Entity Inspector. 91 /// </summary> 92 [CreateProperty] IEnumerable<T> Elements => this.ToArray(); 93 94 /// <summary> 95 /// Whether the list is empty. 96 /// </summary> 97 /// <value>True if this string has no characters or if the container has not been constructed.</value> 98 public readonly bool IsEmpty 99 { 100 [MethodImpl(MethodImplOptions.AggressiveInlining)] 101 get => Length == 0; 102 } 103 104 internal readonly int LengthInBytes => Length * UnsafeUtility.SizeOf<T>(); 105 106 internal readonly unsafe byte* Buffer 107 { 108 [MethodImpl(MethodImplOptions.AggressiveInlining)] 109 get 110 { 111 return buffer + FixedList.PaddingBytes<T>(); 112 } 113 } 114 115 /// <summary> 116 /// The number of elements that can fit in this list. 117 /// </summary> 118 /// <value>The number of elements that can fit in this list.</value> 119 /// <remarks>The capacity of a FixedList cannot be changed. The setter is included only for conformity with <see cref="INativeList{T}"/>.</remarks> 120 /// <exception cref="ArgumentOutOfRangeException">Thrown if the new value does not match the current capacity.</exception> 121 public int Capacity 122 { 123 [MethodImpl(MethodImplOptions.AggressiveInlining)] 124 readonly get 125 { 126 return FixedList.Capacity<U,T>(); 127 } 128 129 set 130 { 131 CollectionHelper.CheckCapacityInRange(value, Length); 132 } 133 } 134 135 /// <summary> 136 /// The element at a given index. 137 /// </summary> 138 /// <param name="index">An index.</param> 139 /// <value>The value to store at the index.</value> 140 /// <exception cref="IndexOutOfRangeException">Thrown if the index is out of bounds.</exception> 141 public T this[int index] 142 { 143 [MethodImpl(MethodImplOptions.AggressiveInlining)] 144 readonly get 145 { 146 CollectionHelper.CheckIndexInRange(index, length); 147 unsafe 148 { 149 return UnsafeUtility.ReadArrayElement<T>(Buffer, CollectionHelper.AssumePositive(index)); 150 } 151 } 152 153 [MethodImpl(MethodImplOptions.AggressiveInlining)] 154 set 155 { 156 CollectionHelper.CheckIndexInRange(index, length); 157 unsafe 158 { 159 UnsafeUtility.WriteArrayElement<T>(Buffer, CollectionHelper.AssumePositive(index), value); 160 } 161 } 162 } 163 164 /// <summary> 165 /// Returns the element at a given index. 166 /// </summary> 167 /// <param name="index">An index.</param> 168 /// <returns>A reference to the element at the index.</returns> 169 [MethodImpl(MethodImplOptions.AggressiveInlining)] 170 public ref T ElementAt(int index) 171 { 172 CollectionHelper.CheckIndexInRange(index, length); 173 unsafe 174 { 175 return ref UnsafeUtility.ArrayElementAsRef<T>(Buffer, index); 176 } 177 } 178 179 /// <summary> 180 /// Returns the hash code of this list. 181 /// </summary> 182 /// <remarks> 183 /// 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> 184 /// <returns>The hash code of this list.</returns> 185 public override int GetHashCode() 186 { 187 unsafe 188 { 189 return (int)CollectionHelper.Hash(Buffer, LengthInBytes); 190 } 191 } 192 193 /// <summary> 194 /// Appends an element to the end of this list. Increments the length by 1. 195 /// </summary> 196 /// <remarks> 197 /// The same as <see cref="AddNoResize"/>. Included only for consistency with the other list types. 198 /// If the element exceeds the capacity, throws cref="IndexOutOfRangeException", and the list is unchanged. 199 /// </remarks> 200 /// <param name="item">The element to append at the end of the list.</param> 201 /// <exception cref="IndexOutOfRangeException">Thrown if the append exceeds the capacity.</exception> 202 public void Add(in T item) => AddNoResize(in item); 203 204 /// <summary> 205 /// Appends elements from a buffer to the end of this list. Increments the length by the number of appended elements. 206 /// </summary> 207 /// <remarks> 208 /// The same as <see cref="AddRangeNoResize"/>. Included only for consistency with the other list types. 209 /// If the elements exceeds the capacity, throws cref="IndexOutOfRangeException", and the list is unchanged. 210 /// </remarks> 211 /// <param name="ptr">A buffer.</param> 212 /// <param name="length">The number of elements from the buffer to append.</param> 213 /// <exception cref="IndexOutOfRangeException">Thrown if the append exceeds the capacity.</exception> 214 public unsafe void AddRange(void* ptr, int length) => AddRangeNoResize(ptr, length); 215 216 /// <summary> 217 /// Appends an element to the end of this list. Increments the length by 1. 218 /// </summary> 219 /// <remarks> 220 /// If the element exceeds the capacity, throws cref="IndexOutOfRangeException", and the list is unchanged. 221 /// </remarks> 222 /// <param name="item">The element to append at the end of the list.</param> 223 /// <exception cref="IndexOutOfRangeException">Thrown if the append exceeds the capacity.</exception> 224 [MethodImpl(MethodImplOptions.AggressiveInlining)] 225 public void AddNoResize(in T item) 226 { 227 this[Length++] = item; 228 } 229 230 /// <summary> 231 /// Appends elements from a buffer to the end of this list. Increments the length by the number of appended elements. 232 /// </summary> 233 /// <remarks> 234 /// If the elements exceeds the capacity, throws cref="IndexOutOfRangeException", and the list is unchanged. 235 /// </remarks> 236 /// <param name="ptr">A buffer.</param> 237 /// <param name="length">The number of elements from the buffer to append.</param> 238 /// <exception cref="IndexOutOfRangeException">Thrown if the append exceeds the capacity.</exception> 239 public unsafe void AddRangeNoResize(void* ptr, int length) 240 { 241 var idx = Length; 242 Length += length; 243 UnsafeUtility.MemCpy((T*)Buffer + idx, ptr, UnsafeUtility.SizeOf<T>() * length); 244 } 245 246 /// <summary> 247 /// Appends value count times to the end of this list. 248 /// </summary> 249 /// <remarks> 250 /// If the elements exceeds the capacity, throws cref="IndexOutOfRangeException", and the list is unchanged. 251 /// </remarks> 252 /// <param name="value">The value to add to the end of this list.</param> 253 /// <param name="count">The number of times to replicate the value.</param> 254 /// <exception cref="IndexOutOfRangeException">Thrown if the append exceeds the capacity.</exception> 255 public unsafe void AddReplicate(in T value, int count) 256 { 257 var idx = Length; 258 Length += count; 259 fixed (T* ptr = &value) 260 UnsafeUtility.MemCpyReplicate((T*)Buffer + idx, ptr, UnsafeUtility.SizeOf<T>(), count); 261 } 262 263 /// <summary> 264 /// Sets the length to 0. 265 /// </summary> 266 /// <remarks> Does *not* zero out the bytes.</remarks> 267 public void Clear() 268 { 269 Length = 0; 270 } 271 272 /// <summary> 273 /// Shifts elements toward the end of this list, increasing its length. 274 /// </summary> 275 /// <remarks> 276 /// Right-shifts elements in the list so as to create 'free' slots at the beginning or in the middle. 277 /// 278 /// The length is increased by `end - begin`. 279 /// 280 /// If `end` equals `begin`, the method does nothing. 281 /// 282 /// 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. 283 /// 284 /// The indexes `begin` up to `end` are not cleared: they will contain whatever values they held prior. 285 /// </remarks> 286 /// <param name="begin">The index of the first element that will be shifted up.</param> 287 /// <param name="end">The index where the first shifted element will end up.</param> 288 /// <exception cref="IndexOutOfRangeException">Thrown if the new length exceeds the capacity.</exception> 289 public void InsertRangeWithBeginEnd(int begin, int end) 290 { 291 int items = end - begin; 292 if(items < 1) 293 return; 294 int itemsToCopy = length - begin; 295 Length += items; 296 if(itemsToCopy < 1) 297 return; 298 int bytesToCopy = itemsToCopy * UnsafeUtility.SizeOf<T>(); 299 unsafe 300 { 301 byte *b = Buffer; 302 byte *dest = b + end * UnsafeUtility.SizeOf<T>(); 303 byte *src = b + begin * UnsafeUtility.SizeOf<T>(); 304 UnsafeUtility.MemMove(dest, src, bytesToCopy); 305 } 306 } 307 308 /// <summary> 309 /// Shifts elements toward the end of this list, increasing its length. 310 /// </summary> 311 /// <remarks> 312 /// Right-shifts elements in the list so as to create 'free' slots at the beginning or in the middle. 313 /// 314 /// The length is increased by `count`. If necessary, the capacity will be increased accordingly. 315 /// 316 /// If `count` equals `0`, the method does nothing. 317 /// 318 /// 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. 319 /// 320 /// The indexes `index` up to `index + count` are not cleared: they will contain whatever values they held prior. 321 /// </remarks> 322 /// <param name="index">The index of the first element that will be shifted up.</param> 323 /// <param name="count">The number of elements to insert.</param> 324 /// <exception cref="ArgumentException">Thrown if `count` is negative.</exception> 325 /// <exception cref="ArgumentOutOfRangeException">Thrown if `index` is out of bounds.</exception> 326 public void InsertRange(int index, int count) => InsertRangeWithBeginEnd(index, index + count); 327 328 /// <summary> 329 /// Inserts a single element at an index. Increments the length by 1. 330 /// </summary> 331 /// <param name="index">The index at which to insert the element.</param> 332 /// <param name="item">The element to insert.</param> 333 /// <exception cref="ArgumentOutOfRangeException">Thrown if the index is out of bounds.</exception> 334 public void Insert(int index, in T item) 335 { 336 InsertRangeWithBeginEnd(index, index+1); 337 this[index] = item; 338 } 339 340 /// <summary> 341 /// Copies the last element of this list to an index. Decrements the length by 1. 342 /// </summary> 343 /// <remarks>Useful as a cheap way to remove elements from a list when you don't care about preserving order.</remarks> 344 /// <param name="index">The index to overwrite with the last element.</param> 345 /// <exception cref="ArgumentOutOfRangeException">Thrown if the index is out of bounds.</exception> 346 public void RemoveAtSwapBack(int index) 347 { 348 RemoveRangeSwapBack(index, 1); 349 } 350 351 /// <summary> 352 /// Copies the last *N* elements of this list to a range in this list. Decrements the length by *N*. 353 /// </summary> 354 /// <remarks> 355 /// Copies the last `count`-numbered elements to the range starting at `index`. 356 /// 357 /// Useful as a cheap way to remove elements from a list when you don't care about preserving order. 358 /// 359 /// Does nothing if the count is less than 1. 360 /// </remarks> 361 /// <param name="index">The first index of the destination range.</param> 362 /// <param name="count">The number of elements to copy and the amount by which to decrement the length.</param> 363 /// <exception cref="ArgumentOutOfRangeException">Thrown if the index is out of bounds.</exception> 364 public void RemoveRangeSwapBack(int index, int count) 365 { 366 if (count > 0) 367 { 368 int copyFrom = math.max(Length - count, index + count); 369 370 unsafe 371 { 372 var sizeOf = UnsafeUtility.SizeOf<T>(); 373 void* dst = Buffer + index * sizeOf; 374 void* src = Buffer + copyFrom * sizeOf; 375 UnsafeUtility.MemCpy(dst, src, (Length - copyFrom) * sizeOf); 376 } 377 378 Length -= count; 379 } 380 } 381 382 /// <summary> 383 /// Removes the element at an index. Shifts everything above the index down by one and decrements the length by 1. 384 /// </summary> 385 /// <param name="index">The index of the element to remove.</param> 386 /// <remarks> 387 /// If you don't care about preserving the order of the elements, `RemoveAtSwapBack` is a more efficient way to remove an element. 388 /// </remarks> 389 /// <exception cref="ArgumentOutOfRangeException">Thrown if the index is out of bounds.</exception> 390 public void RemoveAt(int index) 391 { 392 RemoveRange(index, 1); 393 } 394 395 /// <summary> 396 /// Removes *N* elements of a range. Shifts everything above the range down by *N* and decrements the length by *N*. 397 /// </summary> 398 /// <remarks> 399 /// If you don't care about preserving the order of the elements, `RemoveAtSwapBack` is a more efficient way to remove elements. 400 /// </remarks> 401 /// <param name="index">The first index of the range to remove.</param> 402 /// <param name="count">The number of elements to remove.</param> 403 /// <exception cref="ArgumentOutOfRangeException">Thrown if the index is out of bounds.</exception> 404 public void RemoveRange(int index, int count) 405 { 406 if (count > 0) 407 { 408 int copyFrom = math.min(index + count, Length); 409 410 unsafe 411 { 412 var sizeOf = UnsafeUtility.SizeOf<T>(); 413 void* dst = Buffer + index * sizeOf; 414 void* src = Buffer + copyFrom * sizeOf; 415 UnsafeUtility.MemCpy(dst, src, (Length - copyFrom) * sizeOf); 416 } 417 418 Length -= count; 419 } 420 } 421 422 /// <summary> 423 /// Returns a managed array that is a copy of this list. 424 /// </summary> 425 /// <returns>A managed array that is a copy of this list.</returns> 426 [ExcludeFromBurstCompatTesting("Returns managed array")] 427 public T[] ToArray() 428 { 429 var result = new T[Length]; 430 unsafe 431 { 432 byte* s = Buffer; 433 fixed(T* d = result) 434 UnsafeUtility.MemCpy(d, s, LengthInBytes); 435 } 436 return result; 437 } 438 439 /// <summary> 440 /// Returns an array that is a copy of this list. 441 /// </summary> 442 /// <param name="allocator">The allocator to use.</param> 443 /// <returns>An array that is a copy of this list.</returns> 444 public NativeArray<T> ToNativeArray(AllocatorManager.AllocatorHandle allocator) 445 { 446 unsafe 447 { 448 var copy = CollectionHelper.CreateNativeArray<T>(Length, allocator, NativeArrayOptions.UninitializedMemory); 449 UnsafeUtility.MemCpy(copy.GetUnsafePtr(), Buffer, LengthInBytes); 450 return copy; 451 } 452 } 453 } 454 455 [GenerateTestsForBurstCompatibility] 456 struct FixedList 457 { 458 [GenerateTestsForBurstCompatibility(GenericTypeArguments = new [] { typeof(int) })] 459 [MethodImpl(MethodImplOptions.AggressiveInlining)] 460 internal static int PaddingBytes<T>() where T : unmanaged 461 { 462 return math.max(0, math.min(6, (1 << math.tzcnt(UnsafeUtility.SizeOf<T>())) - 2)); 463 } 464 465 [GenerateTestsForBurstCompatibility(GenericTypeArguments = new [] { typeof(int), typeof(int) })] 466 [MethodImpl(MethodImplOptions.AggressiveInlining)] 467 internal static int StorageBytes<BUFFER,T>() where BUFFER : unmanaged where T : unmanaged 468 { 469 return UnsafeUtility.SizeOf<BUFFER>() - UnsafeUtility.SizeOf<ushort>() - PaddingBytes<T>(); 470 } 471 472 [GenerateTestsForBurstCompatibility(GenericTypeArguments = new [] { typeof(int), typeof(int) })] 473 [MethodImpl(MethodImplOptions.AggressiveInlining)] 474 internal static int Capacity<BUFFER,T>() where BUFFER : unmanaged where T : unmanaged 475 { 476 return StorageBytes<BUFFER,T>() / UnsafeUtility.SizeOf<T>(); 477 } 478 479 [GenerateTestsForBurstCompatibility(GenericTypeArguments = new [] { typeof(int), typeof(int) })] 480 [Conditional("ENABLE_UNITY_COLLECTIONS_CHECKS"), Conditional("UNITY_DOTS_DEBUG")] 481 internal static void CheckResize<BUFFER,T>(int newLength) where BUFFER : unmanaged where T : unmanaged 482 { 483 var Capacity = Capacity<BUFFER,T>(); 484 if (newLength < 0 || newLength > Capacity) 485 throw new IndexOutOfRangeException($"NewLength {newLength} is out of range of '{Capacity}' Capacity."); 486 } 487 } 488 489 /// <summary> 490 /// An unmanaged, resizable list whose content is all stored directly in the 32-byte struct. Useful for small lists. 491 /// </summary> 492 /// <typeparam name="T">The type of the elements.</typeparam> 493 [Serializable] 494 [DebuggerTypeProxy(typeof(FixedList32BytesDebugView<>))] 495 [GenerateTestsForBurstCompatibility(GenericTypeArguments = new [] { typeof(int) })] 496 public struct FixedList32Bytes<T> 497 : INativeList<T> 498 , IEnumerable<T> // Used by collection initializers. 499 , IEquatable<FixedList32Bytes<T>> 500 , IComparable<FixedList32Bytes<T>> 501 , IEquatable<FixedList64Bytes<T>> 502 , IComparable<FixedList64Bytes<T>> 503 , IEquatable<FixedList128Bytes<T>> 504 , IComparable<FixedList128Bytes<T>> 505 , IEquatable<FixedList512Bytes<T>> 506 , IComparable<FixedList512Bytes<T>> 507 , IEquatable<FixedList4096Bytes<T>> 508 , IComparable<FixedList4096Bytes<T>> 509 where T : unmanaged 510 { 511 [SerializeField] internal FixedBytes32Align8 data; 512 513 internal ushort length 514 { 515 [MethodImpl(MethodImplOptions.AggressiveInlining)] 516 readonly get 517 { 518 unsafe 519 { 520 fixed(void* ptr = &data) 521 return *((ushort*)ptr); 522 } 523 } 524 525 [MethodImpl(MethodImplOptions.AggressiveInlining)] 526 set 527 { 528 unsafe 529 { 530 fixed (void* ptr = &data) 531 *((ushort*)ptr) = value; 532 } 533 } 534 } 535 536 internal readonly unsafe byte* buffer 537 { 538 [MethodImpl(MethodImplOptions.AggressiveInlining)] 539 get 540 { 541 unsafe 542 { 543 fixed (void* ptr = &data) 544 return ((byte*)ptr) + UnsafeUtility.SizeOf<ushort>(); 545 } 546 } 547 } 548 549 /// <summary> 550 /// The current number of items in this list. 551 /// </summary> 552 /// <value>The current number of items in this list.</value> 553 [CreateProperty] 554 public int Length 555 { 556 [MethodImpl(MethodImplOptions.AggressiveInlining)] 557 readonly get => length; 558 set 559 { 560 FixedList.CheckResize<FixedBytes32Align8,T>(value); 561 length = (ushort)value; 562 } 563 } 564 565 /// <summary> 566 /// A property in order to display items in the Entity Inspector. 567 /// </summary> 568 [CreateProperty] IEnumerable<T> Elements => this.ToArray(); 569 570 /// <summary> 571 /// Whether this list is empty. 572 /// </summary> 573 /// <value>True if this string has no characters or if the container has not been constructed.</value> 574 public readonly bool IsEmpty 575 { 576 [MethodImpl(MethodImplOptions.AggressiveInlining)] 577 get => Length == 0; 578 } 579 580 internal int LengthInBytes => Length * UnsafeUtility.SizeOf<T>(); 581 582 /// <summary> 583 /// Returns a pointer to the first element of the list buffer. 584 /// </summary> 585 /// <remarks> 586 /// The pointer returned by this method points into the internals of the target list object. It is the 587 /// caller's responsibility to ensure that the pointer is not used after the list is destroyed or goes 588 /// out of scope. 589 /// </remarks> 590 /// <returns>A pointer to the first element of the list buffer.</returns> 591 internal readonly unsafe byte* Buffer 592 { 593 [MethodImpl(MethodImplOptions.AggressiveInlining)] 594 get 595 { 596 return buffer + FixedList.PaddingBytes<T>(); 597 } 598 } 599 600 /// <summary> 601 /// The number of elements that can fit in this list. 602 /// </summary> 603 /// <value>The number of elements that can fit in this list.</value> 604 /// <remarks>The capacity of a FixedList cannot be changed. The setter is included only for conformity with <see cref="INativeList{T}"/>.</remarks> 605 /// <exception cref="ArgumentOutOfRangeException">Thrown if the new value does not match the current capacity.</exception> 606 public int Capacity 607 { 608 [MethodImpl(MethodImplOptions.AggressiveInlining)] 609 readonly get 610 { 611 return FixedList.Capacity<FixedBytes32Align8,T>(); 612 } 613 614 set 615 { 616 CollectionHelper.CheckCapacityInRange(value, Length); 617 } 618 } 619 620 /// <summary> 621 /// The element at a given index. 622 /// </summary> 623 /// <param name="index">An index.</param> 624 /// <value>The value to store at the index.</value> 625 /// <exception cref="IndexOutOfRangeException">Thrown if the index is out of bounds.</exception> 626 public T this[int index] 627 { 628 [MethodImpl(MethodImplOptions.AggressiveInlining)] 629 readonly get 630 { 631 CollectionHelper.CheckIndexInRange(index, length); 632 unsafe 633 { 634 return UnsafeUtility.ReadArrayElement<T>(Buffer, CollectionHelper.AssumePositive(index)); 635 } 636 } 637 638 [MethodImpl(MethodImplOptions.AggressiveInlining)] 639 set 640 { 641 CollectionHelper.CheckIndexInRange(index, length); 642 unsafe 643 { 644 UnsafeUtility.WriteArrayElement<T>(Buffer, CollectionHelper.AssumePositive(index), value); 645 } 646 } 647 } 648 649 /// <summary> 650 /// Returns the element at a given index. 651 /// </summary> 652 /// <param name="index">An index.</param> 653 /// <returns>The list element at the index.</returns> 654 [MethodImpl(MethodImplOptions.AggressiveInlining)] 655 public ref T ElementAt(int index) 656 { 657 CollectionHelper.CheckIndexInRange(index, length); 658 unsafe 659 { 660 return ref UnsafeUtility.ArrayElementAsRef<T>(Buffer, index); 661 } 662 } 663 664 /// <summary> 665 /// Returns the hash code of this list. 666 /// </summary> 667 /// <remarks> 668 /// 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> 669 /// <returns>The hash code of this list.</returns> 670 public override int GetHashCode() 671 { 672 unsafe 673 { 674 return (int)CollectionHelper.Hash(Buffer, LengthInBytes); 675 } 676 } 677 678 /// <summary> 679 /// Appends an element to the end of this list. Increments the length by 1. 680 /// </summary> 681 /// <remarks> 682 /// The same as <see cref="AddNoResize"/>. Included only for consistency with the other list types. 683 /// If the element exceeds the capacity, throws cref="IndexOutOfRangeException", and the list is unchanged. 684 /// </remarks> 685 /// <param name="item">The element to append at the end of the list.</param> 686 /// <exception cref="IndexOutOfRangeException">Thrown if the append exceeds the capacity.</exception> 687 public void Add(in T item) => AddNoResize(in item); 688 689 /// <summary> 690 /// Appends elements from a buffer to the end of this list. Increments the length by the number of appended elements. 691 /// </summary> 692 /// <remarks> 693 /// The same as <see cref="AddRangeNoResize"/>. Included only for consistency with the other list types. 694 /// If the elements exceeds the capacity, throws cref="IndexOutOfRangeException", and the list is unchanged. 695 /// </remarks> 696 /// <param name="ptr">A buffer.</param> 697 /// <param name="length">The number of elements from the buffer to append.</param> 698 /// <exception cref="IndexOutOfRangeException">Thrown if the append exceeds the capacity.</exception> 699 public unsafe void AddRange(void* ptr, int length) => AddRangeNoResize(ptr, length); 700 701 /// <summary> 702 /// Appends an element to the end of this list. Increments the length by 1. 703 /// </summary> 704 /// <remarks> 705 /// If the element exceeds the capacity, throws cref="IndexOutOfRangeException", and the list is unchanged. 706 /// </remarks> 707 /// <param name="item">The element to append at the end of the list.</param> 708 /// <exception cref="IndexOutOfRangeException">Thrown if the append exceeds the capacity.</exception> 709 [MethodImpl(MethodImplOptions.AggressiveInlining)] 710 public void AddNoResize(in T item) 711 { 712 this[Length++] = item; 713 } 714 715 /// <summary> 716 /// Appends elements from a buffer to the end of this list. Increments the length by the number of appended elements. 717 /// </summary> 718 /// <remarks> 719 /// If the elements exceeds the capacity, throws cref="IndexOutOfRangeException", and the list is unchanged. 720 /// </remarks> 721 /// <param name="ptr">A buffer.</param> 722 /// <param name="length">The number of elements from the buffer to append.</param> 723 /// <exception cref="IndexOutOfRangeException">Thrown if the append exceeds the capacity.</exception> 724 public unsafe void AddRangeNoResize(void* ptr, int length) 725 { 726 var idx = Length; 727 Length += length; 728 UnsafeUtility.MemCpy((T*)Buffer + idx, ptr, UnsafeUtility.SizeOf<T>() * length); 729 } 730 731 /// <summary> 732 /// Appends value count times to the end of this list. 733 /// </summary> 734 /// <param name="value">The value to add to the end of this list.</param> 735 /// <param name="count">The number of times to replicate the value.</param> 736 /// <exception cref="IndexOutOfRangeException">Thrown if the append exceeds the capacity.</exception> 737 public unsafe void AddReplicate(in T value, int count) 738 { 739 var idx = Length; 740 Length += count; 741 fixed (T* ptr = &value) 742 UnsafeUtility.MemCpyReplicate((T*)Buffer + idx, ptr, UnsafeUtility.SizeOf<T>(), count); 743 } 744 745 /// <summary> 746 /// Sets the length to 0. 747 /// </summary> 748 /// <remarks> Does *not* zero out the bytes.</remarks> 749 public void Clear() 750 { 751 Length = 0; 752 } 753 754 /// <summary> 755 /// Shifts elements toward the end of this list, increasing its length. 756 /// </summary> 757 /// <remarks> 758 /// Right-shifts elements in the list so as to create 'free' slots at the beginning or in the middle. 759 /// 760 /// The length is increased by `end - begin`. 761 /// 762 /// If `end` equals `begin`, the method does nothing. 763 /// 764 /// 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. 765 /// 766 /// The indexes `begin` up to `end` are not cleared: they will contain whatever values they held prior. 767 /// </remarks> 768 /// <param name="begin">The index of the first element that will be shifted up.</param> 769 /// <param name="end">The index where the first shifted element will end up.</param> 770 /// <exception cref="IndexOutOfRangeException">Thrown if the new length exceeds the capacity.</exception> 771 public void InsertRangeWithBeginEnd(int begin, int end) 772 { 773 int items = end - begin; 774 if(items < 1) 775 return; 776 int itemsToCopy = length - begin; 777 Length += items; 778 if(itemsToCopy < 1) 779 return; 780 int bytesToCopy = itemsToCopy * UnsafeUtility.SizeOf<T>(); 781 unsafe 782 { 783 byte *b = Buffer; 784 byte *dest = b + end * UnsafeUtility.SizeOf<T>(); 785 byte *src = b + begin * UnsafeUtility.SizeOf<T>(); 786 UnsafeUtility.MemMove(dest, src, bytesToCopy); 787 } 788 } 789 790 /// <summary> 791 /// Shifts elements toward the end of this list, increasing its length. 792 /// </summary> 793 /// <remarks> 794 /// Right-shifts elements in the list so as to create 'free' slots at the beginning or in the middle. 795 /// 796 /// The length is increased by `count`. If necessary, the capacity will be increased accordingly. 797 /// 798 /// If `count` equals `0`, the method does nothing. 799 /// 800 /// 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. 801 /// 802 /// The indexes `index` up to `index + count` are not cleared: they will contain whatever values they held prior. 803 /// </remarks> 804 /// <param name="index">The index of the first element that will be shifted up.</param> 805 /// <param name="count">The number of elements to insert.</param> 806 /// <exception cref="ArgumentException">Thrown if `count` is negative.</exception> 807 /// <exception cref="ArgumentOutOfRangeException">Thrown if `index` is out of bounds.</exception> 808 public void InsertRange(int index, int count) => InsertRangeWithBeginEnd(index, index + count); 809 810 /// <summary> 811 /// Inserts a single element at an index. Increments the length by 1. 812 /// </summary> 813 /// <param name="index">The index at which to insert the element.</param> 814 /// <param name="item">The element to insert.</param> 815 /// <exception cref="ArgumentOutOfRangeException">Thrown if the index is out of bounds.</exception> 816 public void Insert(int index, in T item) 817 { 818 InsertRangeWithBeginEnd(index, index+1); 819 this[index] = item; 820 } 821 822 /// <summary> 823 /// Copies the last element of this list to an index. Decrements the length by 1. 824 /// </summary> 825 /// <remarks>Useful as a cheap way to remove elements from a list when you don't care about preserving order.</remarks> 826 /// <param name="index">The index to overwrite with the last element.</param> 827 /// <exception cref="ArgumentOutOfRangeException">Thrown if the index is out of bounds.</exception> 828 public void RemoveAtSwapBack(int index) 829 { 830 RemoveRangeSwapBack(index, 1); 831 } 832 833 /// <summary> 834 /// Copies the last *N* elements of this list to a range in this list. Decrements the length by *N*. 835 /// </summary> 836 /// <remarks> 837 /// Copies the last `count`-numbered elements to the range starting at `index`. 838 /// 839 /// Useful as a cheap way to remove elements from a list when you don't care about preserving order. 840 /// 841 /// Does nothing if the count is less than 1. 842 /// </remarks> 843 /// <param name="index">The first index of the destination range.</param> 844 /// <param name="count">The number of elements to copy and the amount by which to decrement the length.</param> 845 /// <exception cref="ArgumentOutOfRangeException">Thrown if the index is out of bounds.</exception> 846 public void RemoveRangeSwapBack(int index, int count) 847 { 848 if (count > 0) 849 { 850 int copyFrom = math.max(Length - count, index + count); 851 852 unsafe 853 { 854 var sizeOf = UnsafeUtility.SizeOf<T>(); 855 void* dst = Buffer + index * sizeOf; 856 void* src = Buffer + copyFrom * sizeOf; 857 UnsafeUtility.MemCpy(dst, src, (Length - copyFrom) * sizeOf); 858 } 859 860 Length -= count; 861 } 862 } 863 864 /// <summary> 865 /// Removes the element at an index. Shifts everything above the index down by one and decrements the length by 1. 866 /// </summary> 867 /// <param name="index">The index of the element to remove.</param> 868 /// <remarks> 869 /// If you don't care about preserving the order of the elements, `RemoveAtSwapBack` is a more efficient way to remove an element. 870 /// </remarks> 871 /// <exception cref="ArgumentOutOfRangeException">Thrown if the index is out of bounds.</exception> 872 public void RemoveAt(int index) 873 { 874 RemoveRange(index, 1); 875 } 876 877 /// <summary> 878 /// Removes *N* elements of a range. Shifts everything above the range down by *N* and decrements the length by *N*. 879 /// </summary> 880 /// <remarks> 881 /// If you don't care about preserving the order of the elements, `RemoveAtSwapBack` is a more efficient way to remove elements. 882 /// </remarks> 883 /// <param name="index">The first index of the range to remove.</param> 884 /// <param name="count">The number of elements to remove.</param> 885 /// <exception cref="ArgumentOutOfRangeException">Thrown if the index is out of bounds.</exception> 886 public void RemoveRange(int index, int count) 887 { 888 if (count > 0) 889 { 890 int copyFrom = math.min(index + count, Length); 891 892 unsafe 893 { 894 var sizeOf = UnsafeUtility.SizeOf<T>(); 895 void* dst = Buffer + index * sizeOf; 896 void* src = Buffer + copyFrom * sizeOf; 897 UnsafeUtility.MemCpy(dst, src, (Length - copyFrom) * sizeOf); 898 } 899 900 Length -= count; 901 } 902 } 903 904 /// <summary> 905 /// Returns a managed array that is a copy of this list. 906 /// </summary> 907 /// <returns>A managed array that is a copy of this list.</returns> 908 [ExcludeFromBurstCompatTesting("Returns managed array")] 909 public T[] ToArray() 910 { 911 var result = new T[Length]; 912 unsafe 913 { 914 byte* s = Buffer; 915 fixed(T* d = result) 916 UnsafeUtility.MemCpy(d, s, LengthInBytes); 917 } 918 return result; 919 } 920 921 /// <summary> 922 /// Returns an array that is a copy of this list. 923 /// </summary> 924 /// <param name="allocator">The allocator to use.</param> 925 /// <returns>An array that is a copy of this list.</returns> 926 public NativeArray<T> ToNativeArray(AllocatorManager.AllocatorHandle allocator) 927 { 928 unsafe 929 { 930 var copy = CollectionHelper.CreateNativeArray<T>(Length, allocator, NativeArrayOptions.UninitializedMemory); 931 UnsafeUtility.MemCpy(copy.GetUnsafePtr(), Buffer, LengthInBytes); 932 return copy; 933 } 934 } 935 936 937 /// <summary> 938 /// Returns true if two lists are equal. 939 /// </summary> 940 /// <remarks>Two lists are equal if their length and bytes are equal.</remarks> 941 /// <param name="a">The first list to compare for equality.</param> 942 /// <param name="b">The second list to compare for equality.</param> 943 /// <returns>True if the two lists are equal.</returns> 944 public static bool operator ==(in FixedList32Bytes<T> a, in FixedList32Bytes<T> b) 945 { 946 unsafe 947 { 948 if(a.length != b.length) 949 return false; 950 return UnsafeUtility.MemCmp(a.Buffer, b.Buffer, a.LengthInBytes) == 0; 951 } 952 } 953 954 /// <summary> 955 /// Returns true if two lists are unequal. 956 /// </summary> 957 /// <remarks>Two lists are equal if their length and bytes are equal.</remarks> 958 /// <param name="a">The first list to compare for inequality.</param> 959 /// <param name="b">The second list to compare for inequality.</param> 960 /// <returns>True if the two lists are unequal.</returns> 961 public static bool operator !=(in FixedList32Bytes<T> a, in FixedList32Bytes<T> b) 962 { 963 return !(a == b); 964 } 965 966 /// <summary> 967 /// Returns a number denoting whether this list should be placed before or after another list in a sort. 968 /// </summary> 969 /// <param name="other">A list to to compare with.</param> 970 /// <returns>An integer denoting the respective sort position of the list relative to the other: 971 /// 972 /// 0 denotes that both lists should have the same position in a sort. 973 /// -1 denotes that this list should precede the other list in a sort. 974 /// +1 denotes that this list should follow the other list in a sort. 975 /// </returns> 976 public int CompareTo(FixedList32Bytes<T> other) 977 { 978 unsafe 979 { 980 byte* a = buffer; 981 byte* b = other.buffer; 982 var aa = a + FixedList.PaddingBytes<T>(); 983 var bb = b + FixedList.PaddingBytes<T>(); 984 var mini = math.min(Length, other.Length); 985 for(var i = 0; i < mini; ++i) 986 { 987 var j = UnsafeUtility.MemCmp(aa + sizeof(T) * i, bb + sizeof(T) * i, sizeof(T)); 988 if(j != 0) 989 return j; 990 } 991 return Length.CompareTo(other.Length); 992 } 993 } 994 995 /// <summary> 996 /// Returns true if this list and another list are equal. 997 /// </summary> 998 /// <remarks>Two lists are equal if their length and bytes are equal.</remarks> 999 /// <param name="other">The list to compare for equality.</param> 1000 /// <returns>True if the two lists are equal.</returns> 1001 public bool Equals(FixedList32Bytes<T> other) 1002 { 1003 return CompareTo(other) == 0; 1004 } 1005 1006 1007 /// <summary> 1008 /// Returns true if two lists are equal. 1009 /// </summary> 1010 /// <remarks>Two lists are equal if their length and bytes are equal.</remarks> 1011 /// <param name="a">The first list to compare for equality.</param> 1012 /// <param name="b">The second list to compare for equality.</param> 1013 /// <returns>True if the two lists are equal.</returns> 1014 public static bool operator ==(in FixedList32Bytes<T> a, in FixedList64Bytes<T> b) 1015 { 1016 unsafe 1017 { 1018 if(a.length != b.length) 1019 return false; 1020 return UnsafeUtility.MemCmp(a.Buffer, b.Buffer, a.LengthInBytes) == 0; 1021 } 1022 } 1023 1024 /// <summary> 1025 /// Returns true if two lists are unequal. 1026 /// </summary> 1027 /// <remarks>Two lists are equal if their length and bytes are equal.</remarks> 1028 /// <param name="a">The first list to compare for inequality.</param> 1029 /// <param name="b">The second list to compare for inequality.</param> 1030 /// <returns>True if the two lists are unequal.</returns> 1031 public static bool operator !=(in FixedList32Bytes<T> a, in FixedList64Bytes<T> b) 1032 { 1033 return !(a == b); 1034 } 1035 1036 /// <summary> 1037 /// Returns a number denoting whether this list should be placed before or after another list in a sort. 1038 /// </summary> 1039 /// <param name="other">A list to to compare with.</param> 1040 /// <returns>An integer denoting the respective sort position of the list relative to the other: 1041 /// 1042 /// 0 denotes that both lists should have the same position in a sort. 1043 /// -1 denotes that this list should precede the other list in a sort. 1044 /// +1 denotes that this list should follow the other list in a sort. 1045 /// </returns> 1046 public int CompareTo(FixedList64Bytes<T> other) 1047 { 1048 unsafe 1049 { 1050 byte* a = buffer; 1051 byte* b = other.buffer; 1052 var aa = a + FixedList.PaddingBytes<T>(); 1053 var bb = b + FixedList.PaddingBytes<T>(); 1054 var mini = math.min(Length, other.Length); 1055 for(var i = 0; i < mini; ++i) 1056 { 1057 var j = UnsafeUtility.MemCmp(aa + sizeof(T) * i, bb + sizeof(T) * i, sizeof(T)); 1058 if(j != 0) 1059 return j; 1060 } 1061 return Length.CompareTo(other.Length); 1062 } 1063 } 1064 1065 /// <summary> 1066 /// Returns true if this list and another list are equal. 1067 /// </summary> 1068 /// <remarks>Two lists are equal if their length and bytes are equal.</remarks> 1069 /// <param name="other">The list to compare for equality.</param> 1070 /// <returns>True if the two lists are equal.</returns> 1071 public bool Equals(FixedList64Bytes<T> other) 1072 { 1073 return CompareTo(other) == 0; 1074 } 1075 1076 1077 /// <summary> 1078 /// Initializes and returns an instance of FixedList32Bytes with content copied from another list. 1079 /// </summary> 1080 /// <param name="other">The list to copy.</param> 1081 /// <exception cref="IndexOutOfRangeException">Throws if the other list's length exceeds the capacity of FixedList32Bytes&lt;T&gt;.</exception> 1082 public FixedList32Bytes(in FixedList64Bytes<T> other) 1083 { 1084 this = default; 1085 var error = Initialize(other); 1086 if(error != 0) 1087 FixedList.CheckResize<FixedBytes32Align8,T>(other.Length); 1088 } 1089 1090 /// <summary> 1091 /// Initializes an instance of FixedList32Bytes with content copied from another list. 1092 /// </summary> 1093 /// <param name="other">The list to copy.</param> 1094 /// <returns>zero on success, or non-zero on error.</returns> 1095 internal int Initialize(in FixedList64Bytes<T> other) 1096 { 1097 if(other.Length > Capacity) 1098 return (int)CopyError.Truncation; 1099 length = other.length; 1100 unsafe 1101 { 1102 UnsafeUtility.MemCpy(Buffer, other.Buffer, LengthInBytes); 1103 } 1104 return 0; 1105 } 1106 1107 /// <summary> 1108 /// Returns a new list that is a copy of another list. 1109 /// </summary> 1110 /// <param name="other">The list to copy.</param> 1111 /// <returns>A new list that is a copy of the other.</returns> 1112 /// <exception cref="IndexOutOfRangeException">Throws if the other list's length exceeds the capacity of FixedList32Bytes&lt;T&gt;.</exception> 1113 public static implicit operator FixedList32Bytes<T>(in FixedList64Bytes<T> other) 1114 { 1115 return new FixedList32Bytes<T>(other); 1116 } 1117 1118 /// <summary> 1119 /// Returns true if two lists are equal. 1120 /// </summary> 1121 /// <remarks>Two lists are equal if their length and bytes are equal.</remarks> 1122 /// <param name="a">The first list to compare for equality.</param> 1123 /// <param name="b">The second list to compare for equality.</param> 1124 /// <returns>True if the two lists are equal.</returns> 1125 public static bool operator ==(in FixedList32Bytes<T> a, in FixedList128Bytes<T> b) 1126 { 1127 unsafe 1128 { 1129 if(a.length != b.length) 1130 return false; 1131 return UnsafeUtility.MemCmp(a.Buffer, b.Buffer, a.LengthInBytes) == 0; 1132 } 1133 } 1134 1135 /// <summary> 1136 /// Returns true if two lists are unequal. 1137 /// </summary> 1138 /// <remarks>Two lists are equal if their length and bytes are equal.</remarks> 1139 /// <param name="a">The first list to compare for inequality.</param> 1140 /// <param name="b">The second list to compare for inequality.</param> 1141 /// <returns>True if the two lists are unequal.</returns> 1142 public static bool operator !=(in FixedList32Bytes<T> a, in FixedList128Bytes<T> b) 1143 { 1144 return !(a == b); 1145 } 1146 1147 /// <summary> 1148 /// Returns a number denoting whether this list should be placed before or after another list in a sort. 1149 /// </summary> 1150 /// <param name="other">A list to to compare with.</param> 1151 /// <returns>An integer denoting the respective sort position of the list relative to the other: 1152 /// 1153 /// 0 denotes that both lists should have the same position in a sort. 1154 /// -1 denotes that this list should precede the other list in a sort. 1155 /// +1 denotes that this list should follow the other list in a sort. 1156 /// </returns> 1157 public int CompareTo(FixedList128Bytes<T> other) 1158 { 1159 unsafe 1160 { 1161 byte* a = buffer; 1162 byte* b = other.buffer; 1163 var aa = a + FixedList.PaddingBytes<T>(); 1164 var bb = b + FixedList.PaddingBytes<T>(); 1165 var mini = math.min(Length, other.Length); 1166 for(var i = 0; i < mini; ++i) 1167 { 1168 var j = UnsafeUtility.MemCmp(aa + sizeof(T) * i, bb + sizeof(T) * i, sizeof(T)); 1169 if(j != 0) 1170 return j; 1171 } 1172 return Length.CompareTo(other.Length); 1173 } 1174 } 1175 1176 /// <summary> 1177 /// Returns true if this list and another list are equal. 1178 /// </summary> 1179 /// <remarks>Two lists are equal if their length and bytes are equal.</remarks> 1180 /// <param name="other">The list to compare for equality.</param> 1181 /// <returns>True if the two lists are equal.</returns> 1182 public bool Equals(FixedList128Bytes<T> other) 1183 { 1184 return CompareTo(other) == 0; 1185 } 1186 1187 1188 /// <summary> 1189 /// Initializes and returns an instance of FixedList32Bytes with content copied from another list. 1190 /// </summary> 1191 /// <param name="other">The list to copy.</param> 1192 /// <exception cref="IndexOutOfRangeException">Throws if the other list's length exceeds the capacity of FixedList32Bytes&lt;T&gt;.</exception> 1193 public FixedList32Bytes(in FixedList128Bytes<T> other) 1194 { 1195 this = default; 1196 var error = Initialize(other); 1197 if(error != 0) 1198 FixedList.CheckResize<FixedBytes32Align8,T>(other.Length); 1199 } 1200 1201 /// <summary> 1202 /// Initializes an instance of FixedList32Bytes with content copied from another list. 1203 /// </summary> 1204 /// <param name="other">The list to copy.</param> 1205 /// <returns>zero on success, or non-zero on error.</returns> 1206 internal int Initialize(in FixedList128Bytes<T> other) 1207 { 1208 if(other.Length > Capacity) 1209 return (int)CopyError.Truncation; 1210 length = other.length; 1211 unsafe 1212 { 1213 UnsafeUtility.MemCpy(Buffer, other.Buffer, LengthInBytes); 1214 } 1215 return 0; 1216 } 1217 1218 /// <summary> 1219 /// Returns a new list that is a copy of another list. 1220 /// </summary> 1221 /// <param name="other">The list to copy.</param> 1222 /// <returns>A new list that is a copy of the other.</returns> 1223 /// <exception cref="IndexOutOfRangeException">Throws if the other list's length exceeds the capacity of FixedList32Bytes&lt;T&gt;.</exception> 1224 public static implicit operator FixedList32Bytes<T>(in FixedList128Bytes<T> other) 1225 { 1226 return new FixedList32Bytes<T>(other); 1227 } 1228 1229 /// <summary> 1230 /// Returns true if two lists are equal. 1231 /// </summary> 1232 /// <remarks>Two lists are equal if their length and bytes are equal.</remarks> 1233 /// <param name="a">The first list to compare for equality.</param> 1234 /// <param name="b">The second list to compare for equality.</param> 1235 /// <returns>True if the two lists are equal.</returns> 1236 public static bool operator ==(in FixedList32Bytes<T> a, in FixedList512Bytes<T> b) 1237 { 1238 unsafe 1239 { 1240 if(a.length != b.length) 1241 return false; 1242 return UnsafeUtility.MemCmp(a.Buffer, b.Buffer, a.LengthInBytes) == 0; 1243 } 1244 } 1245 1246 /// <summary> 1247 /// Returns true if two lists are unequal. 1248 /// </summary> 1249 /// <remarks>Two lists are equal if their length and bytes are equal.</remarks> 1250 /// <param name="a">The first list to compare for inequality.</param> 1251 /// <param name="b">The second list to compare for inequality.</param> 1252 /// <returns>True if the two lists are unequal.</returns> 1253 public static bool operator !=(in FixedList32Bytes<T> a, in FixedList512Bytes<T> b) 1254 { 1255 return !(a == b); 1256 } 1257 1258 /// <summary> 1259 /// Returns a number denoting whether this list should be placed before or after another list in a sort. 1260 /// </summary> 1261 /// <param name="other">A list to to compare with.</param> 1262 /// <returns>An integer denoting the respective sort position of the list relative to the other: 1263 /// 1264 /// 0 denotes that both lists should have the same position in a sort. 1265 /// -1 denotes that this list should precede the other list in a sort. 1266 /// +1 denotes that this list should follow the other list in a sort. 1267 /// </returns> 1268 public int CompareTo(FixedList512Bytes<T> other) 1269 { 1270 unsafe 1271 { 1272 byte* a = buffer; 1273 byte* b = other.buffer; 1274 var aa = a + FixedList.PaddingBytes<T>(); 1275 var bb = b + FixedList.PaddingBytes<T>(); 1276 var mini = math.min(Length, other.Length); 1277 for(var i = 0; i < mini; ++i) 1278 { 1279 var j = UnsafeUtility.MemCmp(aa + sizeof(T) * i, bb + sizeof(T) * i, sizeof(T)); 1280 if(j != 0) 1281 return j; 1282 } 1283 return Length.CompareTo(other.Length); 1284 } 1285 } 1286 1287 /// <summary> 1288 /// Returns true if this list and another list are equal. 1289 /// </summary> 1290 /// <remarks>Two lists are equal if their length and bytes are equal.</remarks> 1291 /// <param name="other">The list to compare for equality.</param> 1292 /// <returns>True if the two lists are equal.</returns> 1293 public bool Equals(FixedList512Bytes<T> other) 1294 { 1295 return CompareTo(other) == 0; 1296 } 1297 1298 1299 /// <summary> 1300 /// Initializes and returns an instance of FixedList32Bytes with content copied from another list. 1301 /// </summary> 1302 /// <param name="other">The list to copy.</param> 1303 /// <exception cref="IndexOutOfRangeException">Throws if the other list's length exceeds the capacity of FixedList32Bytes&lt;T&gt;.</exception> 1304 public FixedList32Bytes(in FixedList512Bytes<T> other) 1305 { 1306 this = default; 1307 var error = Initialize(other); 1308 if(error != 0) 1309 FixedList.CheckResize<FixedBytes32Align8,T>(other.Length); 1310 } 1311 1312 /// <summary> 1313 /// Initializes an instance of FixedList32Bytes with content copied from another list. 1314 /// </summary> 1315 /// <param name="other">The list to copy.</param> 1316 /// <returns>zero on success, or non-zero on error.</returns> 1317 internal int Initialize(in FixedList512Bytes<T> other) 1318 { 1319 if(other.Length > Capacity) 1320 return (int)CopyError.Truncation; 1321 length = other.length; 1322 unsafe 1323 { 1324 UnsafeUtility.MemCpy(Buffer, other.Buffer, LengthInBytes); 1325 } 1326 return 0; 1327 } 1328 1329 /// <summary> 1330 /// Returns a new list that is a copy of another list. 1331 /// </summary> 1332 /// <param name="other">The list to copy.</param> 1333 /// <returns>A new list that is a copy of the other.</returns> 1334 /// <exception cref="IndexOutOfRangeException">Throws if the other list's length exceeds the capacity of FixedList32Bytes&lt;T&gt;.</exception> 1335 public static implicit operator FixedList32Bytes<T>(in FixedList512Bytes<T> other) 1336 { 1337 return new FixedList32Bytes<T>(other); 1338 } 1339 1340 /// <summary> 1341 /// Returns true if two lists are equal. 1342 /// </summary> 1343 /// <remarks>Two lists are equal if their length and bytes are equal.</remarks> 1344 /// <param name="a">The first list to compare for equality.</param> 1345 /// <param name="b">The second list to compare for equality.</param> 1346 /// <returns>True if the two lists are equal.</returns> 1347 public static bool operator ==(in FixedList32Bytes<T> a, in FixedList4096Bytes<T> b) 1348 { 1349 unsafe 1350 { 1351 if(a.length != b.length) 1352 return false; 1353 return UnsafeUtility.MemCmp(a.Buffer, b.Buffer, a.LengthInBytes) == 0; 1354 } 1355 } 1356 1357 /// <summary> 1358 /// Returns true if two lists are unequal. 1359 /// </summary> 1360 /// <remarks>Two lists are equal if their length and bytes are equal.</remarks> 1361 /// <param name="a">The first list to compare for inequality.</param> 1362 /// <param name="b">The second list to compare for inequality.</param> 1363 /// <returns>True if the two lists are unequal.</returns> 1364 public static bool operator !=(in FixedList32Bytes<T> a, in FixedList4096Bytes<T> b) 1365 { 1366 return !(a == b); 1367 } 1368 1369 /// <summary> 1370 /// Returns a number denoting whether this list should be placed before or after another list in a sort. 1371 /// </summary> 1372 /// <param name="other">A list to to compare with.</param> 1373 /// <returns>An integer denoting the respective sort position of the list relative to the other: 1374 /// 1375 /// 0 denotes that both lists should have the same position in a sort. 1376 /// -1 denotes that this list should precede the other list in a sort. 1377 /// +1 denotes that this list should follow the other list in a sort. 1378 /// </returns> 1379 public int CompareTo(FixedList4096Bytes<T> other) 1380 { 1381 unsafe 1382 { 1383 byte* a = buffer; 1384 byte* b = other.buffer; 1385 var aa = a + FixedList.PaddingBytes<T>(); 1386 var bb = b + FixedList.PaddingBytes<T>(); 1387 var mini = math.min(Length, other.Length); 1388 for(var i = 0; i < mini; ++i) 1389 { 1390 var j = UnsafeUtility.MemCmp(aa + sizeof(T) * i, bb + sizeof(T) * i, sizeof(T)); 1391 if(j != 0) 1392 return j; 1393 } 1394 return Length.CompareTo(other.Length); 1395 } 1396 } 1397 1398 /// <summary> 1399 /// Returns true if this list and another list are equal. 1400 /// </summary> 1401 /// <remarks>Two lists are equal if their length and bytes are equal.</remarks> 1402 /// <param name="other">The list to compare for equality.</param> 1403 /// <returns>True if the two lists are equal.</returns> 1404 public bool Equals(FixedList4096Bytes<T> other) 1405 { 1406 return CompareTo(other) == 0; 1407 } 1408 1409 1410 /// <summary> 1411 /// Initializes and returns an instance of FixedList32Bytes with content copied from another list. 1412 /// </summary> 1413 /// <param name="other">The list to copy.</param> 1414 /// <exception cref="IndexOutOfRangeException">Throws if the other list's length exceeds the capacity of FixedList32Bytes&lt;T&gt;.</exception> 1415 public FixedList32Bytes(in FixedList4096Bytes<T> other) 1416 { 1417 this = default; 1418 var error = Initialize(other); 1419 if(error != 0) 1420 FixedList.CheckResize<FixedBytes32Align8,T>(other.Length); 1421 } 1422 1423 /// <summary> 1424 /// Initializes an instance of FixedList32Bytes with content copied from another list. 1425 /// </summary> 1426 /// <param name="other">The list to copy.</param> 1427 /// <returns>zero on success, or non-zero on error.</returns> 1428 internal int Initialize(in FixedList4096Bytes<T> other) 1429 { 1430 if(other.Length > Capacity) 1431 return (int)CopyError.Truncation; 1432 length = other.length; 1433 unsafe 1434 { 1435 UnsafeUtility.MemCpy(Buffer, other.Buffer, LengthInBytes); 1436 } 1437 return 0; 1438 } 1439 1440 /// <summary> 1441 /// Returns a new list that is a copy of another list. 1442 /// </summary> 1443 /// <param name="other">The list to copy.</param> 1444 /// <returns>A new list that is a copy of the other.</returns> 1445 /// <exception cref="IndexOutOfRangeException">Throws if the other list's length exceeds the capacity of FixedList32Bytes&lt;T&gt;.</exception> 1446 public static implicit operator FixedList32Bytes<T>(in FixedList4096Bytes<T> other) 1447 { 1448 return new FixedList32Bytes<T>(other); 1449 } 1450 1451 /// <summary> 1452 /// Returns true if the list is equal to an object. 1453 /// </summary> 1454 /// <remarks>Two lists are equal if their length and bytes are equal. 1455 /// 1456 /// A FixedList*N*&lt;T&gt; can only be equal to another FixedList*N*&lt;T&gt; with the same *N* and T. 1457 /// </remarks> 1458 /// <param name="obj">An object to compare for equality.</param> 1459 /// <returns>True if the list is equal to the object.</returns> 1460 [ExcludeFromBurstCompatTesting("Takes managed object")] 1461 public override bool Equals(object obj) 1462 { 1463 if(obj is FixedList32Bytes<T> aFixedList32Bytes) return Equals(aFixedList32Bytes); 1464 if(obj is FixedList64Bytes<T> aFixedList64Bytes) return Equals(aFixedList64Bytes); 1465 if(obj is FixedList128Bytes<T> aFixedList128Bytes) return Equals(aFixedList128Bytes); 1466 if(obj is FixedList512Bytes<T> aFixedList512Bytes) return Equals(aFixedList512Bytes); 1467 if(obj is FixedList4096Bytes<T> aFixedList4096Bytes) return Equals(aFixedList4096Bytes); 1468 return false; 1469 } 1470 1471 /// <summary> 1472 /// An enumerator over the elements of a FixedList32Bytes&lt;T&gt;. 1473 /// </summary> 1474 /// <remarks> 1475 /// In an enumerator's initial state, `Current` cannot be read. The first <see cref="MoveNext"/> call advances the enumerator to the first element. 1476 /// </remarks> 1477 public struct Enumerator : IEnumerator<T> 1478 { 1479 FixedList32Bytes<T> m_List; 1480 int m_Index; 1481 1482 /// <summary> 1483 /// Initializes and returns an instance of FixedList32Bytes&lt;T&gt;. 1484 /// </summary> 1485 /// <param name="list">The list for which to create an enumerator.</param> 1486 public Enumerator(ref FixedList32Bytes<T> list) 1487 { 1488 m_List = list; 1489 m_Index = -1; 1490 } 1491 1492 /// <summary> 1493 /// Does nothing. 1494 /// </summary> 1495 public void Dispose() 1496 { 1497 } 1498 1499 /// <summary> 1500 /// Advances the enumerator to the next element. 1501 /// </summary> 1502 /// <returns>True if <see cref="Current"/> is valid to read after the call.</returns> 1503 [MethodImpl(MethodImplOptions.AggressiveInlining)] 1504 public bool MoveNext() 1505 { 1506 m_Index++; 1507 return m_Index < m_List.Length; 1508 } 1509 1510 /// <summary> 1511 /// Resets the enumerator to its initial state. 1512 /// </summary> 1513 public void Reset() 1514 { 1515 m_Index = -1; 1516 } 1517 1518 /// <summary> 1519 /// The current element. 1520 /// </summary> 1521 /// <value>The current element.</value> 1522 public T Current 1523 { 1524 [MethodImpl(MethodImplOptions.AggressiveInlining)] 1525 get => m_List[m_Index]; // Let FixedList32Bytes<T> indexer check for out of range. 1526 } 1527 1528 object IEnumerator.Current => Current; 1529 } 1530 1531 /// <summary> 1532 /// Returns an enumerator for iterating over the elements of this list. 1533 /// </summary> 1534 /// <returns>An enumerator for iterating over the elements of this list.</returns> 1535 public Enumerator GetEnumerator() 1536 { 1537 return new Enumerator(ref this); 1538 } 1539 1540 /// <summary> 1541 /// This method is not implemented. Use <see cref="GetEnumerator"/> instead. 1542 /// </summary> 1543 /// <returns>Nothing because it always throws <see cref="NotImplementedException"/>.</returns> 1544 /// <exception cref="NotImplementedException">Method is not implemented.</exception> 1545 IEnumerator IEnumerable.GetEnumerator() 1546 { 1547 throw new NotImplementedException(); 1548 } 1549 1550 /// <summary> 1551 /// This method is not implemented. Use <see cref="GetEnumerator"/> instead. 1552 /// </summary> 1553 /// <returns>Nothing because it always throws <see cref="NotImplementedException"/>.</returns> 1554 /// <exception cref="NotImplementedException">Method is not implemented.</exception> 1555 IEnumerator<T> IEnumerable<T>.GetEnumerator() 1556 { 1557 throw new NotImplementedException(); 1558 } 1559 } 1560 1561 /// <summary> 1562 /// Provides extension methods for FixedList32Bytes. 1563 /// </summary> 1564 [GenerateTestsForBurstCompatibility] 1565 public unsafe static class FixedList32BytesExtensions 1566 { 1567 /// <summary> 1568 /// Finds the index of the first occurrence of a particular value in this list. 1569 /// </summary> 1570 /// <typeparam name="T">The type of elements in this list.</typeparam> 1571 /// <typeparam name="U">The value type.</typeparam> 1572 /// <param name="list">The list to search.</param> 1573 /// <param name="value">The value to locate.</param> 1574 /// <returns>The index of the first occurrence of the value. Returns -1 if no occurrence is found.</returns> 1575 [GenerateTestsForBurstCompatibility(GenericTypeArguments = new [] { typeof(int), typeof(int) })] 1576 public static int IndexOf<T, U>(this ref FixedList32Bytes<T> list, U value) where T : unmanaged, IEquatable<U> 1577 { 1578 return NativeArrayExtensions.IndexOf<T, U>(list.Buffer, list.Length, value); 1579 } 1580 1581 /// <summary> 1582 /// Returns true if a particular value is present in this list. 1583 /// </summary> 1584 /// <typeparam name="T">The type of elements in this list.</typeparam> 1585 /// <typeparam name="U">The value type.</typeparam> 1586 /// <param name="list">The list to search.</param> 1587 /// <param name="value">The value to locate.</param> 1588 /// <returns>True if the value is present in this list.</returns> 1589 [GenerateTestsForBurstCompatibility(GenericTypeArguments = new [] { typeof(int), typeof(int) })] 1590 public static bool Contains<T, U>(this ref FixedList32Bytes<T> list, U value) where T : unmanaged, IEquatable<U> 1591 { 1592 return list.IndexOf(value) != -1; 1593 } 1594 1595 /// <summary> 1596 /// Removes the first occurrence of a particular value in this list. 1597 /// </summary> 1598 /// <remarks> 1599 /// If a value is removed, all elements after it are shifted down by one, and the list's length is decremented by one. 1600 /// 1601 /// If you don't need to preserve the order of the remaining elements, <see cref="Unity.Collections.FixedList32BytesExtensions.RemoveSwapBack{T, U}"/> is a cheaper alternative. 1602 /// </remarks> 1603 /// <typeparam name="T">The type of elements in this list.</typeparam> 1604 /// <typeparam name="U">The value type.</typeparam> 1605 /// <param name="list">The list to search.</param> 1606 /// <param name="value">The value to locate and remove.</param> 1607 /// <returns>True if the value was found and removed.</returns> 1608 [GenerateTestsForBurstCompatibility(GenericTypeArguments = new [] { typeof(int), typeof(int) })] 1609 public static bool Remove<T, U>(this ref FixedList32Bytes<T> list, U value) where T : unmanaged, IEquatable<U> 1610 { 1611 int index = list.IndexOf(value); 1612 if (index < 0) 1613 { 1614 return false; 1615 } 1616 1617 list.RemoveAt(index); 1618 1619 return true; 1620 } 1621 1622 /// <summary> 1623 /// Removes the first occurrence of a particular value in this list. 1624 /// </summary> 1625 /// <remarks> 1626 /// 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. 1627 /// 1628 /// This is cheaper than <see cref="Remove"/>, but the order of the remaining elements is not preserved. 1629 /// </remarks> 1630 /// <typeparam name="T">The type of elements in this list.</typeparam> 1631 /// <typeparam name="U">The value type.</typeparam> 1632 /// <param name="list">The list to search.</param> 1633 /// <param name="value">The value to locate and remove.</param> 1634 /// <returns>Returns true if the item is removed.</returns> 1635 [GenerateTestsForBurstCompatibility(GenericTypeArguments = new [] { typeof(int), typeof(int) })] 1636 public static bool RemoveSwapBack<T, U>(this ref FixedList32Bytes<T> list, U value) where T : unmanaged, IEquatable<U> 1637 { 1638 var index = list.IndexOf(value); 1639 if (index == -1) 1640 { 1641 return false; 1642 } 1643 1644 list.RemoveAtSwapBack(index); 1645 1646 return true; 1647 } 1648 } 1649 1650 sealed class FixedList32BytesDebugView<T> where T : unmanaged 1651 { 1652 FixedList32Bytes<T> m_List; 1653 public FixedList32BytesDebugView(FixedList32Bytes<T> list) 1654 { 1655 m_List = list; 1656 } 1657 public T[] Items => m_List.ToArray(); 1658 } 1659 /// <summary> 1660 /// An unmanaged, resizable list whose content is all stored directly in the 64-byte struct. Useful for small lists. 1661 /// </summary> 1662 /// <typeparam name="T">The type of the elements.</typeparam> 1663 [Serializable] 1664 [DebuggerTypeProxy(typeof(FixedList64BytesDebugView<>))] 1665 [GenerateTestsForBurstCompatibility(GenericTypeArguments = new [] { typeof(int) })] 1666 public struct FixedList64Bytes<T> 1667 : INativeList<T> 1668 , IEnumerable<T> // Used by collection initializers. 1669 , IEquatable<FixedList32Bytes<T>> 1670 , IComparable<FixedList32Bytes<T>> 1671 , IEquatable<FixedList64Bytes<T>> 1672 , IComparable<FixedList64Bytes<T>> 1673 , IEquatable<FixedList128Bytes<T>> 1674 , IComparable<FixedList128Bytes<T>> 1675 , IEquatable<FixedList512Bytes<T>> 1676 , IComparable<FixedList512Bytes<T>> 1677 , IEquatable<FixedList4096Bytes<T>> 1678 , IComparable<FixedList4096Bytes<T>> 1679 where T : unmanaged 1680 { 1681 [SerializeField] internal FixedBytes64Align8 data; 1682 1683 internal ushort length 1684 { 1685 [MethodImpl(MethodImplOptions.AggressiveInlining)] 1686 readonly get 1687 { 1688 unsafe 1689 { 1690 fixed(void* ptr = &data) 1691 return *((ushort*)ptr); 1692 } 1693 } 1694 1695 [MethodImpl(MethodImplOptions.AggressiveInlining)] 1696 set 1697 { 1698 unsafe 1699 { 1700 fixed (void* ptr = &data) 1701 *((ushort*)ptr) = value; 1702 } 1703 } 1704 } 1705 1706 internal readonly unsafe byte* buffer 1707 { 1708 [MethodImpl(MethodImplOptions.AggressiveInlining)] 1709 get 1710 { 1711 unsafe 1712 { 1713 fixed (void* ptr = &data) 1714 return ((byte*)ptr) + UnsafeUtility.SizeOf<ushort>(); 1715 } 1716 } 1717 } 1718 1719 /// <summary> 1720 /// The current number of items in this list. 1721 /// </summary> 1722 /// <value>The current number of items in this list.</value> 1723 [CreateProperty] 1724 public int Length 1725 { 1726 [MethodImpl(MethodImplOptions.AggressiveInlining)] 1727 readonly get => length; 1728 set 1729 { 1730 FixedList.CheckResize<FixedBytes64Align8,T>(value); 1731 length = (ushort)value; 1732 } 1733 } 1734 1735 /// <summary> 1736 /// A property in order to display items in the Entity Inspector. 1737 /// </summary> 1738 [CreateProperty] IEnumerable<T> Elements => this.ToArray(); 1739 1740 /// <summary> 1741 /// Whether this list is empty. 1742 /// </summary> 1743 /// <value>True if this string has no characters or if the container has not been constructed.</value> 1744 public readonly bool IsEmpty 1745 { 1746 [MethodImpl(MethodImplOptions.AggressiveInlining)] 1747 get => Length == 0; 1748 } 1749 1750 internal int LengthInBytes => Length * UnsafeUtility.SizeOf<T>(); 1751 1752 /// <summary> 1753 /// Returns a pointer to the first element of the list buffer. 1754 /// </summary> 1755 /// <remarks> 1756 /// The pointer returned by this method points into the internals of the target list object. It is the 1757 /// caller's responsibility to ensure that the pointer is not used after the list is destroyed or goes 1758 /// out of scope. 1759 /// </remarks> 1760 /// <returns>A pointer to the first element of the list buffer.</returns> 1761 internal readonly unsafe byte* Buffer 1762 { 1763 [MethodImpl(MethodImplOptions.AggressiveInlining)] 1764 get 1765 { 1766 return buffer + FixedList.PaddingBytes<T>(); 1767 } 1768 } 1769 1770 /// <summary> 1771 /// The number of elements that can fit in this list. 1772 /// </summary> 1773 /// <value>The number of elements that can fit in this list.</value> 1774 /// <remarks>The capacity of a FixedList cannot be changed. The setter is included only for conformity with <see cref="INativeList{T}"/>.</remarks> 1775 /// <exception cref="ArgumentOutOfRangeException">Thrown if the new value does not match the current capacity.</exception> 1776 public int Capacity 1777 { 1778 [MethodImpl(MethodImplOptions.AggressiveInlining)] 1779 readonly get 1780 { 1781 return FixedList.Capacity<FixedBytes64Align8,T>(); 1782 } 1783 1784 set 1785 { 1786 CollectionHelper.CheckCapacityInRange(value, Length); 1787 } 1788 } 1789 1790 /// <summary> 1791 /// The element at a given index. 1792 /// </summary> 1793 /// <param name="index">An index.</param> 1794 /// <value>The value to store at the index.</value> 1795 /// <exception cref="IndexOutOfRangeException">Thrown if the index is out of bounds.</exception> 1796 public T this[int index] 1797 { 1798 [MethodImpl(MethodImplOptions.AggressiveInlining)] 1799 readonly get 1800 { 1801 CollectionHelper.CheckIndexInRange(index, length); 1802 unsafe 1803 { 1804 return UnsafeUtility.ReadArrayElement<T>(Buffer, CollectionHelper.AssumePositive(index)); 1805 } 1806 } 1807 1808 [MethodImpl(MethodImplOptions.AggressiveInlining)] 1809 set 1810 { 1811 CollectionHelper.CheckIndexInRange(index, length); 1812 unsafe 1813 { 1814 UnsafeUtility.WriteArrayElement<T>(Buffer, CollectionHelper.AssumePositive(index), value); 1815 } 1816 } 1817 } 1818 1819 /// <summary> 1820 /// Returns the element at a given index. 1821 /// </summary> 1822 /// <param name="index">An index.</param> 1823 /// <returns>The list element at the index.</returns> 1824 [MethodImpl(MethodImplOptions.AggressiveInlining)] 1825 public ref T ElementAt(int index) 1826 { 1827 CollectionHelper.CheckIndexInRange(index, length); 1828 unsafe 1829 { 1830 return ref UnsafeUtility.ArrayElementAsRef<T>(Buffer, index); 1831 } 1832 } 1833 1834 /// <summary> 1835 /// Returns the hash code of this list. 1836 /// </summary> 1837 /// <remarks> 1838 /// 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> 1839 /// <returns>The hash code of this list.</returns> 1840 public override int GetHashCode() 1841 { 1842 unsafe 1843 { 1844 return (int)CollectionHelper.Hash(Buffer, LengthInBytes); 1845 } 1846 } 1847 1848 /// <summary> 1849 /// Appends an element to the end of this list. Increments the length by 1. 1850 /// </summary> 1851 /// <remarks> 1852 /// The same as <see cref="AddNoResize"/>. Included only for consistency with the other list types. 1853 /// If the element exceeds the capacity, throws cref="IndexOutOfRangeException", and the list is unchanged. 1854 /// </remarks> 1855 /// <param name="item">The element to append at the end of the list.</param> 1856 /// <exception cref="IndexOutOfRangeException">Thrown if the append exceeds the capacity.</exception> 1857 public void Add(in T item) => AddNoResize(in item); 1858 1859 /// <summary> 1860 /// Appends elements from a buffer to the end of this list. Increments the length by the number of appended elements. 1861 /// </summary> 1862 /// <remarks> 1863 /// The same as <see cref="AddRangeNoResize"/>. Included only for consistency with the other list types. 1864 /// If the elements exceeds the capacity, throws cref="IndexOutOfRangeException", and the list is unchanged. 1865 /// </remarks> 1866 /// <param name="ptr">A buffer.</param> 1867 /// <param name="length">The number of elements from the buffer to append.</param> 1868 /// <exception cref="IndexOutOfRangeException">Thrown if the append exceeds the capacity.</exception> 1869 public unsafe void AddRange(void* ptr, int length) => AddRangeNoResize(ptr, length); 1870 1871 /// <summary> 1872 /// Appends an element to the end of this list. Increments the length by 1. 1873 /// </summary> 1874 /// <remarks> 1875 /// If the element exceeds the capacity, throws cref="IndexOutOfRangeException", and the list is unchanged. 1876 /// </remarks> 1877 /// <param name="item">The element to append at the end of the list.</param> 1878 /// <exception cref="IndexOutOfRangeException">Thrown if the append exceeds the capacity.</exception> 1879 [MethodImpl(MethodImplOptions.AggressiveInlining)] 1880 public void AddNoResize(in T item) 1881 { 1882 this[Length++] = item; 1883 } 1884 1885 /// <summary> 1886 /// Appends elements from a buffer to the end of this list. Increments the length by the number of appended elements. 1887 /// </summary> 1888 /// <remarks> 1889 /// If the elements exceeds the capacity, throws cref="IndexOutOfRangeException", and the list is unchanged. 1890 /// </remarks> 1891 /// <param name="ptr">A buffer.</param> 1892 /// <param name="length">The number of elements from the buffer to append.</param> 1893 /// <exception cref="IndexOutOfRangeException">Thrown if the append exceeds the capacity.</exception> 1894 public unsafe void AddRangeNoResize(void* ptr, int length) 1895 { 1896 var idx = Length; 1897 Length += length; 1898 UnsafeUtility.MemCpy((T*)Buffer + idx, ptr, UnsafeUtility.SizeOf<T>() * length); 1899 } 1900 1901 /// <summary> 1902 /// Appends value count times to the end of this list. 1903 /// </summary> 1904 /// <param name="value">The value to add to the end of this list.</param> 1905 /// <param name="count">The number of times to replicate the value.</param> 1906 /// <exception cref="IndexOutOfRangeException">Thrown if the append exceeds the capacity.</exception> 1907 public unsafe void AddReplicate(in T value, int count) 1908 { 1909 var idx = Length; 1910 Length += count; 1911 fixed (T* ptr = &value) 1912 UnsafeUtility.MemCpyReplicate((T*)Buffer + idx, ptr, UnsafeUtility.SizeOf<T>(), count); 1913 } 1914 1915 /// <summary> 1916 /// Sets the length to 0. 1917 /// </summary> 1918 /// <remarks> Does *not* zero out the bytes.</remarks> 1919 public void Clear() 1920 { 1921 Length = 0; 1922 } 1923 1924 /// <summary> 1925 /// Shifts elements toward the end of this list, increasing its length. 1926 /// </summary> 1927 /// <remarks> 1928 /// Right-shifts elements in the list so as to create 'free' slots at the beginning or in the middle. 1929 /// 1930 /// The length is increased by `end - begin`. 1931 /// 1932 /// If `end` equals `begin`, the method does nothing. 1933 /// 1934 /// 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. 1935 /// 1936 /// The indexes `begin` up to `end` are not cleared: they will contain whatever values they held prior. 1937 /// </remarks> 1938 /// <param name="begin">The index of the first element that will be shifted up.</param> 1939 /// <param name="end">The index where the first shifted element will end up.</param> 1940 /// <exception cref="IndexOutOfRangeException">Thrown if the new length exceeds the capacity.</exception> 1941 public void InsertRangeWithBeginEnd(int begin, int end) 1942 { 1943 int items = end - begin; 1944 if(items < 1) 1945 return; 1946 int itemsToCopy = length - begin; 1947 Length += items; 1948 if(itemsToCopy < 1) 1949 return; 1950 int bytesToCopy = itemsToCopy * UnsafeUtility.SizeOf<T>(); 1951 unsafe 1952 { 1953 byte *b = Buffer; 1954 byte *dest = b + end * UnsafeUtility.SizeOf<T>(); 1955 byte *src = b + begin * UnsafeUtility.SizeOf<T>(); 1956 UnsafeUtility.MemMove(dest, src, bytesToCopy); 1957 } 1958 } 1959 1960 /// <summary> 1961 /// Shifts elements toward the end of this list, increasing its length. 1962 /// </summary> 1963 /// <remarks> 1964 /// Right-shifts elements in the list so as to create 'free' slots at the beginning or in the middle. 1965 /// 1966 /// The length is increased by `count`. If necessary, the capacity will be increased accordingly. 1967 /// 1968 /// If `count` equals `0`, the method does nothing. 1969 /// 1970 /// 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. 1971 /// 1972 /// The indexes `index` up to `index + count` are not cleared: they will contain whatever values they held prior. 1973 /// </remarks> 1974 /// <param name="index">The index of the first element that will be shifted up.</param> 1975 /// <param name="count">The number of elements to insert.</param> 1976 /// <exception cref="ArgumentException">Thrown if `count` is negative.</exception> 1977 /// <exception cref="ArgumentOutOfRangeException">Thrown if `index` is out of bounds.</exception> 1978 public void InsertRange(int index, int count) => InsertRangeWithBeginEnd(index, index + count); 1979 1980 /// <summary> 1981 /// Inserts a single element at an index. Increments the length by 1. 1982 /// </summary> 1983 /// <param name="index">The index at which to insert the element.</param> 1984 /// <param name="item">The element to insert.</param> 1985 /// <exception cref="ArgumentOutOfRangeException">Thrown if the index is out of bounds.</exception> 1986 public void Insert(int index, in T item) 1987 { 1988 InsertRangeWithBeginEnd(index, index+1); 1989 this[index] = item; 1990 } 1991 1992 /// <summary> 1993 /// Copies the last element of this list to an index. Decrements the length by 1. 1994 /// </summary> 1995 /// <remarks>Useful as a cheap way to remove elements from a list when you don't care about preserving order.</remarks> 1996 /// <param name="index">The index to overwrite with the last element.</param> 1997 /// <exception cref="ArgumentOutOfRangeException">Thrown if the index is out of bounds.</exception> 1998 public void RemoveAtSwapBack(int index) 1999 { 2000 RemoveRangeSwapBack(index, 1); 2001 } 2002 2003 /// <summary> 2004 /// Copies the last *N* elements of this list to a range in this list. Decrements the length by *N*. 2005 /// </summary> 2006 /// <remarks> 2007 /// Copies the last `count`-numbered elements to the range starting at `index`. 2008 /// 2009 /// Useful as a cheap way to remove elements from a list when you don't care about preserving order. 2010 /// 2011 /// Does nothing if the count is less than 1. 2012 /// </remarks> 2013 /// <param name="index">The first index of the destination range.</param> 2014 /// <param name="count">The number of elements to copy and the amount by which to decrement the length.</param> 2015 /// <exception cref="ArgumentOutOfRangeException">Thrown if the index is out of bounds.</exception> 2016 public void RemoveRangeSwapBack(int index, int count) 2017 { 2018 if (count > 0) 2019 { 2020 int copyFrom = math.max(Length - count, index + count); 2021 2022 unsafe 2023 { 2024 var sizeOf = UnsafeUtility.SizeOf<T>(); 2025 void* dst = Buffer + index * sizeOf; 2026 void* src = Buffer + copyFrom * sizeOf; 2027 UnsafeUtility.MemCpy(dst, src, (Length - copyFrom) * sizeOf); 2028 } 2029 2030 Length -= count; 2031 } 2032 } 2033 2034 /// <summary> 2035 /// Removes the element at an index. Shifts everything above the index down by one and decrements the length by 1. 2036 /// </summary> 2037 /// <param name="index">The index of the element to remove.</param> 2038 /// <remarks> 2039 /// If you don't care about preserving the order of the elements, `RemoveAtSwapBack` is a more efficient way to remove an element. 2040 /// </remarks> 2041 /// <exception cref="ArgumentOutOfRangeException">Thrown if the index is out of bounds.</exception> 2042 public void RemoveAt(int index) 2043 { 2044 RemoveRange(index, 1); 2045 } 2046 2047 /// <summary> 2048 /// Removes *N* elements of a range. Shifts everything above the range down by *N* and decrements the length by *N*. 2049 /// </summary> 2050 /// <remarks> 2051 /// If you don't care about preserving the order of the elements, `RemoveAtSwapBack` is a more efficient way to remove elements. 2052 /// </remarks> 2053 /// <param name="index">The first index of the range to remove.</param> 2054 /// <param name="count">The number of elements to remove.</param> 2055 /// <exception cref="ArgumentOutOfRangeException">Thrown if the index is out of bounds.</exception> 2056 public void RemoveRange(int index, int count) 2057 { 2058 if (count > 0) 2059 { 2060 int copyFrom = math.min(index + count, Length); 2061 2062 unsafe 2063 { 2064 var sizeOf = UnsafeUtility.SizeOf<T>(); 2065 void* dst = Buffer + index * sizeOf; 2066 void* src = Buffer + copyFrom * sizeOf; 2067 UnsafeUtility.MemCpy(dst, src, (Length - copyFrom) * sizeOf); 2068 } 2069 2070 Length -= count; 2071 } 2072 } 2073 2074 /// <summary> 2075 /// Returns a managed array that is a copy of this list. 2076 /// </summary> 2077 /// <returns>A managed array that is a copy of this list.</returns> 2078 [ExcludeFromBurstCompatTesting("Returns managed array")] 2079 public T[] ToArray() 2080 { 2081 var result = new T[Length]; 2082 unsafe 2083 { 2084 byte* s = Buffer; 2085 fixed(T* d = result) 2086 UnsafeUtility.MemCpy(d, s, LengthInBytes); 2087 } 2088 return result; 2089 } 2090 2091 /// <summary> 2092 /// Returns an array that is a copy of this list. 2093 /// </summary> 2094 /// <param name="allocator">The allocator to use.</param> 2095 /// <returns>An array that is a copy of this list.</returns> 2096 public NativeArray<T> ToNativeArray(AllocatorManager.AllocatorHandle allocator) 2097 { 2098 unsafe 2099 { 2100 var copy = CollectionHelper.CreateNativeArray<T>(Length, allocator, NativeArrayOptions.UninitializedMemory); 2101 UnsafeUtility.MemCpy(copy.GetUnsafePtr(), Buffer, LengthInBytes); 2102 return copy; 2103 } 2104 } 2105 2106 2107 /// <summary> 2108 /// Returns true if two lists are equal. 2109 /// </summary> 2110 /// <remarks>Two lists are equal if their length and bytes are equal.</remarks> 2111 /// <param name="a">The first list to compare for equality.</param> 2112 /// <param name="b">The second list to compare for equality.</param> 2113 /// <returns>True if the two lists are equal.</returns> 2114 public static bool operator ==(in FixedList64Bytes<T> a, in FixedList32Bytes<T> b) 2115 { 2116 unsafe 2117 { 2118 if(a.length != b.length) 2119 return false; 2120 return UnsafeUtility.MemCmp(a.Buffer, b.Buffer, a.LengthInBytes) == 0; 2121 } 2122 } 2123 2124 /// <summary> 2125 /// Returns true if two lists are unequal. 2126 /// </summary> 2127 /// <remarks>Two lists are equal if their length and bytes are equal.</remarks> 2128 /// <param name="a">The first list to compare for inequality.</param> 2129 /// <param name="b">The second list to compare for inequality.</param> 2130 /// <returns>True if the two lists are unequal.</returns> 2131 public static bool operator !=(in FixedList64Bytes<T> a, in FixedList32Bytes<T> b) 2132 { 2133 return !(a == b); 2134 } 2135 2136 /// <summary> 2137 /// Returns a number denoting whether this list should be placed before or after another list in a sort. 2138 /// </summary> 2139 /// <param name="other">A list to to compare with.</param> 2140 /// <returns>An integer denoting the respective sort position of the list relative to the other: 2141 /// 2142 /// 0 denotes that both lists should have the same position in a sort. 2143 /// -1 denotes that this list should precede the other list in a sort. 2144 /// +1 denotes that this list should follow the other list in a sort. 2145 /// </returns> 2146 public int CompareTo(FixedList32Bytes<T> other) 2147 { 2148 unsafe 2149 { 2150 byte* a = buffer; 2151 byte* b = other.buffer; 2152 var aa = a + FixedList.PaddingBytes<T>(); 2153 var bb = b + FixedList.PaddingBytes<T>(); 2154 var mini = math.min(Length, other.Length); 2155 for(var i = 0; i < mini; ++i) 2156 { 2157 var j = UnsafeUtility.MemCmp(aa + sizeof(T) * i, bb + sizeof(T) * i, sizeof(T)); 2158 if(j != 0) 2159 return j; 2160 } 2161 return Length.CompareTo(other.Length); 2162 } 2163 } 2164 2165 /// <summary> 2166 /// Returns true if this list and another list are equal. 2167 /// </summary> 2168 /// <remarks>Two lists are equal if their length and bytes are equal.</remarks> 2169 /// <param name="other">The list to compare for equality.</param> 2170 /// <returns>True if the two lists are equal.</returns> 2171 public bool Equals(FixedList32Bytes<T> other) 2172 { 2173 return CompareTo(other) == 0; 2174 } 2175 2176 2177 /// <summary> 2178 /// Initializes and returns an instance of FixedList64Bytes with content copied from another list. 2179 /// </summary> 2180 /// <param name="other">The list to copy.</param> 2181 /// <exception cref="IndexOutOfRangeException">Throws if the other list's length exceeds the capacity of FixedList64Bytes&lt;T&gt;.</exception> 2182 public FixedList64Bytes(in FixedList32Bytes<T> other) 2183 { 2184 this = default; 2185 var error = Initialize(other); 2186 if(error != 0) 2187 FixedList.CheckResize<FixedBytes64Align8,T>(other.Length); 2188 } 2189 2190 /// <summary> 2191 /// Initializes an instance of FixedList64Bytes with content copied from another list. 2192 /// </summary> 2193 /// <param name="other">The list to copy.</param> 2194 /// <returns>zero on success, or non-zero on error.</returns> 2195 internal int Initialize(in FixedList32Bytes<T> other) 2196 { 2197 if(other.Length > Capacity) 2198 return (int)CopyError.Truncation; 2199 length = other.length; 2200 unsafe 2201 { 2202 UnsafeUtility.MemCpy(Buffer, other.Buffer, LengthInBytes); 2203 } 2204 return 0; 2205 } 2206 2207 /// <summary> 2208 /// Returns a new list that is a copy of another list. 2209 /// </summary> 2210 /// <param name="other">The list to copy.</param> 2211 /// <returns>A new list that is a copy of the other.</returns> 2212 /// <exception cref="IndexOutOfRangeException">Throws if the other list's length exceeds the capacity of FixedList64Bytes&lt;T&gt;.</exception> 2213 public static implicit operator FixedList64Bytes<T>(in FixedList32Bytes<T> other) 2214 { 2215 return new FixedList64Bytes<T>(other); 2216 } 2217 2218 /// <summary> 2219 /// Returns true if two lists are equal. 2220 /// </summary> 2221 /// <remarks>Two lists are equal if their length and bytes are equal.</remarks> 2222 /// <param name="a">The first list to compare for equality.</param> 2223 /// <param name="b">The second list to compare for equality.</param> 2224 /// <returns>True if the two lists are equal.</returns> 2225 public static bool operator ==(in FixedList64Bytes<T> a, in FixedList64Bytes<T> b) 2226 { 2227 unsafe 2228 { 2229 if(a.length != b.length) 2230 return false; 2231 return UnsafeUtility.MemCmp(a.Buffer, b.Buffer, a.LengthInBytes) == 0; 2232 } 2233 } 2234 2235 /// <summary> 2236 /// Returns true if two lists are unequal. 2237 /// </summary> 2238 /// <remarks>Two lists are equal if their length and bytes are equal.</remarks> 2239 /// <param name="a">The first list to compare for inequality.</param> 2240 /// <param name="b">The second list to compare for inequality.</param> 2241 /// <returns>True if the two lists are unequal.</returns> 2242 public static bool operator !=(in FixedList64Bytes<T> a, in FixedList64Bytes<T> b) 2243 { 2244 return !(a == b); 2245 } 2246 2247 /// <summary> 2248 /// Returns a number denoting whether this list should be placed before or after another list in a sort. 2249 /// </summary> 2250 /// <param name="other">A list to to compare with.</param> 2251 /// <returns>An integer denoting the respective sort position of the list relative to the other: 2252 /// 2253 /// 0 denotes that both lists should have the same position in a sort. 2254 /// -1 denotes that this list should precede the other list in a sort. 2255 /// +1 denotes that this list should follow the other list in a sort. 2256 /// </returns> 2257 public int CompareTo(FixedList64Bytes<T> other) 2258 { 2259 unsafe 2260 { 2261 byte* a = buffer; 2262 byte* b = other.buffer; 2263 var aa = a + FixedList.PaddingBytes<T>(); 2264 var bb = b + FixedList.PaddingBytes<T>(); 2265 var mini = math.min(Length, other.Length); 2266 for(var i = 0; i < mini; ++i) 2267 { 2268 var j = UnsafeUtility.MemCmp(aa + sizeof(T) * i, bb + sizeof(T) * i, sizeof(T)); 2269 if(j != 0) 2270 return j; 2271 } 2272 return Length.CompareTo(other.Length); 2273 } 2274 } 2275 2276 /// <summary> 2277 /// Returns true if this list and another list are equal. 2278 /// </summary> 2279 /// <remarks>Two lists are equal if their length and bytes are equal.</remarks> 2280 /// <param name="other">The list to compare for equality.</param> 2281 /// <returns>True if the two lists are equal.</returns> 2282 public bool Equals(FixedList64Bytes<T> other) 2283 { 2284 return CompareTo(other) == 0; 2285 } 2286 2287 2288 /// <summary> 2289 /// Returns true if two lists are equal. 2290 /// </summary> 2291 /// <remarks>Two lists are equal if their length and bytes are equal.</remarks> 2292 /// <param name="a">The first list to compare for equality.</param> 2293 /// <param name="b">The second list to compare for equality.</param> 2294 /// <returns>True if the two lists are equal.</returns> 2295 public static bool operator ==(in FixedList64Bytes<T> a, in FixedList128Bytes<T> b) 2296 { 2297 unsafe 2298 { 2299 if(a.length != b.length) 2300 return false; 2301 return UnsafeUtility.MemCmp(a.Buffer, b.Buffer, a.LengthInBytes) == 0; 2302 } 2303 } 2304 2305 /// <summary> 2306 /// Returns true if two lists are unequal. 2307 /// </summary> 2308 /// <remarks>Two lists are equal if their length and bytes are equal.</remarks> 2309 /// <param name="a">The first list to compare for inequality.</param> 2310 /// <param name="b">The second list to compare for inequality.</param> 2311 /// <returns>True if the two lists are unequal.</returns> 2312 public static bool operator !=(in FixedList64Bytes<T> a, in FixedList128Bytes<T> b) 2313 { 2314 return !(a == b); 2315 } 2316 2317 /// <summary> 2318 /// Returns a number denoting whether this list should be placed before or after another list in a sort. 2319 /// </summary> 2320 /// <param name="other">A list to to compare with.</param> 2321 /// <returns>An integer denoting the respective sort position of the list relative to the other: 2322 /// 2323 /// 0 denotes that both lists should have the same position in a sort. 2324 /// -1 denotes that this list should precede the other list in a sort. 2325 /// +1 denotes that this list should follow the other list in a sort. 2326 /// </returns> 2327 public int CompareTo(FixedList128Bytes<T> other) 2328 { 2329 unsafe 2330 { 2331 byte* a = buffer; 2332 byte* b = other.buffer; 2333 var aa = a + FixedList.PaddingBytes<T>(); 2334 var bb = b + FixedList.PaddingBytes<T>(); 2335 var mini = math.min(Length, other.Length); 2336 for(var i = 0; i < mini; ++i) 2337 { 2338 var j = UnsafeUtility.MemCmp(aa + sizeof(T) * i, bb + sizeof(T) * i, sizeof(T)); 2339 if(j != 0) 2340 return j; 2341 } 2342 return Length.CompareTo(other.Length); 2343 } 2344 } 2345 2346 /// <summary> 2347 /// Returns true if this list and another list are equal. 2348 /// </summary> 2349 /// <remarks>Two lists are equal if their length and bytes are equal.</remarks> 2350 /// <param name="other">The list to compare for equality.</param> 2351 /// <returns>True if the two lists are equal.</returns> 2352 public bool Equals(FixedList128Bytes<T> other) 2353 { 2354 return CompareTo(other) == 0; 2355 } 2356 2357 2358 /// <summary> 2359 /// Initializes and returns an instance of FixedList64Bytes with content copied from another list. 2360 /// </summary> 2361 /// <param name="other">The list to copy.</param> 2362 /// <exception cref="IndexOutOfRangeException">Throws if the other list's length exceeds the capacity of FixedList64Bytes&lt;T&gt;.</exception> 2363 public FixedList64Bytes(in FixedList128Bytes<T> other) 2364 { 2365 this = default; 2366 var error = Initialize(other); 2367 if(error != 0) 2368 FixedList.CheckResize<FixedBytes64Align8,T>(other.Length); 2369 } 2370 2371 /// <summary> 2372 /// Initializes an instance of FixedList64Bytes with content copied from another list. 2373 /// </summary> 2374 /// <param name="other">The list to copy.</param> 2375 /// <returns>zero on success, or non-zero on error.</returns> 2376 internal int Initialize(in FixedList128Bytes<T> other) 2377 { 2378 if(other.Length > Capacity) 2379 return (int)CopyError.Truncation; 2380 length = other.length; 2381 unsafe 2382 { 2383 UnsafeUtility.MemCpy(Buffer, other.Buffer, LengthInBytes); 2384 } 2385 return 0; 2386 } 2387 2388 /// <summary> 2389 /// Returns a new list that is a copy of another list. 2390 /// </summary> 2391 /// <param name="other">The list to copy.</param> 2392 /// <returns>A new list that is a copy of the other.</returns> 2393 /// <exception cref="IndexOutOfRangeException">Throws if the other list's length exceeds the capacity of FixedList64Bytes&lt;T&gt;.</exception> 2394 public static implicit operator FixedList64Bytes<T>(in FixedList128Bytes<T> other) 2395 { 2396 return new FixedList64Bytes<T>(other); 2397 } 2398 2399 /// <summary> 2400 /// Returns true if two lists are equal. 2401 /// </summary> 2402 /// <remarks>Two lists are equal if their length and bytes are equal.</remarks> 2403 /// <param name="a">The first list to compare for equality.</param> 2404 /// <param name="b">The second list to compare for equality.</param> 2405 /// <returns>True if the two lists are equal.</returns> 2406 public static bool operator ==(in FixedList64Bytes<T> a, in FixedList512Bytes<T> b) 2407 { 2408 unsafe 2409 { 2410 if(a.length != b.length) 2411 return false; 2412 return UnsafeUtility.MemCmp(a.Buffer, b.Buffer, a.LengthInBytes) == 0; 2413 } 2414 } 2415 2416 /// <summary> 2417 /// Returns true if two lists are unequal. 2418 /// </summary> 2419 /// <remarks>Two lists are equal if their length and bytes are equal.</remarks> 2420 /// <param name="a">The first list to compare for inequality.</param> 2421 /// <param name="b">The second list to compare for inequality.</param> 2422 /// <returns>True if the two lists are unequal.</returns> 2423 public static bool operator !=(in FixedList64Bytes<T> a, in FixedList512Bytes<T> b) 2424 { 2425 return !(a == b); 2426 } 2427 2428 /// <summary> 2429 /// Returns a number denoting whether this list should be placed before or after another list in a sort. 2430 /// </summary> 2431 /// <param name="other">A list to to compare with.</param> 2432 /// <returns>An integer denoting the respective sort position of the list relative to the other: 2433 /// 2434 /// 0 denotes that both lists should have the same position in a sort. 2435 /// -1 denotes that this list should precede the other list in a sort. 2436 /// +1 denotes that this list should follow the other list in a sort. 2437 /// </returns> 2438 public int CompareTo(FixedList512Bytes<T> other) 2439 { 2440 unsafe 2441 { 2442 byte* a = buffer; 2443 byte* b = other.buffer; 2444 var aa = a + FixedList.PaddingBytes<T>(); 2445 var bb = b + FixedList.PaddingBytes<T>(); 2446 var mini = math.min(Length, other.Length); 2447 for(var i = 0; i < mini; ++i) 2448 { 2449 var j = UnsafeUtility.MemCmp(aa + sizeof(T) * i, bb + sizeof(T) * i, sizeof(T)); 2450 if(j != 0) 2451 return j; 2452 } 2453 return Length.CompareTo(other.Length); 2454 } 2455 } 2456 2457 /// <summary> 2458 /// Returns true if this list and another list are equal. 2459 /// </summary> 2460 /// <remarks>Two lists are equal if their length and bytes are equal.</remarks> 2461 /// <param name="other">The list to compare for equality.</param> 2462 /// <returns>True if the two lists are equal.</returns> 2463 public bool Equals(FixedList512Bytes<T> other) 2464 { 2465 return CompareTo(other) == 0; 2466 } 2467 2468 2469 /// <summary> 2470 /// Initializes and returns an instance of FixedList64Bytes with content copied from another list. 2471 /// </summary> 2472 /// <param name="other">The list to copy.</param> 2473 /// <exception cref="IndexOutOfRangeException">Throws if the other list's length exceeds the capacity of FixedList64Bytes&lt;T&gt;.</exception> 2474 public FixedList64Bytes(in FixedList512Bytes<T> other) 2475 { 2476 this = default; 2477 var error = Initialize(other); 2478 if(error != 0) 2479 FixedList.CheckResize<FixedBytes64Align8,T>(other.Length); 2480 } 2481 2482 /// <summary> 2483 /// Initializes an instance of FixedList64Bytes with content copied from another list. 2484 /// </summary> 2485 /// <param name="other">The list to copy.</param> 2486 /// <returns>zero on success, or non-zero on error.</returns> 2487 internal int Initialize(in FixedList512Bytes<T> other) 2488 { 2489 if(other.Length > Capacity) 2490 return (int)CopyError.Truncation; 2491 length = other.length; 2492 unsafe 2493 { 2494 UnsafeUtility.MemCpy(Buffer, other.Buffer, LengthInBytes); 2495 } 2496 return 0; 2497 } 2498 2499 /// <summary> 2500 /// Returns a new list that is a copy of another list. 2501 /// </summary> 2502 /// <param name="other">The list to copy.</param> 2503 /// <returns>A new list that is a copy of the other.</returns> 2504 /// <exception cref="IndexOutOfRangeException">Throws if the other list's length exceeds the capacity of FixedList64Bytes&lt;T&gt;.</exception> 2505 public static implicit operator FixedList64Bytes<T>(in FixedList512Bytes<T> other) 2506 { 2507 return new FixedList64Bytes<T>(other); 2508 } 2509 2510 /// <summary> 2511 /// Returns true if two lists are equal. 2512 /// </summary> 2513 /// <remarks>Two lists are equal if their length and bytes are equal.</remarks> 2514 /// <param name="a">The first list to compare for equality.</param> 2515 /// <param name="b">The second list to compare for equality.</param> 2516 /// <returns>True if the two lists are equal.</returns> 2517 public static bool operator ==(in FixedList64Bytes<T> a, in FixedList4096Bytes<T> b) 2518 { 2519 unsafe 2520 { 2521 if(a.length != b.length) 2522 return false; 2523 return UnsafeUtility.MemCmp(a.Buffer, b.Buffer, a.LengthInBytes) == 0; 2524 } 2525 } 2526 2527 /// <summary> 2528 /// Returns true if two lists are unequal. 2529 /// </summary> 2530 /// <remarks>Two lists are equal if their length and bytes are equal.</remarks> 2531 /// <param name="a">The first list to compare for inequality.</param> 2532 /// <param name="b">The second list to compare for inequality.</param> 2533 /// <returns>True if the two lists are unequal.</returns> 2534 public static bool operator !=(in FixedList64Bytes<T> a, in FixedList4096Bytes<T> b) 2535 { 2536 return !(a == b); 2537 } 2538 2539 /// <summary> 2540 /// Returns a number denoting whether this list should be placed before or after another list in a sort. 2541 /// </summary> 2542 /// <param name="other">A list to to compare with.</param> 2543 /// <returns>An integer denoting the respective sort position of the list relative to the other: 2544 /// 2545 /// 0 denotes that both lists should have the same position in a sort. 2546 /// -1 denotes that this list should precede the other list in a sort. 2547 /// +1 denotes that this list should follow the other list in a sort. 2548 /// </returns> 2549 public int CompareTo(FixedList4096Bytes<T> other) 2550 { 2551 unsafe 2552 { 2553 byte* a = buffer; 2554 byte* b = other.buffer; 2555 var aa = a + FixedList.PaddingBytes<T>(); 2556 var bb = b + FixedList.PaddingBytes<T>(); 2557 var mini = math.min(Length, other.Length); 2558 for(var i = 0; i < mini; ++i) 2559 { 2560 var j = UnsafeUtility.MemCmp(aa + sizeof(T) * i, bb + sizeof(T) * i, sizeof(T)); 2561 if(j != 0) 2562 return j; 2563 } 2564 return Length.CompareTo(other.Length); 2565 } 2566 } 2567 2568 /// <summary> 2569 /// Returns true if this list and another list are equal. 2570 /// </summary> 2571 /// <remarks>Two lists are equal if their length and bytes are equal.</remarks> 2572 /// <param name="other">The list to compare for equality.</param> 2573 /// <returns>True if the two lists are equal.</returns> 2574 public bool Equals(FixedList4096Bytes<T> other) 2575 { 2576 return CompareTo(other) == 0; 2577 } 2578 2579 2580 /// <summary> 2581 /// Initializes and returns an instance of FixedList64Bytes with content copied from another list. 2582 /// </summary> 2583 /// <param name="other">The list to copy.</param> 2584 /// <exception cref="IndexOutOfRangeException">Throws if the other list's length exceeds the capacity of FixedList64Bytes&lt;T&gt;.</exception> 2585 public FixedList64Bytes(in FixedList4096Bytes<T> other) 2586 { 2587 this = default; 2588 var error = Initialize(other); 2589 if(error != 0) 2590 FixedList.CheckResize<FixedBytes64Align8,T>(other.Length); 2591 } 2592 2593 /// <summary> 2594 /// Initializes an instance of FixedList64Bytes with content copied from another list. 2595 /// </summary> 2596 /// <param name="other">The list to copy.</param> 2597 /// <returns>zero on success, or non-zero on error.</returns> 2598 internal int Initialize(in FixedList4096Bytes<T> other) 2599 { 2600 if(other.Length > Capacity) 2601 return (int)CopyError.Truncation; 2602 length = other.length; 2603 unsafe 2604 { 2605 UnsafeUtility.MemCpy(Buffer, other.Buffer, LengthInBytes); 2606 } 2607 return 0; 2608 } 2609 2610 /// <summary> 2611 /// Returns a new list that is a copy of another list. 2612 /// </summary> 2613 /// <param name="other">The list to copy.</param> 2614 /// <returns>A new list that is a copy of the other.</returns> 2615 /// <exception cref="IndexOutOfRangeException">Throws if the other list's length exceeds the capacity of FixedList64Bytes&lt;T&gt;.</exception> 2616 public static implicit operator FixedList64Bytes<T>(in FixedList4096Bytes<T> other) 2617 { 2618 return new FixedList64Bytes<T>(other); 2619 } 2620 2621 /// <summary> 2622 /// Returns true if the list is equal to an object. 2623 /// </summary> 2624 /// <remarks>Two lists are equal if their length and bytes are equal. 2625 /// 2626 /// A FixedList*N*&lt;T&gt; can only be equal to another FixedList*N*&lt;T&gt; with the same *N* and T. 2627 /// </remarks> 2628 /// <param name="obj">An object to compare for equality.</param> 2629 /// <returns>True if the list is equal to the object.</returns> 2630 [ExcludeFromBurstCompatTesting("Takes managed object")] 2631 public override bool Equals(object obj) 2632 { 2633 if(obj is FixedList32Bytes<T> aFixedList32Bytes) return Equals(aFixedList32Bytes); 2634 if(obj is FixedList64Bytes<T> aFixedList64Bytes) return Equals(aFixedList64Bytes); 2635 if(obj is FixedList128Bytes<T> aFixedList128Bytes) return Equals(aFixedList128Bytes); 2636 if(obj is FixedList512Bytes<T> aFixedList512Bytes) return Equals(aFixedList512Bytes); 2637 if(obj is FixedList4096Bytes<T> aFixedList4096Bytes) return Equals(aFixedList4096Bytes); 2638 return false; 2639 } 2640 2641 /// <summary> 2642 /// An enumerator over the elements of a FixedList64Bytes&lt;T&gt;. 2643 /// </summary> 2644 /// <remarks> 2645 /// In an enumerator's initial state, `Current` cannot be read. The first <see cref="MoveNext"/> call advances the enumerator to the first element. 2646 /// </remarks> 2647 public struct Enumerator : IEnumerator<T> 2648 { 2649 FixedList64Bytes<T> m_List; 2650 int m_Index; 2651 2652 /// <summary> 2653 /// Initializes and returns an instance of FixedList64Bytes&lt;T&gt;. 2654 /// </summary> 2655 /// <param name="list">The list for which to create an enumerator.</param> 2656 public Enumerator(ref FixedList64Bytes<T> list) 2657 { 2658 m_List = list; 2659 m_Index = -1; 2660 } 2661 2662 /// <summary> 2663 /// Does nothing. 2664 /// </summary> 2665 public void Dispose() 2666 { 2667 } 2668 2669 /// <summary> 2670 /// Advances the enumerator to the next element. 2671 /// </summary> 2672 /// <returns>True if <see cref="Current"/> is valid to read after the call.</returns> 2673 [MethodImpl(MethodImplOptions.AggressiveInlining)] 2674 public bool MoveNext() 2675 { 2676 m_Index++; 2677 return m_Index < m_List.Length; 2678 } 2679 2680 /// <summary> 2681 /// Resets the enumerator to its initial state. 2682 /// </summary> 2683 public void Reset() 2684 { 2685 m_Index = -1; 2686 } 2687 2688 /// <summary> 2689 /// The current element. 2690 /// </summary> 2691 /// <value>The current element.</value> 2692 public T Current 2693 { 2694 [MethodImpl(MethodImplOptions.AggressiveInlining)] 2695 get => m_List[m_Index]; // Let FixedList64Bytes<T> indexer check for out of range. 2696 } 2697 2698 object IEnumerator.Current => Current; 2699 } 2700 2701 /// <summary> 2702 /// Returns an enumerator for iterating over the elements of this list. 2703 /// </summary> 2704 /// <returns>An enumerator for iterating over the elements of this list.</returns> 2705 public Enumerator GetEnumerator() 2706 { 2707 return new Enumerator(ref this); 2708 } 2709 2710 /// <summary> 2711 /// This method is not implemented. Use <see cref="GetEnumerator"/> instead. 2712 /// </summary> 2713 /// <returns>Nothing because it always throws <see cref="NotImplementedException"/>.</returns> 2714 /// <exception cref="NotImplementedException">Method is not implemented.</exception> 2715 IEnumerator IEnumerable.GetEnumerator() 2716 { 2717 throw new NotImplementedException(); 2718 } 2719 2720 /// <summary> 2721 /// This method is not implemented. Use <see cref="GetEnumerator"/> instead. 2722 /// </summary> 2723 /// <returns>Nothing because it always throws <see cref="NotImplementedException"/>.</returns> 2724 /// <exception cref="NotImplementedException">Method is not implemented.</exception> 2725 IEnumerator<T> IEnumerable<T>.GetEnumerator() 2726 { 2727 throw new NotImplementedException(); 2728 } 2729 } 2730 2731 /// <summary> 2732 /// Provides extension methods for FixedList64Bytes. 2733 /// </summary> 2734 [GenerateTestsForBurstCompatibility] 2735 public unsafe static class FixedList64BytesExtensions 2736 { 2737 /// <summary> 2738 /// Finds the index of the first occurrence of a particular value in this list. 2739 /// </summary> 2740 /// <typeparam name="T">The type of elements in this list.</typeparam> 2741 /// <typeparam name="U">The value type.</typeparam> 2742 /// <param name="list">The list to search.</param> 2743 /// <param name="value">The value to locate.</param> 2744 /// <returns>The index of the first occurrence of the value. Returns -1 if no occurrence is found.</returns> 2745 [GenerateTestsForBurstCompatibility(GenericTypeArguments = new [] { typeof(int), typeof(int) })] 2746 public static int IndexOf<T, U>(this ref FixedList64Bytes<T> list, U value) where T : unmanaged, IEquatable<U> 2747 { 2748 return NativeArrayExtensions.IndexOf<T, U>(list.Buffer, list.Length, value); 2749 } 2750 2751 /// <summary> 2752 /// Returns true if a particular value is present in this list. 2753 /// </summary> 2754 /// <typeparam name="T">The type of elements in this list.</typeparam> 2755 /// <typeparam name="U">The value type.</typeparam> 2756 /// <param name="list">The list to search.</param> 2757 /// <param name="value">The value to locate.</param> 2758 /// <returns>True if the value is present in this list.</returns> 2759 [GenerateTestsForBurstCompatibility(GenericTypeArguments = new [] { typeof(int), typeof(int) })] 2760 public static bool Contains<T, U>(this ref FixedList64Bytes<T> list, U value) where T : unmanaged, IEquatable<U> 2761 { 2762 return list.IndexOf(value) != -1; 2763 } 2764 2765 /// <summary> 2766 /// Removes the first occurrence of a particular value in this list. 2767 /// </summary> 2768 /// <remarks> 2769 /// If a value is removed, all elements after it are shifted down by one, and the list's length is decremented by one. 2770 /// 2771 /// If you don't need to preserve the order of the remaining elements, <see cref="Unity.Collections.FixedList64BytesExtensions.RemoveSwapBack{T, U}"/> is a cheaper alternative. 2772 /// </remarks> 2773 /// <typeparam name="T">The type of elements in this list.</typeparam> 2774 /// <typeparam name="U">The value type.</typeparam> 2775 /// <param name="list">The list to search.</param> 2776 /// <param name="value">The value to locate and remove.</param> 2777 /// <returns>True if the value was found and removed.</returns> 2778 [GenerateTestsForBurstCompatibility(GenericTypeArguments = new [] { typeof(int), typeof(int) })] 2779 public static bool Remove<T, U>(this ref FixedList64Bytes<T> list, U value) where T : unmanaged, IEquatable<U> 2780 { 2781 int index = list.IndexOf(value); 2782 if (index < 0) 2783 { 2784 return false; 2785 } 2786 2787 list.RemoveAt(index); 2788 2789 return true; 2790 } 2791 2792 /// <summary> 2793 /// Removes the first occurrence of a particular value in this list. 2794 /// </summary> 2795 /// <remarks> 2796 /// 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. 2797 /// 2798 /// This is cheaper than <see cref="Remove"/>, but the order of the remaining elements is not preserved. 2799 /// </remarks> 2800 /// <typeparam name="T">The type of elements in this list.</typeparam> 2801 /// <typeparam name="U">The value type.</typeparam> 2802 /// <param name="list">The list to search.</param> 2803 /// <param name="value">The value to locate and remove.</param> 2804 /// <returns>Returns true if the item is removed.</returns> 2805 [GenerateTestsForBurstCompatibility(GenericTypeArguments = new [] { typeof(int), typeof(int) })] 2806 public static bool RemoveSwapBack<T, U>(this ref FixedList64Bytes<T> list, U value) where T : unmanaged, IEquatable<U> 2807 { 2808 var index = list.IndexOf(value); 2809 if (index == -1) 2810 { 2811 return false; 2812 } 2813 2814 list.RemoveAtSwapBack(index); 2815 2816 return true; 2817 } 2818 } 2819 2820 sealed class FixedList64BytesDebugView<T> where T : unmanaged 2821 { 2822 FixedList64Bytes<T> m_List; 2823 public FixedList64BytesDebugView(FixedList64Bytes<T> list) 2824 { 2825 m_List = list; 2826 } 2827 public T[] Items => m_List.ToArray(); 2828 } 2829 /// <summary> 2830 /// An unmanaged, resizable list whose content is all stored directly in the 128-byte struct. Useful for small lists. 2831 /// </summary> 2832 /// <typeparam name="T">The type of the elements.</typeparam> 2833 [Serializable] 2834 [DebuggerTypeProxy(typeof(FixedList128BytesDebugView<>))] 2835 [GenerateTestsForBurstCompatibility(GenericTypeArguments = new [] { typeof(int) })] 2836 public struct FixedList128Bytes<T> 2837 : INativeList<T> 2838 , IEnumerable<T> // Used by collection initializers. 2839 , IEquatable<FixedList32Bytes<T>> 2840 , IComparable<FixedList32Bytes<T>> 2841 , IEquatable<FixedList64Bytes<T>> 2842 , IComparable<FixedList64Bytes<T>> 2843 , IEquatable<FixedList128Bytes<T>> 2844 , IComparable<FixedList128Bytes<T>> 2845 , IEquatable<FixedList512Bytes<T>> 2846 , IComparable<FixedList512Bytes<T>> 2847 , IEquatable<FixedList4096Bytes<T>> 2848 , IComparable<FixedList4096Bytes<T>> 2849 where T : unmanaged 2850 { 2851 [SerializeField] internal FixedBytes128Align8 data; 2852 2853 internal ushort length 2854 { 2855 [MethodImpl(MethodImplOptions.AggressiveInlining)] 2856 readonly get 2857 { 2858 unsafe 2859 { 2860 fixed(void* ptr = &data) 2861 return *((ushort*)ptr); 2862 } 2863 } 2864 2865 [MethodImpl(MethodImplOptions.AggressiveInlining)] 2866 set 2867 { 2868 unsafe 2869 { 2870 fixed (void* ptr = &data) 2871 *((ushort*)ptr) = value; 2872 } 2873 } 2874 } 2875 2876 internal readonly unsafe byte* buffer 2877 { 2878 [MethodImpl(MethodImplOptions.AggressiveInlining)] 2879 get 2880 { 2881 unsafe 2882 { 2883 fixed (void* ptr = &data) 2884 return ((byte*)ptr) + UnsafeUtility.SizeOf<ushort>(); 2885 } 2886 } 2887 } 2888 2889 /// <summary> 2890 /// The current number of items in this list. 2891 /// </summary> 2892 /// <value>The current number of items in this list.</value> 2893 [CreateProperty] 2894 public int Length 2895 { 2896 [MethodImpl(MethodImplOptions.AggressiveInlining)] 2897 readonly get => length; 2898 set 2899 { 2900 FixedList.CheckResize<FixedBytes128Align8,T>(value); 2901 length = (ushort)value; 2902 } 2903 } 2904 2905 /// <summary> 2906 /// A property in order to display items in the Entity Inspector. 2907 /// </summary> 2908 [CreateProperty] IEnumerable<T> Elements => this.ToArray(); 2909 2910 /// <summary> 2911 /// Whether this list is empty. 2912 /// </summary> 2913 /// <value>True if this string has no characters or if the container has not been constructed.</value> 2914 public readonly bool IsEmpty 2915 { 2916 [MethodImpl(MethodImplOptions.AggressiveInlining)] 2917 get => Length == 0; 2918 } 2919 2920 internal int LengthInBytes => Length * UnsafeUtility.SizeOf<T>(); 2921 2922 /// <summary> 2923 /// Returns a pointer to the first element of the list buffer. 2924 /// </summary> 2925 /// <remarks> 2926 /// The pointer returned by this method points into the internals of the target list object. It is the 2927 /// caller's responsibility to ensure that the pointer is not used after the list is destroyed or goes 2928 /// out of scope. 2929 /// </remarks> 2930 /// <returns>A pointer to the first element of the list buffer.</returns> 2931 internal readonly unsafe byte* Buffer 2932 { 2933 [MethodImpl(MethodImplOptions.AggressiveInlining)] 2934 get 2935 { 2936 return buffer + FixedList.PaddingBytes<T>(); 2937 } 2938 } 2939 2940 /// <summary> 2941 /// The number of elements that can fit in this list. 2942 /// </summary> 2943 /// <value>The number of elements that can fit in this list.</value> 2944 /// <remarks>The capacity of a FixedList cannot be changed. The setter is included only for conformity with <see cref="INativeList{T}"/>.</remarks> 2945 /// <exception cref="ArgumentOutOfRangeException">Thrown if the new value does not match the current capacity.</exception> 2946 public int Capacity 2947 { 2948 [MethodImpl(MethodImplOptions.AggressiveInlining)] 2949 readonly get 2950 { 2951 return FixedList.Capacity<FixedBytes128Align8,T>(); 2952 } 2953 2954 set 2955 { 2956 CollectionHelper.CheckCapacityInRange(value, Length); 2957 } 2958 } 2959 2960 /// <summary> 2961 /// The element at a given index. 2962 /// </summary> 2963 /// <param name="index">An index.</param> 2964 /// <value>The value to store at the index.</value> 2965 /// <exception cref="IndexOutOfRangeException">Thrown if the index is out of bounds.</exception> 2966 public T this[int index] 2967 { 2968 [MethodImpl(MethodImplOptions.AggressiveInlining)] 2969 readonly get 2970 { 2971 CollectionHelper.CheckIndexInRange(index, length); 2972 unsafe 2973 { 2974 return UnsafeUtility.ReadArrayElement<T>(Buffer, CollectionHelper.AssumePositive(index)); 2975 } 2976 } 2977 2978 [MethodImpl(MethodImplOptions.AggressiveInlining)] 2979 set 2980 { 2981 CollectionHelper.CheckIndexInRange(index, length); 2982 unsafe 2983 { 2984 UnsafeUtility.WriteArrayElement<T>(Buffer, CollectionHelper.AssumePositive(index), value); 2985 } 2986 } 2987 } 2988 2989 /// <summary> 2990 /// Returns the element at a given index. 2991 /// </summary> 2992 /// <param name="index">An index.</param> 2993 /// <returns>The list element at the index.</returns> 2994 [MethodImpl(MethodImplOptions.AggressiveInlining)] 2995 public ref T ElementAt(int index) 2996 { 2997 CollectionHelper.CheckIndexInRange(index, length); 2998 unsafe 2999 { 3000 return ref UnsafeUtility.ArrayElementAsRef<T>(Buffer, index); 3001 } 3002 } 3003 3004 /// <summary> 3005 /// Returns the hash code of this list. 3006 /// </summary> 3007 /// <remarks> 3008 /// 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> 3009 /// <returns>The hash code of this list.</returns> 3010 public override int GetHashCode() 3011 { 3012 unsafe 3013 { 3014 return (int)CollectionHelper.Hash(Buffer, LengthInBytes); 3015 } 3016 } 3017 3018 /// <summary> 3019 /// Appends an element to the end of this list. Increments the length by 1. 3020 /// </summary> 3021 /// <remarks> 3022 /// The same as <see cref="AddNoResize"/>. Included only for consistency with the other list types. 3023 /// If the element exceeds the capacity, throws cref="IndexOutOfRangeException", and the list is unchanged. 3024 /// </remarks> 3025 /// <param name="item">The element to append at the end of the list.</param> 3026 /// <exception cref="IndexOutOfRangeException">Thrown if the append exceeds the capacity.</exception> 3027 public void Add(in T item) => AddNoResize(in item); 3028 3029 /// <summary> 3030 /// Appends elements from a buffer to the end of this list. Increments the length by the number of appended elements. 3031 /// </summary> 3032 /// <remarks> 3033 /// The same as <see cref="AddRangeNoResize"/>. Included only for consistency with the other list types. 3034 /// If the elements exceeds the capacity, throws cref="IndexOutOfRangeException", and the list is unchanged. 3035 /// </remarks> 3036 /// <param name="ptr">A buffer.</param> 3037 /// <param name="length">The number of elements from the buffer to append.</param> 3038 /// <exception cref="IndexOutOfRangeException">Thrown if the append exceeds the capacity.</exception> 3039 public unsafe void AddRange(void* ptr, int length) => AddRangeNoResize(ptr, length); 3040 3041 /// <summary> 3042 /// Appends an element to the end of this list. Increments the length by 1. 3043 /// </summary> 3044 /// <remarks> 3045 /// If the element exceeds the capacity, throws cref="IndexOutOfRangeException", and the list is unchanged. 3046 /// </remarks> 3047 /// <param name="item">The element to append at the end of the list.</param> 3048 /// <exception cref="IndexOutOfRangeException">Thrown if the append exceeds the capacity.</exception> 3049 [MethodImpl(MethodImplOptions.AggressiveInlining)] 3050 public void AddNoResize(in T item) 3051 { 3052 this[Length++] = item; 3053 } 3054 3055 /// <summary> 3056 /// Appends elements from a buffer to the end of this list. Increments the length by the number of appended elements. 3057 /// </summary> 3058 /// <remarks> 3059 /// If the elements exceeds the capacity, throws cref="IndexOutOfRangeException", and the list is unchanged. 3060 /// </remarks> 3061 /// <param name="ptr">A buffer.</param> 3062 /// <param name="length">The number of elements from the buffer to append.</param> 3063 /// <exception cref="IndexOutOfRangeException">Thrown if the append exceeds the capacity.</exception> 3064 public unsafe void AddRangeNoResize(void* ptr, int length) 3065 { 3066 var idx = Length; 3067 Length += length; 3068 UnsafeUtility.MemCpy((T*)Buffer + idx, ptr, UnsafeUtility.SizeOf<T>() * length); 3069 } 3070 3071 /// <summary> 3072 /// Appends value count times to the end of this list. 3073 /// </summary> 3074 /// <param name="value">The value to add to the end of this list.</param> 3075 /// <param name="count">The number of times to replicate the value.</param> 3076 /// <exception cref="IndexOutOfRangeException">Thrown if the append exceeds the capacity.</exception> 3077 public unsafe void AddReplicate(in T value, int count) 3078 { 3079 var idx = Length; 3080 Length += count; 3081 fixed (T* ptr = &value) 3082 UnsafeUtility.MemCpyReplicate((T*)Buffer + idx, ptr, UnsafeUtility.SizeOf<T>(), count); 3083 } 3084 3085 /// <summary> 3086 /// Sets the length to 0. 3087 /// </summary> 3088 /// <remarks> Does *not* zero out the bytes.</remarks> 3089 public void Clear() 3090 { 3091 Length = 0; 3092 } 3093 3094 /// <summary> 3095 /// Shifts elements toward the end of this list, increasing its length. 3096 /// </summary> 3097 /// <remarks> 3098 /// Right-shifts elements in the list so as to create 'free' slots at the beginning or in the middle. 3099 /// 3100 /// The length is increased by `end - begin`. 3101 /// 3102 /// If `end` equals `begin`, the method does nothing. 3103 /// 3104 /// 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. 3105 /// 3106 /// The indexes `begin` up to `end` are not cleared: they will contain whatever values they held prior. 3107 /// </remarks> 3108 /// <param name="begin">The index of the first element that will be shifted up.</param> 3109 /// <param name="end">The index where the first shifted element will end up.</param> 3110 /// <exception cref="IndexOutOfRangeException">Thrown if the new length exceeds the capacity.</exception> 3111 public void InsertRangeWithBeginEnd(int begin, int end) 3112 { 3113 int items = end - begin; 3114 if(items < 1) 3115 return; 3116 int itemsToCopy = length - begin; 3117 Length += items; 3118 if(itemsToCopy < 1) 3119 return; 3120 int bytesToCopy = itemsToCopy * UnsafeUtility.SizeOf<T>(); 3121 unsafe 3122 { 3123 byte *b = Buffer; 3124 byte *dest = b + end * UnsafeUtility.SizeOf<T>(); 3125 byte *src = b + begin * UnsafeUtility.SizeOf<T>(); 3126 UnsafeUtility.MemMove(dest, src, bytesToCopy); 3127 } 3128 } 3129 3130 /// <summary> 3131 /// Shifts elements toward the end of this list, increasing its length. 3132 /// </summary> 3133 /// <remarks> 3134 /// Right-shifts elements in the list so as to create 'free' slots at the beginning or in the middle. 3135 /// 3136 /// The length is increased by `count`. If necessary, the capacity will be increased accordingly. 3137 /// 3138 /// If `count` equals `0`, the method does nothing. 3139 /// 3140 /// 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. 3141 /// 3142 /// The indexes `index` up to `index + count` are not cleared: they will contain whatever values they held prior. 3143 /// </remarks> 3144 /// <param name="index">The index of the first element that will be shifted up.</param> 3145 /// <param name="count">The number of elements to insert.</param> 3146 /// <exception cref="ArgumentException">Thrown if `count` is negative.</exception> 3147 /// <exception cref="ArgumentOutOfRangeException">Thrown if `index` is out of bounds.</exception> 3148 public void InsertRange(int index, int count) => InsertRangeWithBeginEnd(index, index + count); 3149 3150 /// <summary> 3151 /// Inserts a single element at an index. Increments the length by 1. 3152 /// </summary> 3153 /// <param name="index">The index at which to insert the element.</param> 3154 /// <param name="item">The element to insert.</param> 3155 /// <exception cref="ArgumentOutOfRangeException">Thrown if the index is out of bounds.</exception> 3156 public void Insert(int index, in T item) 3157 { 3158 InsertRangeWithBeginEnd(index, index+1); 3159 this[index] = item; 3160 } 3161 3162 /// <summary> 3163 /// Copies the last element of this list to an index. Decrements the length by 1. 3164 /// </summary> 3165 /// <remarks>Useful as a cheap way to remove elements from a list when you don't care about preserving order.</remarks> 3166 /// <param name="index">The index to overwrite with the last element.</param> 3167 /// <exception cref="ArgumentOutOfRangeException">Thrown if the index is out of bounds.</exception> 3168 public void RemoveAtSwapBack(int index) 3169 { 3170 RemoveRangeSwapBack(index, 1); 3171 } 3172 3173 /// <summary> 3174 /// Copies the last *N* elements of this list to a range in this list. Decrements the length by *N*. 3175 /// </summary> 3176 /// <remarks> 3177 /// Copies the last `count`-numbered elements to the range starting at `index`. 3178 /// 3179 /// Useful as a cheap way to remove elements from a list when you don't care about preserving order. 3180 /// 3181 /// Does nothing if the count is less than 1. 3182 /// </remarks> 3183 /// <param name="index">The first index of the destination range.</param> 3184 /// <param name="count">The number of elements to copy and the amount by which to decrement the length.</param> 3185 /// <exception cref="ArgumentOutOfRangeException">Thrown if the index is out of bounds.</exception> 3186 public void RemoveRangeSwapBack(int index, int count) 3187 { 3188 if (count > 0) 3189 { 3190 int copyFrom = math.max(Length - count, index + count); 3191 3192 unsafe 3193 { 3194 var sizeOf = UnsafeUtility.SizeOf<T>(); 3195 void* dst = Buffer + index * sizeOf; 3196 void* src = Buffer + copyFrom * sizeOf; 3197 UnsafeUtility.MemCpy(dst, src, (Length - copyFrom) * sizeOf); 3198 } 3199 3200 Length -= count; 3201 } 3202 } 3203 3204 /// <summary> 3205 /// Removes the element at an index. Shifts everything above the index down by one and decrements the length by 1. 3206 /// </summary> 3207 /// <param name="index">The index of the element to remove.</param> 3208 /// <remarks> 3209 /// If you don't care about preserving the order of the elements, `RemoveAtSwapBack` is a more efficient way to remove an element. 3210 /// </remarks> 3211 /// <exception cref="ArgumentOutOfRangeException">Thrown if the index is out of bounds.</exception> 3212 public void RemoveAt(int index) 3213 { 3214 RemoveRange(index, 1); 3215 } 3216 3217 /// <summary> 3218 /// Removes *N* elements of a range. Shifts everything above the range down by *N* and decrements the length by *N*. 3219 /// </summary> 3220 /// <remarks> 3221 /// If you don't care about preserving the order of the elements, `RemoveAtSwapBack` is a more efficient way to remove elements. 3222 /// </remarks> 3223 /// <param name="index">The first index of the range to remove.</param> 3224 /// <param name="count">The number of elements to remove.</param> 3225 /// <exception cref="ArgumentOutOfRangeException">Thrown if the index is out of bounds.</exception> 3226 public void RemoveRange(int index, int count) 3227 { 3228 if (count > 0) 3229 { 3230 int copyFrom = math.min(index + count, Length); 3231 3232 unsafe 3233 { 3234 var sizeOf = UnsafeUtility.SizeOf<T>(); 3235 void* dst = Buffer + index * sizeOf; 3236 void* src = Buffer + copyFrom * sizeOf; 3237 UnsafeUtility.MemCpy(dst, src, (Length - copyFrom) * sizeOf); 3238 } 3239 3240 Length -= count; 3241 } 3242 } 3243 3244 /// <summary> 3245 /// Returns a managed array that is a copy of this list. 3246 /// </summary> 3247 /// <returns>A managed array that is a copy of this list.</returns> 3248 [ExcludeFromBurstCompatTesting("Returns managed array")] 3249 public T[] ToArray() 3250 { 3251 var result = new T[Length]; 3252 unsafe 3253 { 3254 byte* s = Buffer; 3255 fixed(T* d = result) 3256 UnsafeUtility.MemCpy(d, s, LengthInBytes); 3257 } 3258 return result; 3259 } 3260 3261 /// <summary> 3262 /// Returns an array that is a copy of this list. 3263 /// </summary> 3264 /// <param name="allocator">The allocator to use.</param> 3265 /// <returns>An array that is a copy of this list.</returns> 3266 public NativeArray<T> ToNativeArray(AllocatorManager.AllocatorHandle allocator) 3267 { 3268 unsafe 3269 { 3270 var copy = CollectionHelper.CreateNativeArray<T>(Length, allocator, NativeArrayOptions.UninitializedMemory); 3271 UnsafeUtility.MemCpy(copy.GetUnsafePtr(), Buffer, LengthInBytes); 3272 return copy; 3273 } 3274 } 3275 3276 3277 /// <summary> 3278 /// Returns true if two lists are equal. 3279 /// </summary> 3280 /// <remarks>Two lists are equal if their length and bytes are equal.</remarks> 3281 /// <param name="a">The first list to compare for equality.</param> 3282 /// <param name="b">The second list to compare for equality.</param> 3283 /// <returns>True if the two lists are equal.</returns> 3284 public static bool operator ==(in FixedList128Bytes<T> a, in FixedList32Bytes<T> b) 3285 { 3286 unsafe 3287 { 3288 if(a.length != b.length) 3289 return false; 3290 return UnsafeUtility.MemCmp(a.Buffer, b.Buffer, a.LengthInBytes) == 0; 3291 } 3292 } 3293 3294 /// <summary> 3295 /// Returns true if two lists are unequal. 3296 /// </summary> 3297 /// <remarks>Two lists are equal if their length and bytes are equal.</remarks> 3298 /// <param name="a">The first list to compare for inequality.</param> 3299 /// <param name="b">The second list to compare for inequality.</param> 3300 /// <returns>True if the two lists are unequal.</returns> 3301 public static bool operator !=(in FixedList128Bytes<T> a, in FixedList32Bytes<T> b) 3302 { 3303 return !(a == b); 3304 } 3305 3306 /// <summary> 3307 /// Returns a number denoting whether this list should be placed before or after another list in a sort. 3308 /// </summary> 3309 /// <param name="other">A list to to compare with.</param> 3310 /// <returns>An integer denoting the respective sort position of the list relative to the other: 3311 /// 3312 /// 0 denotes that both lists should have the same position in a sort. 3313 /// -1 denotes that this list should precede the other list in a sort. 3314 /// +1 denotes that this list should follow the other list in a sort. 3315 /// </returns> 3316 public int CompareTo(FixedList32Bytes<T> other) 3317 { 3318 unsafe 3319 { 3320 byte* a = buffer; 3321 byte* b = other.buffer; 3322 var aa = a + FixedList.PaddingBytes<T>(); 3323 var bb = b + FixedList.PaddingBytes<T>(); 3324 var mini = math.min(Length, other.Length); 3325 for(var i = 0; i < mini; ++i) 3326 { 3327 var j = UnsafeUtility.MemCmp(aa + sizeof(T) * i, bb + sizeof(T) * i, sizeof(T)); 3328 if(j != 0) 3329 return j; 3330 } 3331 return Length.CompareTo(other.Length); 3332 } 3333 } 3334 3335 /// <summary> 3336 /// Returns true if this list and another list are equal. 3337 /// </summary> 3338 /// <remarks>Two lists are equal if their length and bytes are equal.</remarks> 3339 /// <param name="other">The list to compare for equality.</param> 3340 /// <returns>True if the two lists are equal.</returns> 3341 public bool Equals(FixedList32Bytes<T> other) 3342 { 3343 return CompareTo(other) == 0; 3344 } 3345 3346 3347 /// <summary> 3348 /// Initializes and returns an instance of FixedList128Bytes with content copied from another list. 3349 /// </summary> 3350 /// <param name="other">The list to copy.</param> 3351 /// <exception cref="IndexOutOfRangeException">Throws if the other list's length exceeds the capacity of FixedList128Bytes&lt;T&gt;.</exception> 3352 public FixedList128Bytes(in FixedList32Bytes<T> other) 3353 { 3354 this = default; 3355 var error = Initialize(other); 3356 if(error != 0) 3357 FixedList.CheckResize<FixedBytes128Align8,T>(other.Length); 3358 } 3359 3360 /// <summary> 3361 /// Initializes an instance of FixedList128Bytes with content copied from another list. 3362 /// </summary> 3363 /// <param name="other">The list to copy.</param> 3364 /// <returns>zero on success, or non-zero on error.</returns> 3365 internal int Initialize(in FixedList32Bytes<T> other) 3366 { 3367 if(other.Length > Capacity) 3368 return (int)CopyError.Truncation; 3369 length = other.length; 3370 unsafe 3371 { 3372 UnsafeUtility.MemCpy(Buffer, other.Buffer, LengthInBytes); 3373 } 3374 return 0; 3375 } 3376 3377 /// <summary> 3378 /// Returns a new list that is a copy of another list. 3379 /// </summary> 3380 /// <param name="other">The list to copy.</param> 3381 /// <returns>A new list that is a copy of the other.</returns> 3382 /// <exception cref="IndexOutOfRangeException">Throws if the other list's length exceeds the capacity of FixedList128Bytes&lt;T&gt;.</exception> 3383 public static implicit operator FixedList128Bytes<T>(in FixedList32Bytes<T> other) 3384 { 3385 return new FixedList128Bytes<T>(other); 3386 } 3387 3388 /// <summary> 3389 /// Returns true if two lists are equal. 3390 /// </summary> 3391 /// <remarks>Two lists are equal if their length and bytes are equal.</remarks> 3392 /// <param name="a">The first list to compare for equality.</param> 3393 /// <param name="b">The second list to compare for equality.</param> 3394 /// <returns>True if the two lists are equal.</returns> 3395 public static bool operator ==(in FixedList128Bytes<T> a, in FixedList64Bytes<T> b) 3396 { 3397 unsafe 3398 { 3399 if(a.length != b.length) 3400 return false; 3401 return UnsafeUtility.MemCmp(a.Buffer, b.Buffer, a.LengthInBytes) == 0; 3402 } 3403 } 3404 3405 /// <summary> 3406 /// Returns true if two lists are unequal. 3407 /// </summary> 3408 /// <remarks>Two lists are equal if their length and bytes are equal.</remarks> 3409 /// <param name="a">The first list to compare for inequality.</param> 3410 /// <param name="b">The second list to compare for inequality.</param> 3411 /// <returns>True if the two lists are unequal.</returns> 3412 public static bool operator !=(in FixedList128Bytes<T> a, in FixedList64Bytes<T> b) 3413 { 3414 return !(a == b); 3415 } 3416 3417 /// <summary> 3418 /// Returns a number denoting whether this list should be placed before or after another list in a sort. 3419 /// </summary> 3420 /// <param name="other">A list to to compare with.</param> 3421 /// <returns>An integer denoting the respective sort position of the list relative to the other: 3422 /// 3423 /// 0 denotes that both lists should have the same position in a sort. 3424 /// -1 denotes that this list should precede the other list in a sort. 3425 /// +1 denotes that this list should follow the other list in a sort. 3426 /// </returns> 3427 public int CompareTo(FixedList64Bytes<T> other) 3428 { 3429 unsafe 3430 { 3431 byte* a = buffer; 3432 byte* b = other.buffer; 3433 var aa = a + FixedList.PaddingBytes<T>(); 3434 var bb = b + FixedList.PaddingBytes<T>(); 3435 var mini = math.min(Length, other.Length); 3436 for(var i = 0; i < mini; ++i) 3437 { 3438 var j = UnsafeUtility.MemCmp(aa + sizeof(T) * i, bb + sizeof(T) * i, sizeof(T)); 3439 if(j != 0) 3440 return j; 3441 } 3442 return Length.CompareTo(other.Length); 3443 } 3444 } 3445 3446 /// <summary> 3447 /// Returns true if this list and another list are equal. 3448 /// </summary> 3449 /// <remarks>Two lists are equal if their length and bytes are equal.</remarks> 3450 /// <param name="other">The list to compare for equality.</param> 3451 /// <returns>True if the two lists are equal.</returns> 3452 public bool Equals(FixedList64Bytes<T> other) 3453 { 3454 return CompareTo(other) == 0; 3455 } 3456 3457 3458 /// <summary> 3459 /// Initializes and returns an instance of FixedList128Bytes with content copied from another list. 3460 /// </summary> 3461 /// <param name="other">The list to copy.</param> 3462 /// <exception cref="IndexOutOfRangeException">Throws if the other list's length exceeds the capacity of FixedList128Bytes&lt;T&gt;.</exception> 3463 public FixedList128Bytes(in FixedList64Bytes<T> other) 3464 { 3465 this = default; 3466 var error = Initialize(other); 3467 if(error != 0) 3468 FixedList.CheckResize<FixedBytes128Align8,T>(other.Length); 3469 } 3470 3471 /// <summary> 3472 /// Initializes an instance of FixedList128Bytes with content copied from another list. 3473 /// </summary> 3474 /// <param name="other">The list to copy.</param> 3475 /// <returns>zero on success, or non-zero on error.</returns> 3476 internal int Initialize(in FixedList64Bytes<T> other) 3477 { 3478 if(other.Length > Capacity) 3479 return (int)CopyError.Truncation; 3480 length = other.length; 3481 unsafe 3482 { 3483 UnsafeUtility.MemCpy(Buffer, other.Buffer, LengthInBytes); 3484 } 3485 return 0; 3486 } 3487 3488 /// <summary> 3489 /// Returns a new list that is a copy of another list. 3490 /// </summary> 3491 /// <param name="other">The list to copy.</param> 3492 /// <returns>A new list that is a copy of the other.</returns> 3493 /// <exception cref="IndexOutOfRangeException">Throws if the other list's length exceeds the capacity of FixedList128Bytes&lt;T&gt;.</exception> 3494 public static implicit operator FixedList128Bytes<T>(in FixedList64Bytes<T> other) 3495 { 3496 return new FixedList128Bytes<T>(other); 3497 } 3498 3499 /// <summary> 3500 /// Returns true if two lists are equal. 3501 /// </summary> 3502 /// <remarks>Two lists are equal if their length and bytes are equal.</remarks> 3503 /// <param name="a">The first list to compare for equality.</param> 3504 /// <param name="b">The second list to compare for equality.</param> 3505 /// <returns>True if the two lists are equal.</returns> 3506 public static bool operator ==(in FixedList128Bytes<T> a, in FixedList128Bytes<T> b) 3507 { 3508 unsafe 3509 { 3510 if(a.length != b.length) 3511 return false; 3512 return UnsafeUtility.MemCmp(a.Buffer, b.Buffer, a.LengthInBytes) == 0; 3513 } 3514 } 3515 3516 /// <summary> 3517 /// Returns true if two lists are unequal. 3518 /// </summary> 3519 /// <remarks>Two lists are equal if their length and bytes are equal.</remarks> 3520 /// <param name="a">The first list to compare for inequality.</param> 3521 /// <param name="b">The second list to compare for inequality.</param> 3522 /// <returns>True if the two lists are unequal.</returns> 3523 public static bool operator !=(in FixedList128Bytes<T> a, in FixedList128Bytes<T> b) 3524 { 3525 return !(a == b); 3526 } 3527 3528 /// <summary> 3529 /// Returns a number denoting whether this list should be placed before or after another list in a sort. 3530 /// </summary> 3531 /// <param name="other">A list to to compare with.</param> 3532 /// <returns>An integer denoting the respective sort position of the list relative to the other: 3533 /// 3534 /// 0 denotes that both lists should have the same position in a sort. 3535 /// -1 denotes that this list should precede the other list in a sort. 3536 /// +1 denotes that this list should follow the other list in a sort. 3537 /// </returns> 3538 public int CompareTo(FixedList128Bytes<T> other) 3539 { 3540 unsafe 3541 { 3542 byte* a = buffer; 3543 byte* b = other.buffer; 3544 var aa = a + FixedList.PaddingBytes<T>(); 3545 var bb = b + FixedList.PaddingBytes<T>(); 3546 var mini = math.min(Length, other.Length); 3547 for(var i = 0; i < mini; ++i) 3548 { 3549 var j = UnsafeUtility.MemCmp(aa + sizeof(T) * i, bb + sizeof(T) * i, sizeof(T)); 3550 if(j != 0) 3551 return j; 3552 } 3553 return Length.CompareTo(other.Length); 3554 } 3555 } 3556 3557 /// <summary> 3558 /// Returns true if this list and another list are equal. 3559 /// </summary> 3560 /// <remarks>Two lists are equal if their length and bytes are equal.</remarks> 3561 /// <param name="other">The list to compare for equality.</param> 3562 /// <returns>True if the two lists are equal.</returns> 3563 public bool Equals(FixedList128Bytes<T> other) 3564 { 3565 return CompareTo(other) == 0; 3566 } 3567 3568 3569 /// <summary> 3570 /// Returns true if two lists are equal. 3571 /// </summary> 3572 /// <remarks>Two lists are equal if their length and bytes are equal.</remarks> 3573 /// <param name="a">The first list to compare for equality.</param> 3574 /// <param name="b">The second list to compare for equality.</param> 3575 /// <returns>True if the two lists are equal.</returns> 3576 public static bool operator ==(in FixedList128Bytes<T> a, in FixedList512Bytes<T> b) 3577 { 3578 unsafe 3579 { 3580 if(a.length != b.length) 3581 return false; 3582 return UnsafeUtility.MemCmp(a.Buffer, b.Buffer, a.LengthInBytes) == 0; 3583 } 3584 } 3585 3586 /// <summary> 3587 /// Returns true if two lists are unequal. 3588 /// </summary> 3589 /// <remarks>Two lists are equal if their length and bytes are equal.</remarks> 3590 /// <param name="a">The first list to compare for inequality.</param> 3591 /// <param name="b">The second list to compare for inequality.</param> 3592 /// <returns>True if the two lists are unequal.</returns> 3593 public static bool operator !=(in FixedList128Bytes<T> a, in FixedList512Bytes<T> b) 3594 { 3595 return !(a == b); 3596 } 3597 3598 /// <summary> 3599 /// Returns a number denoting whether this list should be placed before or after another list in a sort. 3600 /// </summary> 3601 /// <param name="other">A list to to compare with.</param> 3602 /// <returns>An integer denoting the respective sort position of the list relative to the other: 3603 /// 3604 /// 0 denotes that both lists should have the same position in a sort. 3605 /// -1 denotes that this list should precede the other list in a sort. 3606 /// +1 denotes that this list should follow the other list in a sort. 3607 /// </returns> 3608 public int CompareTo(FixedList512Bytes<T> other) 3609 { 3610 unsafe 3611 { 3612 byte* a = buffer; 3613 byte* b = other.buffer; 3614 var aa = a + FixedList.PaddingBytes<T>(); 3615 var bb = b + FixedList.PaddingBytes<T>(); 3616 var mini = math.min(Length, other.Length); 3617 for(var i = 0; i < mini; ++i) 3618 { 3619 var j = UnsafeUtility.MemCmp(aa + sizeof(T) * i, bb + sizeof(T) * i, sizeof(T)); 3620 if(j != 0) 3621 return j; 3622 } 3623 return Length.CompareTo(other.Length); 3624 } 3625 } 3626 3627 /// <summary> 3628 /// Returns true if this list and another list are equal. 3629 /// </summary> 3630 /// <remarks>Two lists are equal if their length and bytes are equal.</remarks> 3631 /// <param name="other">The list to compare for equality.</param> 3632 /// <returns>True if the two lists are equal.</returns> 3633 public bool Equals(FixedList512Bytes<T> other) 3634 { 3635 return CompareTo(other) == 0; 3636 } 3637 3638 3639 /// <summary> 3640 /// Initializes and returns an instance of FixedList128Bytes with content copied from another list. 3641 /// </summary> 3642 /// <param name="other">The list to copy.</param> 3643 /// <exception cref="IndexOutOfRangeException">Throws if the other list's length exceeds the capacity of FixedList128Bytes&lt;T&gt;.</exception> 3644 public FixedList128Bytes(in FixedList512Bytes<T> other) 3645 { 3646 this = default; 3647 var error = Initialize(other); 3648 if(error != 0) 3649 FixedList.CheckResize<FixedBytes128Align8,T>(other.Length); 3650 } 3651 3652 /// <summary> 3653 /// Initializes an instance of FixedList128Bytes with content copied from another list. 3654 /// </summary> 3655 /// <param name="other">The list to copy.</param> 3656 /// <returns>zero on success, or non-zero on error.</returns> 3657 internal int Initialize(in FixedList512Bytes<T> other) 3658 { 3659 if(other.Length > Capacity) 3660 return (int)CopyError.Truncation; 3661 length = other.length; 3662 unsafe 3663 { 3664 UnsafeUtility.MemCpy(Buffer, other.Buffer, LengthInBytes); 3665 } 3666 return 0; 3667 } 3668 3669 /// <summary> 3670 /// Returns a new list that is a copy of another list. 3671 /// </summary> 3672 /// <param name="other">The list to copy.</param> 3673 /// <returns>A new list that is a copy of the other.</returns> 3674 /// <exception cref="IndexOutOfRangeException">Throws if the other list's length exceeds the capacity of FixedList128Bytes&lt;T&gt;.</exception> 3675 public static implicit operator FixedList128Bytes<T>(in FixedList512Bytes<T> other) 3676 { 3677 return new FixedList128Bytes<T>(other); 3678 } 3679 3680 /// <summary> 3681 /// Returns true if two lists are equal. 3682 /// </summary> 3683 /// <remarks>Two lists are equal if their length and bytes are equal.</remarks> 3684 /// <param name="a">The first list to compare for equality.</param> 3685 /// <param name="b">The second list to compare for equality.</param> 3686 /// <returns>True if the two lists are equal.</returns> 3687 public static bool operator ==(in FixedList128Bytes<T> a, in FixedList4096Bytes<T> b) 3688 { 3689 unsafe 3690 { 3691 if(a.length != b.length) 3692 return false; 3693 return UnsafeUtility.MemCmp(a.Buffer, b.Buffer, a.LengthInBytes) == 0; 3694 } 3695 } 3696 3697 /// <summary> 3698 /// Returns true if two lists are unequal. 3699 /// </summary> 3700 /// <remarks>Two lists are equal if their length and bytes are equal.</remarks> 3701 /// <param name="a">The first list to compare for inequality.</param> 3702 /// <param name="b">The second list to compare for inequality.</param> 3703 /// <returns>True if the two lists are unequal.</returns> 3704 public static bool operator !=(in FixedList128Bytes<T> a, in FixedList4096Bytes<T> b) 3705 { 3706 return !(a == b); 3707 } 3708 3709 /// <summary> 3710 /// Returns a number denoting whether this list should be placed before or after another list in a sort. 3711 /// </summary> 3712 /// <param name="other">A list to to compare with.</param> 3713 /// <returns>An integer denoting the respective sort position of the list relative to the other: 3714 /// 3715 /// 0 denotes that both lists should have the same position in a sort. 3716 /// -1 denotes that this list should precede the other list in a sort. 3717 /// +1 denotes that this list should follow the other list in a sort. 3718 /// </returns> 3719 public int CompareTo(FixedList4096Bytes<T> other) 3720 { 3721 unsafe 3722 { 3723 byte* a = buffer; 3724 byte* b = other.buffer; 3725 var aa = a + FixedList.PaddingBytes<T>(); 3726 var bb = b + FixedList.PaddingBytes<T>(); 3727 var mini = math.min(Length, other.Length); 3728 for(var i = 0; i < mini; ++i) 3729 { 3730 var j = UnsafeUtility.MemCmp(aa + sizeof(T) * i, bb + sizeof(T) * i, sizeof(T)); 3731 if(j != 0) 3732 return j; 3733 } 3734 return Length.CompareTo(other.Length); 3735 } 3736 } 3737 3738 /// <summary> 3739 /// Returns true if this list and another list are equal. 3740 /// </summary> 3741 /// <remarks>Two lists are equal if their length and bytes are equal.</remarks> 3742 /// <param name="other">The list to compare for equality.</param> 3743 /// <returns>True if the two lists are equal.</returns> 3744 public bool Equals(FixedList4096Bytes<T> other) 3745 { 3746 return CompareTo(other) == 0; 3747 } 3748 3749 3750 /// <summary> 3751 /// Initializes and returns an instance of FixedList128Bytes with content copied from another list. 3752 /// </summary> 3753 /// <param name="other">The list to copy.</param> 3754 /// <exception cref="IndexOutOfRangeException">Throws if the other list's length exceeds the capacity of FixedList128Bytes&lt;T&gt;.</exception> 3755 public FixedList128Bytes(in FixedList4096Bytes<T> other) 3756 { 3757 this = default; 3758 var error = Initialize(other); 3759 if(error != 0) 3760 FixedList.CheckResize<FixedBytes128Align8,T>(other.Length); 3761 } 3762 3763 /// <summary> 3764 /// Initializes an instance of FixedList128Bytes with content copied from another list. 3765 /// </summary> 3766 /// <param name="other">The list to copy.</param> 3767 /// <returns>zero on success, or non-zero on error.</returns> 3768 internal int Initialize(in FixedList4096Bytes<T> other) 3769 { 3770 if(other.Length > Capacity) 3771 return (int)CopyError.Truncation; 3772 length = other.length; 3773 unsafe 3774 { 3775 UnsafeUtility.MemCpy(Buffer, other.Buffer, LengthInBytes); 3776 } 3777 return 0; 3778 } 3779 3780 /// <summary> 3781 /// Returns a new list that is a copy of another list. 3782 /// </summary> 3783 /// <param name="other">The list to copy.</param> 3784 /// <returns>A new list that is a copy of the other.</returns> 3785 /// <exception cref="IndexOutOfRangeException">Throws if the other list's length exceeds the capacity of FixedList128Bytes&lt;T&gt;.</exception> 3786 public static implicit operator FixedList128Bytes<T>(in FixedList4096Bytes<T> other) 3787 { 3788 return new FixedList128Bytes<T>(other); 3789 } 3790 3791 /// <summary> 3792 /// Returns true if the list is equal to an object. 3793 /// </summary> 3794 /// <remarks>Two lists are equal if their length and bytes are equal. 3795 /// 3796 /// A FixedList*N*&lt;T&gt; can only be equal to another FixedList*N*&lt;T&gt; with the same *N* and T. 3797 /// </remarks> 3798 /// <param name="obj">An object to compare for equality.</param> 3799 /// <returns>True if the list is equal to the object.</returns> 3800 [ExcludeFromBurstCompatTesting("Takes managed object")] 3801 public override bool Equals(object obj) 3802 { 3803 if(obj is FixedList32Bytes<T> aFixedList32Bytes) return Equals(aFixedList32Bytes); 3804 if(obj is FixedList64Bytes<T> aFixedList64Bytes) return Equals(aFixedList64Bytes); 3805 if(obj is FixedList128Bytes<T> aFixedList128Bytes) return Equals(aFixedList128Bytes); 3806 if(obj is FixedList512Bytes<T> aFixedList512Bytes) return Equals(aFixedList512Bytes); 3807 if(obj is FixedList4096Bytes<T> aFixedList4096Bytes) return Equals(aFixedList4096Bytes); 3808 return false; 3809 } 3810 3811 /// <summary> 3812 /// An enumerator over the elements of a FixedList128Bytes&lt;T&gt;. 3813 /// </summary> 3814 /// <remarks> 3815 /// In an enumerator's initial state, `Current` cannot be read. The first <see cref="MoveNext"/> call advances the enumerator to the first element. 3816 /// </remarks> 3817 public struct Enumerator : IEnumerator<T> 3818 { 3819 FixedList128Bytes<T> m_List; 3820 int m_Index; 3821 3822 /// <summary> 3823 /// Initializes and returns an instance of FixedList128Bytes&lt;T&gt;. 3824 /// </summary> 3825 /// <param name="list">The list for which to create an enumerator.</param> 3826 public Enumerator(ref FixedList128Bytes<T> list) 3827 { 3828 m_List = list; 3829 m_Index = -1; 3830 } 3831 3832 /// <summary> 3833 /// Does nothing. 3834 /// </summary> 3835 public void Dispose() 3836 { 3837 } 3838 3839 /// <summary> 3840 /// Advances the enumerator to the next element. 3841 /// </summary> 3842 /// <returns>True if <see cref="Current"/> is valid to read after the call.</returns> 3843 [MethodImpl(MethodImplOptions.AggressiveInlining)] 3844 public bool MoveNext() 3845 { 3846 m_Index++; 3847 return m_Index < m_List.Length; 3848 } 3849 3850 /// <summary> 3851 /// Resets the enumerator to its initial state. 3852 /// </summary> 3853 public void Reset() 3854 { 3855 m_Index = -1; 3856 } 3857 3858 /// <summary> 3859 /// The current element. 3860 /// </summary> 3861 /// <value>The current element.</value> 3862 public T Current 3863 { 3864 [MethodImpl(MethodImplOptions.AggressiveInlining)] 3865 get => m_List[m_Index]; // Let FixedList128Bytes<T> indexer check for out of range. 3866 } 3867 3868 object IEnumerator.Current => Current; 3869 } 3870 3871 /// <summary> 3872 /// Returns an enumerator for iterating over the elements of this list. 3873 /// </summary> 3874 /// <returns>An enumerator for iterating over the elements of this list.</returns> 3875 public Enumerator GetEnumerator() 3876 { 3877 return new Enumerator(ref this); 3878 } 3879 3880 /// <summary> 3881 /// This method is not implemented. Use <see cref="GetEnumerator"/> instead. 3882 /// </summary> 3883 /// <returns>Nothing because it always throws <see cref="NotImplementedException"/>.</returns> 3884 /// <exception cref="NotImplementedException">Method is not implemented.</exception> 3885 IEnumerator IEnumerable.GetEnumerator() 3886 { 3887 throw new NotImplementedException(); 3888 } 3889 3890 /// <summary> 3891 /// This method is not implemented. Use <see cref="GetEnumerator"/> instead. 3892 /// </summary> 3893 /// <returns>Nothing because it always throws <see cref="NotImplementedException"/>.</returns> 3894 /// <exception cref="NotImplementedException">Method is not implemented.</exception> 3895 IEnumerator<T> IEnumerable<T>.GetEnumerator() 3896 { 3897 throw new NotImplementedException(); 3898 } 3899 } 3900 3901 /// <summary> 3902 /// Provides extension methods for FixedList128Bytes. 3903 /// </summary> 3904 [GenerateTestsForBurstCompatibility] 3905 public unsafe static class FixedList128BytesExtensions 3906 { 3907 /// <summary> 3908 /// Finds the index of the first occurrence of a particular value in this list. 3909 /// </summary> 3910 /// <typeparam name="T">The type of elements in this list.</typeparam> 3911 /// <typeparam name="U">The value type.</typeparam> 3912 /// <param name="list">The list to search.</param> 3913 /// <param name="value">The value to locate.</param> 3914 /// <returns>The index of the first occurrence of the value. Returns -1 if no occurrence is found.</returns> 3915 [GenerateTestsForBurstCompatibility(GenericTypeArguments = new [] { typeof(int), typeof(int) })] 3916 public static int IndexOf<T, U>(this ref FixedList128Bytes<T> list, U value) where T : unmanaged, IEquatable<U> 3917 { 3918 return NativeArrayExtensions.IndexOf<T, U>(list.Buffer, list.Length, value); 3919 } 3920 3921 /// <summary> 3922 /// Returns true if a particular value is present in this list. 3923 /// </summary> 3924 /// <typeparam name="T">The type of elements in this list.</typeparam> 3925 /// <typeparam name="U">The value type.</typeparam> 3926 /// <param name="list">The list to search.</param> 3927 /// <param name="value">The value to locate.</param> 3928 /// <returns>True if the value is present in this list.</returns> 3929 [GenerateTestsForBurstCompatibility(GenericTypeArguments = new [] { typeof(int), typeof(int) })] 3930 public static bool Contains<T, U>(this ref FixedList128Bytes<T> list, U value) where T : unmanaged, IEquatable<U> 3931 { 3932 return list.IndexOf(value) != -1; 3933 } 3934 3935 /// <summary> 3936 /// Removes the first occurrence of a particular value in this list. 3937 /// </summary> 3938 /// <remarks> 3939 /// If a value is removed, all elements after it are shifted down by one, and the list's length is decremented by one. 3940 /// 3941 /// If you don't need to preserve the order of the remaining elements, <see cref="Unity.Collections.FixedList128BytesExtensions.RemoveSwapBack{T, U}"/> is a cheaper alternative. 3942 /// </remarks> 3943 /// <typeparam name="T">The type of elements in this list.</typeparam> 3944 /// <typeparam name="U">The value type.</typeparam> 3945 /// <param name="list">The list to search.</param> 3946 /// <param name="value">The value to locate and remove.</param> 3947 /// <returns>True if the value was found and removed.</returns> 3948 [GenerateTestsForBurstCompatibility(GenericTypeArguments = new [] { typeof(int), typeof(int) })] 3949 public static bool Remove<T, U>(this ref FixedList128Bytes<T> list, U value) where T : unmanaged, IEquatable<U> 3950 { 3951 int index = list.IndexOf(value); 3952 if (index < 0) 3953 { 3954 return false; 3955 } 3956 3957 list.RemoveAt(index); 3958 3959 return true; 3960 } 3961 3962 /// <summary> 3963 /// Removes the first occurrence of a particular value in this list. 3964 /// </summary> 3965 /// <remarks> 3966 /// 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. 3967 /// 3968 /// This is cheaper than <see cref="Remove"/>, but the order of the remaining elements is not preserved. 3969 /// </remarks> 3970 /// <typeparam name="T">The type of elements in this list.</typeparam> 3971 /// <typeparam name="U">The value type.</typeparam> 3972 /// <param name="list">The list to search.</param> 3973 /// <param name="value">The value to locate and remove.</param> 3974 /// <returns>Returns true if the item is removed.</returns> 3975 [GenerateTestsForBurstCompatibility(GenericTypeArguments = new [] { typeof(int), typeof(int) })] 3976 public static bool RemoveSwapBack<T, U>(this ref FixedList128Bytes<T> list, U value) where T : unmanaged, IEquatable<U> 3977 { 3978 var index = list.IndexOf(value); 3979 if (index == -1) 3980 { 3981 return false; 3982 } 3983 3984 list.RemoveAtSwapBack(index); 3985 3986 return true; 3987 } 3988 } 3989 3990 sealed class FixedList128BytesDebugView<T> where T : unmanaged 3991 { 3992 FixedList128Bytes<T> m_List; 3993 public FixedList128BytesDebugView(FixedList128Bytes<T> list) 3994 { 3995 m_List = list; 3996 } 3997 public T[] Items => m_List.ToArray(); 3998 } 3999 /// <summary> 4000 /// An unmanaged, resizable list whose content is all stored directly in the 512-byte struct. Useful for small lists. 4001 /// </summary> 4002 /// <typeparam name="T">The type of the elements.</typeparam> 4003 [Serializable] 4004 [DebuggerTypeProxy(typeof(FixedList512BytesDebugView<>))] 4005 [GenerateTestsForBurstCompatibility(GenericTypeArguments = new [] { typeof(int) })] 4006 public struct FixedList512Bytes<T> 4007 : INativeList<T> 4008 , IEnumerable<T> // Used by collection initializers. 4009 , IEquatable<FixedList32Bytes<T>> 4010 , IComparable<FixedList32Bytes<T>> 4011 , IEquatable<FixedList64Bytes<T>> 4012 , IComparable<FixedList64Bytes<T>> 4013 , IEquatable<FixedList128Bytes<T>> 4014 , IComparable<FixedList128Bytes<T>> 4015 , IEquatable<FixedList512Bytes<T>> 4016 , IComparable<FixedList512Bytes<T>> 4017 , IEquatable<FixedList4096Bytes<T>> 4018 , IComparable<FixedList4096Bytes<T>> 4019 where T : unmanaged 4020 { 4021 [SerializeField] internal FixedBytes512Align8 data; 4022 4023 internal ushort length 4024 { 4025 [MethodImpl(MethodImplOptions.AggressiveInlining)] 4026 readonly get 4027 { 4028 unsafe 4029 { 4030 fixed(void* ptr = &data) 4031 return *((ushort*)ptr); 4032 } 4033 } 4034 4035 [MethodImpl(MethodImplOptions.AggressiveInlining)] 4036 set 4037 { 4038 unsafe 4039 { 4040 fixed (void* ptr = &data) 4041 *((ushort*)ptr) = value; 4042 } 4043 } 4044 } 4045 4046 internal readonly unsafe byte* buffer 4047 { 4048 [MethodImpl(MethodImplOptions.AggressiveInlining)] 4049 get 4050 { 4051 unsafe 4052 { 4053 fixed (void* ptr = &data) 4054 return ((byte*)ptr) + UnsafeUtility.SizeOf<ushort>(); 4055 } 4056 } 4057 } 4058 4059 /// <summary> 4060 /// The current number of items in this list. 4061 /// </summary> 4062 /// <value>The current number of items in this list.</value> 4063 [CreateProperty] 4064 public int Length 4065 { 4066 [MethodImpl(MethodImplOptions.AggressiveInlining)] 4067 readonly get => length; 4068 set 4069 { 4070 FixedList.CheckResize<FixedBytes512Align8,T>(value); 4071 length = (ushort)value; 4072 } 4073 } 4074 4075 /// <summary> 4076 /// A property in order to display items in the Entity Inspector. 4077 /// </summary> 4078 [CreateProperty] IEnumerable<T> Elements => this.ToArray(); 4079 4080 /// <summary> 4081 /// Whether this list is empty. 4082 /// </summary> 4083 /// <value>True if this string has no characters or if the container has not been constructed.</value> 4084 public readonly bool IsEmpty 4085 { 4086 [MethodImpl(MethodImplOptions.AggressiveInlining)] 4087 get => Length == 0; 4088 } 4089 4090 internal int LengthInBytes => Length * UnsafeUtility.SizeOf<T>(); 4091 4092 /// <summary> 4093 /// Returns a pointer to the first element of the list buffer. 4094 /// </summary> 4095 /// <remarks> 4096 /// The pointer returned by this method points into the internals of the target list object. It is the 4097 /// caller's responsibility to ensure that the pointer is not used after the list is destroyed or goes 4098 /// out of scope. 4099 /// </remarks> 4100 /// <returns>A pointer to the first element of the list buffer.</returns> 4101 internal readonly unsafe byte* Buffer 4102 { 4103 [MethodImpl(MethodImplOptions.AggressiveInlining)] 4104 get 4105 { 4106 return buffer + FixedList.PaddingBytes<T>(); 4107 } 4108 } 4109 4110 /// <summary> 4111 /// The number of elements that can fit in this list. 4112 /// </summary> 4113 /// <value>The number of elements that can fit in this list.</value> 4114 /// <remarks>The capacity of a FixedList cannot be changed. The setter is included only for conformity with <see cref="INativeList{T}"/>.</remarks> 4115 /// <exception cref="ArgumentOutOfRangeException">Thrown if the new value does not match the current capacity.</exception> 4116 public int Capacity 4117 { 4118 [MethodImpl(MethodImplOptions.AggressiveInlining)] 4119 readonly get 4120 { 4121 return FixedList.Capacity<FixedBytes512Align8,T>(); 4122 } 4123 4124 set 4125 { 4126 CollectionHelper.CheckCapacityInRange(value, Length); 4127 } 4128 } 4129 4130 /// <summary> 4131 /// The element at a given index. 4132 /// </summary> 4133 /// <param name="index">An index.</param> 4134 /// <value>The value to store at the index.</value> 4135 /// <exception cref="IndexOutOfRangeException">Thrown if the index is out of bounds.</exception> 4136 public T this[int index] 4137 { 4138 [MethodImpl(MethodImplOptions.AggressiveInlining)] 4139 readonly get 4140 { 4141 CollectionHelper.CheckIndexInRange(index, length); 4142 unsafe 4143 { 4144 return UnsafeUtility.ReadArrayElement<T>(Buffer, CollectionHelper.AssumePositive(index)); 4145 } 4146 } 4147 4148 [MethodImpl(MethodImplOptions.AggressiveInlining)] 4149 set 4150 { 4151 CollectionHelper.CheckIndexInRange(index, length); 4152 unsafe 4153 { 4154 UnsafeUtility.WriteArrayElement<T>(Buffer, CollectionHelper.AssumePositive(index), value); 4155 } 4156 } 4157 } 4158 4159 /// <summary> 4160 /// Returns the element at a given index. 4161 /// </summary> 4162 /// <param name="index">An index.</param> 4163 /// <returns>The list element at the index.</returns> 4164 [MethodImpl(MethodImplOptions.AggressiveInlining)] 4165 public ref T ElementAt(int index) 4166 { 4167 CollectionHelper.CheckIndexInRange(index, length); 4168 unsafe 4169 { 4170 return ref UnsafeUtility.ArrayElementAsRef<T>(Buffer, index); 4171 } 4172 } 4173 4174 /// <summary> 4175 /// Returns the hash code of this list. 4176 /// </summary> 4177 /// <remarks> 4178 /// 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> 4179 /// <returns>The hash code of this list.</returns> 4180 public override int GetHashCode() 4181 { 4182 unsafe 4183 { 4184 return (int)CollectionHelper.Hash(Buffer, LengthInBytes); 4185 } 4186 } 4187 4188 /// <summary> 4189 /// Appends an element to the end of this list. Increments the length by 1. 4190 /// </summary> 4191 /// <remarks> 4192 /// The same as <see cref="AddNoResize"/>. Included only for consistency with the other list types. 4193 /// If the element exceeds the capacity, throws cref="IndexOutOfRangeException", and the list is unchanged. 4194 /// </remarks> 4195 /// <param name="item">The element to append at the end of the list.</param> 4196 /// <exception cref="IndexOutOfRangeException">Thrown if the append exceeds the capacity.</exception> 4197 public void Add(in T item) => AddNoResize(in item); 4198 4199 /// <summary> 4200 /// Appends elements from a buffer to the end of this list. Increments the length by the number of appended elements. 4201 /// </summary> 4202 /// <remarks> 4203 /// The same as <see cref="AddRangeNoResize"/>. Included only for consistency with the other list types. 4204 /// If the elements exceeds the capacity, throws cref="IndexOutOfRangeException", and the list is unchanged. 4205 /// </remarks> 4206 /// <param name="ptr">A buffer.</param> 4207 /// <param name="length">The number of elements from the buffer to append.</param> 4208 /// <exception cref="IndexOutOfRangeException">Thrown if the append exceeds the capacity.</exception> 4209 public unsafe void AddRange(void* ptr, int length) => AddRangeNoResize(ptr, length); 4210 4211 /// <summary> 4212 /// Appends an element to the end of this list. Increments the length by 1. 4213 /// </summary> 4214 /// <remarks> 4215 /// If the element exceeds the capacity, throws cref="IndexOutOfRangeException", and the list is unchanged. 4216 /// </remarks> 4217 /// <param name="item">The element to append at the end of the list.</param> 4218 /// <exception cref="IndexOutOfRangeException">Thrown if the append exceeds the capacity.</exception> 4219 [MethodImpl(MethodImplOptions.AggressiveInlining)] 4220 public void AddNoResize(in T item) 4221 { 4222 this[Length++] = item; 4223 } 4224 4225 /// <summary> 4226 /// Appends elements from a buffer to the end of this list. Increments the length by the number of appended elements. 4227 /// </summary> 4228 /// <remarks> 4229 /// If the elements exceeds the capacity, throws cref="IndexOutOfRangeException", and the list is unchanged. 4230 /// </remarks> 4231 /// <param name="ptr">A buffer.</param> 4232 /// <param name="length">The number of elements from the buffer to append.</param> 4233 /// <exception cref="IndexOutOfRangeException">Thrown if the append exceeds the capacity.</exception> 4234 public unsafe void AddRangeNoResize(void* ptr, int length) 4235 { 4236 var idx = Length; 4237 Length += length; 4238 UnsafeUtility.MemCpy((T*)Buffer + idx, ptr, UnsafeUtility.SizeOf<T>() * length); 4239 } 4240 4241 /// <summary> 4242 /// Appends value count times to the end of this list. 4243 /// </summary> 4244 /// <param name="value">The value to add to the end of this list.</param> 4245 /// <param name="count">The number of times to replicate the value.</param> 4246 /// <exception cref="IndexOutOfRangeException">Thrown if the append exceeds the capacity.</exception> 4247 public unsafe void AddReplicate(in T value, int count) 4248 { 4249 var idx = Length; 4250 Length += count; 4251 fixed (T* ptr = &value) 4252 UnsafeUtility.MemCpyReplicate((T*)Buffer + idx, ptr, UnsafeUtility.SizeOf<T>(), count); 4253 } 4254 4255 /// <summary> 4256 /// Sets the length to 0. 4257 /// </summary> 4258 /// <remarks> Does *not* zero out the bytes.</remarks> 4259 public void Clear() 4260 { 4261 Length = 0; 4262 } 4263 4264 /// <summary> 4265 /// Shifts elements toward the end of this list, increasing its length. 4266 /// </summary> 4267 /// <remarks> 4268 /// Right-shifts elements in the list so as to create 'free' slots at the beginning or in the middle. 4269 /// 4270 /// The length is increased by `end - begin`. 4271 /// 4272 /// If `end` equals `begin`, the method does nothing. 4273 /// 4274 /// 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. 4275 /// 4276 /// The indexes `begin` up to `end` are not cleared: they will contain whatever values they held prior. 4277 /// </remarks> 4278 /// <param name="begin">The index of the first element that will be shifted up.</param> 4279 /// <param name="end">The index where the first shifted element will end up.</param> 4280 /// <exception cref="IndexOutOfRangeException">Thrown if the new length exceeds the capacity.</exception> 4281 public void InsertRangeWithBeginEnd(int begin, int end) 4282 { 4283 int items = end - begin; 4284 if(items < 1) 4285 return; 4286 int itemsToCopy = length - begin; 4287 Length += items; 4288 if(itemsToCopy < 1) 4289 return; 4290 int bytesToCopy = itemsToCopy * UnsafeUtility.SizeOf<T>(); 4291 unsafe 4292 { 4293 byte *b = Buffer; 4294 byte *dest = b + end * UnsafeUtility.SizeOf<T>(); 4295 byte *src = b + begin * UnsafeUtility.SizeOf<T>(); 4296 UnsafeUtility.MemMove(dest, src, bytesToCopy); 4297 } 4298 } 4299 4300 /// <summary> 4301 /// Shifts elements toward the end of this list, increasing its length. 4302 /// </summary> 4303 /// <remarks> 4304 /// Right-shifts elements in the list so as to create 'free' slots at the beginning or in the middle. 4305 /// 4306 /// The length is increased by `count`. If necessary, the capacity will be increased accordingly. 4307 /// 4308 /// If `count` equals `0`, the method does nothing. 4309 /// 4310 /// 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. 4311 /// 4312 /// The indexes `index` up to `index + count` are not cleared: they will contain whatever values they held prior. 4313 /// </remarks> 4314 /// <param name="index">The index of the first element that will be shifted up.</param> 4315 /// <param name="count">The number of elements to insert.</param> 4316 /// <exception cref="ArgumentException">Thrown if `count` is negative.</exception> 4317 /// <exception cref="ArgumentOutOfRangeException">Thrown if `index` is out of bounds.</exception> 4318 public void InsertRange(int index, int count) => InsertRangeWithBeginEnd(index, index + count); 4319 4320 /// <summary> 4321 /// Inserts a single element at an index. Increments the length by 1. 4322 /// </summary> 4323 /// <param name="index">The index at which to insert the element.</param> 4324 /// <param name="item">The element to insert.</param> 4325 /// <exception cref="ArgumentOutOfRangeException">Thrown if the index is out of bounds.</exception> 4326 public void Insert(int index, in T item) 4327 { 4328 InsertRangeWithBeginEnd(index, index+1); 4329 this[index] = item; 4330 } 4331 4332 /// <summary> 4333 /// Copies the last element of this list to an index. Decrements the length by 1. 4334 /// </summary> 4335 /// <remarks>Useful as a cheap way to remove elements from a list when you don't care about preserving order.</remarks> 4336 /// <param name="index">The index to overwrite with the last element.</param> 4337 /// <exception cref="ArgumentOutOfRangeException">Thrown if the index is out of bounds.</exception> 4338 public void RemoveAtSwapBack(int index) 4339 { 4340 RemoveRangeSwapBack(index, 1); 4341 } 4342 4343 /// <summary> 4344 /// Copies the last *N* elements of this list to a range in this list. Decrements the length by *N*. 4345 /// </summary> 4346 /// <remarks> 4347 /// Copies the last `count`-numbered elements to the range starting at `index`. 4348 /// 4349 /// Useful as a cheap way to remove elements from a list when you don't care about preserving order. 4350 /// 4351 /// Does nothing if the count is less than 1. 4352 /// </remarks> 4353 /// <param name="index">The first index of the destination range.</param> 4354 /// <param name="count">The number of elements to copy and the amount by which to decrement the length.</param> 4355 /// <exception cref="ArgumentOutOfRangeException">Thrown if the index is out of bounds.</exception> 4356 public void RemoveRangeSwapBack(int index, int count) 4357 { 4358 if (count > 0) 4359 { 4360 int copyFrom = math.max(Length - count, index + count); 4361 4362 unsafe 4363 { 4364 var sizeOf = UnsafeUtility.SizeOf<T>(); 4365 void* dst = Buffer + index * sizeOf; 4366 void* src = Buffer + copyFrom * sizeOf; 4367 UnsafeUtility.MemCpy(dst, src, (Length - copyFrom) * sizeOf); 4368 } 4369 4370 Length -= count; 4371 } 4372 } 4373 4374 /// <summary> 4375 /// Removes the element at an index. Shifts everything above the index down by one and decrements the length by 1. 4376 /// </summary> 4377 /// <param name="index">The index of the element to remove.</param> 4378 /// <remarks> 4379 /// If you don't care about preserving the order of the elements, `RemoveAtSwapBack` is a more efficient way to remove an element. 4380 /// </remarks> 4381 /// <exception cref="ArgumentOutOfRangeException">Thrown if the index is out of bounds.</exception> 4382 public void RemoveAt(int index) 4383 { 4384 RemoveRange(index, 1); 4385 } 4386 4387 /// <summary> 4388 /// Removes *N* elements of a range. Shifts everything above the range down by *N* and decrements the length by *N*. 4389 /// </summary> 4390 /// <remarks> 4391 /// If you don't care about preserving the order of the elements, `RemoveAtSwapBack` is a more efficient way to remove elements. 4392 /// </remarks> 4393 /// <param name="index">The first index of the range to remove.</param> 4394 /// <param name="count">The number of elements to remove.</param> 4395 /// <exception cref="ArgumentOutOfRangeException">Thrown if the index is out of bounds.</exception> 4396 public void RemoveRange(int index, int count) 4397 { 4398 if (count > 0) 4399 { 4400 int copyFrom = math.min(index + count, Length); 4401 4402 unsafe 4403 { 4404 var sizeOf = UnsafeUtility.SizeOf<T>(); 4405 void* dst = Buffer + index * sizeOf; 4406 void* src = Buffer + copyFrom * sizeOf; 4407 UnsafeUtility.MemCpy(dst, src, (Length - copyFrom) * sizeOf); 4408 } 4409 4410 Length -= count; 4411 } 4412 } 4413 4414 /// <summary> 4415 /// Returns a managed array that is a copy of this list. 4416 /// </summary> 4417 /// <returns>A managed array that is a copy of this list.</returns> 4418 [ExcludeFromBurstCompatTesting("Returns managed array")] 4419 public T[] ToArray() 4420 { 4421 var result = new T[Length]; 4422 unsafe 4423 { 4424 byte* s = Buffer; 4425 fixed(T* d = result) 4426 UnsafeUtility.MemCpy(d, s, LengthInBytes); 4427 } 4428 return result; 4429 } 4430 4431 /// <summary> 4432 /// Returns an array that is a copy of this list. 4433 /// </summary> 4434 /// <param name="allocator">The allocator to use.</param> 4435 /// <returns>An array that is a copy of this list.</returns> 4436 public NativeArray<T> ToNativeArray(AllocatorManager.AllocatorHandle allocator) 4437 { 4438 unsafe 4439 { 4440 var copy = CollectionHelper.CreateNativeArray<T>(Length, allocator, NativeArrayOptions.UninitializedMemory); 4441 UnsafeUtility.MemCpy(copy.GetUnsafePtr(), Buffer, LengthInBytes); 4442 return copy; 4443 } 4444 } 4445 4446 4447 /// <summary> 4448 /// Returns true if two lists are equal. 4449 /// </summary> 4450 /// <remarks>Two lists are equal if their length and bytes are equal.</remarks> 4451 /// <param name="a">The first list to compare for equality.</param> 4452 /// <param name="b">The second list to compare for equality.</param> 4453 /// <returns>True if the two lists are equal.</returns> 4454 public static bool operator ==(in FixedList512Bytes<T> a, in FixedList32Bytes<T> b) 4455 { 4456 unsafe 4457 { 4458 if(a.length != b.length) 4459 return false; 4460 return UnsafeUtility.MemCmp(a.Buffer, b.Buffer, a.LengthInBytes) == 0; 4461 } 4462 } 4463 4464 /// <summary> 4465 /// Returns true if two lists are unequal. 4466 /// </summary> 4467 /// <remarks>Two lists are equal if their length and bytes are equal.</remarks> 4468 /// <param name="a">The first list to compare for inequality.</param> 4469 /// <param name="b">The second list to compare for inequality.</param> 4470 /// <returns>True if the two lists are unequal.</returns> 4471 public static bool operator !=(in FixedList512Bytes<T> a, in FixedList32Bytes<T> b) 4472 { 4473 return !(a == b); 4474 } 4475 4476 /// <summary> 4477 /// Returns a number denoting whether this list should be placed before or after another list in a sort. 4478 /// </summary> 4479 /// <param name="other">A list to to compare with.</param> 4480 /// <returns>An integer denoting the respective sort position of the list relative to the other: 4481 /// 4482 /// 0 denotes that both lists should have the same position in a sort. 4483 /// -1 denotes that this list should precede the other list in a sort. 4484 /// +1 denotes that this list should follow the other list in a sort. 4485 /// </returns> 4486 public int CompareTo(FixedList32Bytes<T> other) 4487 { 4488 unsafe 4489 { 4490 byte* a = buffer; 4491 byte* b = other.buffer; 4492 var aa = a + FixedList.PaddingBytes<T>(); 4493 var bb = b + FixedList.PaddingBytes<T>(); 4494 var mini = math.min(Length, other.Length); 4495 for(var i = 0; i < mini; ++i) 4496 { 4497 var j = UnsafeUtility.MemCmp(aa + sizeof(T) * i, bb + sizeof(T) * i, sizeof(T)); 4498 if(j != 0) 4499 return j; 4500 } 4501 return Length.CompareTo(other.Length); 4502 } 4503 } 4504 4505 /// <summary> 4506 /// Returns true if this list and another list are equal. 4507 /// </summary> 4508 /// <remarks>Two lists are equal if their length and bytes are equal.</remarks> 4509 /// <param name="other">The list to compare for equality.</param> 4510 /// <returns>True if the two lists are equal.</returns> 4511 public bool Equals(FixedList32Bytes<T> other) 4512 { 4513 return CompareTo(other) == 0; 4514 } 4515 4516 4517 /// <summary> 4518 /// Initializes and returns an instance of FixedList512Bytes with content copied from another list. 4519 /// </summary> 4520 /// <param name="other">The list to copy.</param> 4521 /// <exception cref="IndexOutOfRangeException">Throws if the other list's length exceeds the capacity of FixedList512Bytes&lt;T&gt;.</exception> 4522 public FixedList512Bytes(in FixedList32Bytes<T> other) 4523 { 4524 this = default; 4525 var error = Initialize(other); 4526 if(error != 0) 4527 FixedList.CheckResize<FixedBytes512Align8,T>(other.Length); 4528 } 4529 4530 /// <summary> 4531 /// Initializes an instance of FixedList512Bytes with content copied from another list. 4532 /// </summary> 4533 /// <param name="other">The list to copy.</param> 4534 /// <returns>zero on success, or non-zero on error.</returns> 4535 internal int Initialize(in FixedList32Bytes<T> other) 4536 { 4537 if(other.Length > Capacity) 4538 return (int)CopyError.Truncation; 4539 length = other.length; 4540 unsafe 4541 { 4542 UnsafeUtility.MemCpy(Buffer, other.Buffer, LengthInBytes); 4543 } 4544 return 0; 4545 } 4546 4547 /// <summary> 4548 /// Returns a new list that is a copy of another list. 4549 /// </summary> 4550 /// <param name="other">The list to copy.</param> 4551 /// <returns>A new list that is a copy of the other.</returns> 4552 /// <exception cref="IndexOutOfRangeException">Throws if the other list's length exceeds the capacity of FixedList512Bytes&lt;T&gt;.</exception> 4553 public static implicit operator FixedList512Bytes<T>(in FixedList32Bytes<T> other) 4554 { 4555 return new FixedList512Bytes<T>(other); 4556 } 4557 4558 /// <summary> 4559 /// Returns true if two lists are equal. 4560 /// </summary> 4561 /// <remarks>Two lists are equal if their length and bytes are equal.</remarks> 4562 /// <param name="a">The first list to compare for equality.</param> 4563 /// <param name="b">The second list to compare for equality.</param> 4564 /// <returns>True if the two lists are equal.</returns> 4565 public static bool operator ==(in FixedList512Bytes<T> a, in FixedList64Bytes<T> b) 4566 { 4567 unsafe 4568 { 4569 if(a.length != b.length) 4570 return false; 4571 return UnsafeUtility.MemCmp(a.Buffer, b.Buffer, a.LengthInBytes) == 0; 4572 } 4573 } 4574 4575 /// <summary> 4576 /// Returns true if two lists are unequal. 4577 /// </summary> 4578 /// <remarks>Two lists are equal if their length and bytes are equal.</remarks> 4579 /// <param name="a">The first list to compare for inequality.</param> 4580 /// <param name="b">The second list to compare for inequality.</param> 4581 /// <returns>True if the two lists are unequal.</returns> 4582 public static bool operator !=(in FixedList512Bytes<T> a, in FixedList64Bytes<T> b) 4583 { 4584 return !(a == b); 4585 } 4586 4587 /// <summary> 4588 /// Returns a number denoting whether this list should be placed before or after another list in a sort. 4589 /// </summary> 4590 /// <param name="other">A list to to compare with.</param> 4591 /// <returns>An integer denoting the respective sort position of the list relative to the other: 4592 /// 4593 /// 0 denotes that both lists should have the same position in a sort. 4594 /// -1 denotes that this list should precede the other list in a sort. 4595 /// +1 denotes that this list should follow the other list in a sort. 4596 /// </returns> 4597 public int CompareTo(FixedList64Bytes<T> other) 4598 { 4599 unsafe 4600 { 4601 byte* a = buffer; 4602 byte* b = other.buffer; 4603 var aa = a + FixedList.PaddingBytes<T>(); 4604 var bb = b + FixedList.PaddingBytes<T>(); 4605 var mini = math.min(Length, other.Length); 4606 for(var i = 0; i < mini; ++i) 4607 { 4608 var j = UnsafeUtility.MemCmp(aa + sizeof(T) * i, bb + sizeof(T) * i, sizeof(T)); 4609 if(j != 0) 4610 return j; 4611 } 4612 return Length.CompareTo(other.Length); 4613 } 4614 } 4615 4616 /// <summary> 4617 /// Returns true if this list and another list are equal. 4618 /// </summary> 4619 /// <remarks>Two lists are equal if their length and bytes are equal.</remarks> 4620 /// <param name="other">The list to compare for equality.</param> 4621 /// <returns>True if the two lists are equal.</returns> 4622 public bool Equals(FixedList64Bytes<T> other) 4623 { 4624 return CompareTo(other) == 0; 4625 } 4626 4627 4628 /// <summary> 4629 /// Initializes and returns an instance of FixedList512Bytes with content copied from another list. 4630 /// </summary> 4631 /// <param name="other">The list to copy.</param> 4632 /// <exception cref="IndexOutOfRangeException">Throws if the other list's length exceeds the capacity of FixedList512Bytes&lt;T&gt;.</exception> 4633 public FixedList512Bytes(in FixedList64Bytes<T> other) 4634 { 4635 this = default; 4636 var error = Initialize(other); 4637 if(error != 0) 4638 FixedList.CheckResize<FixedBytes512Align8,T>(other.Length); 4639 } 4640 4641 /// <summary> 4642 /// Initializes an instance of FixedList512Bytes with content copied from another list. 4643 /// </summary> 4644 /// <param name="other">The list to copy.</param> 4645 /// <returns>zero on success, or non-zero on error.</returns> 4646 internal int Initialize(in FixedList64Bytes<T> other) 4647 { 4648 if(other.Length > Capacity) 4649 return (int)CopyError.Truncation; 4650 length = other.length; 4651 unsafe 4652 { 4653 UnsafeUtility.MemCpy(Buffer, other.Buffer, LengthInBytes); 4654 } 4655 return 0; 4656 } 4657 4658 /// <summary> 4659 /// Returns a new list that is a copy of another list. 4660 /// </summary> 4661 /// <param name="other">The list to copy.</param> 4662 /// <returns>A new list that is a copy of the other.</returns> 4663 /// <exception cref="IndexOutOfRangeException">Throws if the other list's length exceeds the capacity of FixedList512Bytes&lt;T&gt;.</exception> 4664 public static implicit operator FixedList512Bytes<T>(in FixedList64Bytes<T> other) 4665 { 4666 return new FixedList512Bytes<T>(other); 4667 } 4668 4669 /// <summary> 4670 /// Returns true if two lists are equal. 4671 /// </summary> 4672 /// <remarks>Two lists are equal if their length and bytes are equal.</remarks> 4673 /// <param name="a">The first list to compare for equality.</param> 4674 /// <param name="b">The second list to compare for equality.</param> 4675 /// <returns>True if the two lists are equal.</returns> 4676 public static bool operator ==(in FixedList512Bytes<T> a, in FixedList128Bytes<T> b) 4677 { 4678 unsafe 4679 { 4680 if(a.length != b.length) 4681 return false; 4682 return UnsafeUtility.MemCmp(a.Buffer, b.Buffer, a.LengthInBytes) == 0; 4683 } 4684 } 4685 4686 /// <summary> 4687 /// Returns true if two lists are unequal. 4688 /// </summary> 4689 /// <remarks>Two lists are equal if their length and bytes are equal.</remarks> 4690 /// <param name="a">The first list to compare for inequality.</param> 4691 /// <param name="b">The second list to compare for inequality.</param> 4692 /// <returns>True if the two lists are unequal.</returns> 4693 public static bool operator !=(in FixedList512Bytes<T> a, in FixedList128Bytes<T> b) 4694 { 4695 return !(a == b); 4696 } 4697 4698 /// <summary> 4699 /// Returns a number denoting whether this list should be placed before or after another list in a sort. 4700 /// </summary> 4701 /// <param name="other">A list to to compare with.</param> 4702 /// <returns>An integer denoting the respective sort position of the list relative to the other: 4703 /// 4704 /// 0 denotes that both lists should have the same position in a sort. 4705 /// -1 denotes that this list should precede the other list in a sort. 4706 /// +1 denotes that this list should follow the other list in a sort. 4707 /// </returns> 4708 public int CompareTo(FixedList128Bytes<T> other) 4709 { 4710 unsafe 4711 { 4712 byte* a = buffer; 4713 byte* b = other.buffer; 4714 var aa = a + FixedList.PaddingBytes<T>(); 4715 var bb = b + FixedList.PaddingBytes<T>(); 4716 var mini = math.min(Length, other.Length); 4717 for(var i = 0; i < mini; ++i) 4718 { 4719 var j = UnsafeUtility.MemCmp(aa + sizeof(T) * i, bb + sizeof(T) * i, sizeof(T)); 4720 if(j != 0) 4721 return j; 4722 } 4723 return Length.CompareTo(other.Length); 4724 } 4725 } 4726 4727 /// <summary> 4728 /// Returns true if this list and another list are equal. 4729 /// </summary> 4730 /// <remarks>Two lists are equal if their length and bytes are equal.</remarks> 4731 /// <param name="other">The list to compare for equality.</param> 4732 /// <returns>True if the two lists are equal.</returns> 4733 public bool Equals(FixedList128Bytes<T> other) 4734 { 4735 return CompareTo(other) == 0; 4736 } 4737 4738 4739 /// <summary> 4740 /// Initializes and returns an instance of FixedList512Bytes with content copied from another list. 4741 /// </summary> 4742 /// <param name="other">The list to copy.</param> 4743 /// <exception cref="IndexOutOfRangeException">Throws if the other list's length exceeds the capacity of FixedList512Bytes&lt;T&gt;.</exception> 4744 public FixedList512Bytes(in FixedList128Bytes<T> other) 4745 { 4746 this = default; 4747 var error = Initialize(other); 4748 if(error != 0) 4749 FixedList.CheckResize<FixedBytes512Align8,T>(other.Length); 4750 } 4751 4752 /// <summary> 4753 /// Initializes an instance of FixedList512Bytes with content copied from another list. 4754 /// </summary> 4755 /// <param name="other">The list to copy.</param> 4756 /// <returns>zero on success, or non-zero on error.</returns> 4757 internal int Initialize(in FixedList128Bytes<T> other) 4758 { 4759 if(other.Length > Capacity) 4760 return (int)CopyError.Truncation; 4761 length = other.length; 4762 unsafe 4763 { 4764 UnsafeUtility.MemCpy(Buffer, other.Buffer, LengthInBytes); 4765 } 4766 return 0; 4767 } 4768 4769 /// <summary> 4770 /// Returns a new list that is a copy of another list. 4771 /// </summary> 4772 /// <param name="other">The list to copy.</param> 4773 /// <returns>A new list that is a copy of the other.</returns> 4774 /// <exception cref="IndexOutOfRangeException">Throws if the other list's length exceeds the capacity of FixedList512Bytes&lt;T&gt;.</exception> 4775 public static implicit operator FixedList512Bytes<T>(in FixedList128Bytes<T> other) 4776 { 4777 return new FixedList512Bytes<T>(other); 4778 } 4779 4780 /// <summary> 4781 /// Returns true if two lists are equal. 4782 /// </summary> 4783 /// <remarks>Two lists are equal if their length and bytes are equal.</remarks> 4784 /// <param name="a">The first list to compare for equality.</param> 4785 /// <param name="b">The second list to compare for equality.</param> 4786 /// <returns>True if the two lists are equal.</returns> 4787 public static bool operator ==(in FixedList512Bytes<T> a, in FixedList512Bytes<T> b) 4788 { 4789 unsafe 4790 { 4791 if(a.length != b.length) 4792 return false; 4793 return UnsafeUtility.MemCmp(a.Buffer, b.Buffer, a.LengthInBytes) == 0; 4794 } 4795 } 4796 4797 /// <summary> 4798 /// Returns true if two lists are unequal. 4799 /// </summary> 4800 /// <remarks>Two lists are equal if their length and bytes are equal.</remarks> 4801 /// <param name="a">The first list to compare for inequality.</param> 4802 /// <param name="b">The second list to compare for inequality.</param> 4803 /// <returns>True if the two lists are unequal.</returns> 4804 public static bool operator !=(in FixedList512Bytes<T> a, in FixedList512Bytes<T> b) 4805 { 4806 return !(a == b); 4807 } 4808 4809 /// <summary> 4810 /// Returns a number denoting whether this list should be placed before or after another list in a sort. 4811 /// </summary> 4812 /// <param name="other">A list to to compare with.</param> 4813 /// <returns>An integer denoting the respective sort position of the list relative to the other: 4814 /// 4815 /// 0 denotes that both lists should have the same position in a sort. 4816 /// -1 denotes that this list should precede the other list in a sort. 4817 /// +1 denotes that this list should follow the other list in a sort. 4818 /// </returns> 4819 public int CompareTo(FixedList512Bytes<T> other) 4820 { 4821 unsafe 4822 { 4823 byte* a = buffer; 4824 byte* b = other.buffer; 4825 var aa = a + FixedList.PaddingBytes<T>(); 4826 var bb = b + FixedList.PaddingBytes<T>(); 4827 var mini = math.min(Length, other.Length); 4828 for(var i = 0; i < mini; ++i) 4829 { 4830 var j = UnsafeUtility.MemCmp(aa + sizeof(T) * i, bb + sizeof(T) * i, sizeof(T)); 4831 if(j != 0) 4832 return j; 4833 } 4834 return Length.CompareTo(other.Length); 4835 } 4836 } 4837 4838 /// <summary> 4839 /// Returns true if this list and another list are equal. 4840 /// </summary> 4841 /// <remarks>Two lists are equal if their length and bytes are equal.</remarks> 4842 /// <param name="other">The list to compare for equality.</param> 4843 /// <returns>True if the two lists are equal.</returns> 4844 public bool Equals(FixedList512Bytes<T> other) 4845 { 4846 return CompareTo(other) == 0; 4847 } 4848 4849 4850 /// <summary> 4851 /// Returns true if two lists are equal. 4852 /// </summary> 4853 /// <remarks>Two lists are equal if their length and bytes are equal.</remarks> 4854 /// <param name="a">The first list to compare for equality.</param> 4855 /// <param name="b">The second list to compare for equality.</param> 4856 /// <returns>True if the two lists are equal.</returns> 4857 public static bool operator ==(in FixedList512Bytes<T> a, in FixedList4096Bytes<T> b) 4858 { 4859 unsafe 4860 { 4861 if(a.length != b.length) 4862 return false; 4863 return UnsafeUtility.MemCmp(a.Buffer, b.Buffer, a.LengthInBytes) == 0; 4864 } 4865 } 4866 4867 /// <summary> 4868 /// Returns true if two lists are unequal. 4869 /// </summary> 4870 /// <remarks>Two lists are equal if their length and bytes are equal.</remarks> 4871 /// <param name="a">The first list to compare for inequality.</param> 4872 /// <param name="b">The second list to compare for inequality.</param> 4873 /// <returns>True if the two lists are unequal.</returns> 4874 public static bool operator !=(in FixedList512Bytes<T> a, in FixedList4096Bytes<T> b) 4875 { 4876 return !(a == b); 4877 } 4878 4879 /// <summary> 4880 /// Returns a number denoting whether this list should be placed before or after another list in a sort. 4881 /// </summary> 4882 /// <param name="other">A list to to compare with.</param> 4883 /// <returns>An integer denoting the respective sort position of the list relative to the other: 4884 /// 4885 /// 0 denotes that both lists should have the same position in a sort. 4886 /// -1 denotes that this list should precede the other list in a sort. 4887 /// +1 denotes that this list should follow the other list in a sort. 4888 /// </returns> 4889 public int CompareTo(FixedList4096Bytes<T> other) 4890 { 4891 unsafe 4892 { 4893 byte* a = buffer; 4894 byte* b = other.buffer; 4895 var aa = a + FixedList.PaddingBytes<T>(); 4896 var bb = b + FixedList.PaddingBytes<T>(); 4897 var mini = math.min(Length, other.Length); 4898 for(var i = 0; i < mini; ++i) 4899 { 4900 var j = UnsafeUtility.MemCmp(aa + sizeof(T) * i, bb + sizeof(T) * i, sizeof(T)); 4901 if(j != 0) 4902 return j; 4903 } 4904 return Length.CompareTo(other.Length); 4905 } 4906 } 4907 4908 /// <summary> 4909 /// Returns true if this list and another list are equal. 4910 /// </summary> 4911 /// <remarks>Two lists are equal if their length and bytes are equal.</remarks> 4912 /// <param name="other">The list to compare for equality.</param> 4913 /// <returns>True if the two lists are equal.</returns> 4914 public bool Equals(FixedList4096Bytes<T> other) 4915 { 4916 return CompareTo(other) == 0; 4917 } 4918 4919 4920 /// <summary> 4921 /// Initializes and returns an instance of FixedList512Bytes with content copied from another list. 4922 /// </summary> 4923 /// <param name="other">The list to copy.</param> 4924 /// <exception cref="IndexOutOfRangeException">Throws if the other list's length exceeds the capacity of FixedList512Bytes&lt;T&gt;.</exception> 4925 public FixedList512Bytes(in FixedList4096Bytes<T> other) 4926 { 4927 this = default; 4928 var error = Initialize(other); 4929 if(error != 0) 4930 FixedList.CheckResize<FixedBytes512Align8,T>(other.Length); 4931 } 4932 4933 /// <summary> 4934 /// Initializes an instance of FixedList512Bytes with content copied from another list. 4935 /// </summary> 4936 /// <param name="other">The list to copy.</param> 4937 /// <returns>zero on success, or non-zero on error.</returns> 4938 internal int Initialize(in FixedList4096Bytes<T> other) 4939 { 4940 if(other.Length > Capacity) 4941 return (int)CopyError.Truncation; 4942 length = other.length; 4943 unsafe 4944 { 4945 UnsafeUtility.MemCpy(Buffer, other.Buffer, LengthInBytes); 4946 } 4947 return 0; 4948 } 4949 4950 /// <summary> 4951 /// Returns a new list that is a copy of another list. 4952 /// </summary> 4953 /// <param name="other">The list to copy.</param> 4954 /// <returns>A new list that is a copy of the other.</returns> 4955 /// <exception cref="IndexOutOfRangeException">Throws if the other list's length exceeds the capacity of FixedList512Bytes&lt;T&gt;.</exception> 4956 public static implicit operator FixedList512Bytes<T>(in FixedList4096Bytes<T> other) 4957 { 4958 return new FixedList512Bytes<T>(other); 4959 } 4960 4961 /// <summary> 4962 /// Returns true if the list is equal to an object. 4963 /// </summary> 4964 /// <remarks>Two lists are equal if their length and bytes are equal. 4965 /// 4966 /// A FixedList*N*&lt;T&gt; can only be equal to another FixedList*N*&lt;T&gt; with the same *N* and T. 4967 /// </remarks> 4968 /// <param name="obj">An object to compare for equality.</param> 4969 /// <returns>True if the list is equal to the object.</returns> 4970 [ExcludeFromBurstCompatTesting("Takes managed object")] 4971 public override bool Equals(object obj) 4972 { 4973 if(obj is FixedList32Bytes<T> aFixedList32Bytes) return Equals(aFixedList32Bytes); 4974 if(obj is FixedList64Bytes<T> aFixedList64Bytes) return Equals(aFixedList64Bytes); 4975 if(obj is FixedList128Bytes<T> aFixedList128Bytes) return Equals(aFixedList128Bytes); 4976 if(obj is FixedList512Bytes<T> aFixedList512Bytes) return Equals(aFixedList512Bytes); 4977 if(obj is FixedList4096Bytes<T> aFixedList4096Bytes) return Equals(aFixedList4096Bytes); 4978 return false; 4979 } 4980 4981 /// <summary> 4982 /// An enumerator over the elements of a FixedList512Bytes&lt;T&gt;. 4983 /// </summary> 4984 /// <remarks> 4985 /// In an enumerator's initial state, `Current` cannot be read. The first <see cref="MoveNext"/> call advances the enumerator to the first element. 4986 /// </remarks> 4987 public struct Enumerator : IEnumerator<T> 4988 { 4989 FixedList512Bytes<T> m_List; 4990 int m_Index; 4991 4992 /// <summary> 4993 /// Initializes and returns an instance of FixedList512Bytes&lt;T&gt;. 4994 /// </summary> 4995 /// <param name="list">The list for which to create an enumerator.</param> 4996 public Enumerator(ref FixedList512Bytes<T> list) 4997 { 4998 m_List = list; 4999 m_Index = -1; 5000 } 5001 5002 /// <summary> 5003 /// Does nothing. 5004 /// </summary> 5005 public void Dispose() 5006 { 5007 } 5008 5009 /// <summary> 5010 /// Advances the enumerator to the next element. 5011 /// </summary> 5012 /// <returns>True if <see cref="Current"/> is valid to read after the call.</returns> 5013 [MethodImpl(MethodImplOptions.AggressiveInlining)] 5014 public bool MoveNext() 5015 { 5016 m_Index++; 5017 return m_Index < m_List.Length; 5018 } 5019 5020 /// <summary> 5021 /// Resets the enumerator to its initial state. 5022 /// </summary> 5023 public void Reset() 5024 { 5025 m_Index = -1; 5026 } 5027 5028 /// <summary> 5029 /// The current element. 5030 /// </summary> 5031 /// <value>The current element.</value> 5032 public T Current 5033 { 5034 [MethodImpl(MethodImplOptions.AggressiveInlining)] 5035 get => m_List[m_Index]; // Let FixedList512Bytes<T> indexer check for out of range. 5036 } 5037 5038 object IEnumerator.Current => Current; 5039 } 5040 5041 /// <summary> 5042 /// Returns an enumerator for iterating over the elements of this list. 5043 /// </summary> 5044 /// <returns>An enumerator for iterating over the elements of this list.</returns> 5045 public Enumerator GetEnumerator() 5046 { 5047 return new Enumerator(ref this); 5048 } 5049 5050 /// <summary> 5051 /// This method is not implemented. Use <see cref="GetEnumerator"/> instead. 5052 /// </summary> 5053 /// <returns>Nothing because it always throws <see cref="NotImplementedException"/>.</returns> 5054 /// <exception cref="NotImplementedException">Method is not implemented.</exception> 5055 IEnumerator IEnumerable.GetEnumerator() 5056 { 5057 throw new NotImplementedException(); 5058 } 5059 5060 /// <summary> 5061 /// This method is not implemented. Use <see cref="GetEnumerator"/> instead. 5062 /// </summary> 5063 /// <returns>Nothing because it always throws <see cref="NotImplementedException"/>.</returns> 5064 /// <exception cref="NotImplementedException">Method is not implemented.</exception> 5065 IEnumerator<T> IEnumerable<T>.GetEnumerator() 5066 { 5067 throw new NotImplementedException(); 5068 } 5069 } 5070 5071 /// <summary> 5072 /// Provides extension methods for FixedList512Bytes. 5073 /// </summary> 5074 [GenerateTestsForBurstCompatibility] 5075 public unsafe static class FixedList512BytesExtensions 5076 { 5077 /// <summary> 5078 /// Finds the index of the first occurrence of a particular value in this list. 5079 /// </summary> 5080 /// <typeparam name="T">The type of elements in this list.</typeparam> 5081 /// <typeparam name="U">The value type.</typeparam> 5082 /// <param name="list">The list to search.</param> 5083 /// <param name="value">The value to locate.</param> 5084 /// <returns>The index of the first occurrence of the value. Returns -1 if no occurrence is found.</returns> 5085 [GenerateTestsForBurstCompatibility(GenericTypeArguments = new [] { typeof(int), typeof(int) })] 5086 public static int IndexOf<T, U>(this ref FixedList512Bytes<T> list, U value) where T : unmanaged, IEquatable<U> 5087 { 5088 return NativeArrayExtensions.IndexOf<T, U>(list.Buffer, list.Length, value); 5089 } 5090 5091 /// <summary> 5092 /// Returns true if a particular value is present in this list. 5093 /// </summary> 5094 /// <typeparam name="T">The type of elements in this list.</typeparam> 5095 /// <typeparam name="U">The value type.</typeparam> 5096 /// <param name="list">The list to search.</param> 5097 /// <param name="value">The value to locate.</param> 5098 /// <returns>True if the value is present in this list.</returns> 5099 [GenerateTestsForBurstCompatibility(GenericTypeArguments = new [] { typeof(int), typeof(int) })] 5100 public static bool Contains<T, U>(this ref FixedList512Bytes<T> list, U value) where T : unmanaged, IEquatable<U> 5101 { 5102 return list.IndexOf(value) != -1; 5103 } 5104 5105 /// <summary> 5106 /// Removes the first occurrence of a particular value in this list. 5107 /// </summary> 5108 /// <remarks> 5109 /// If a value is removed, all elements after it are shifted down by one, and the list's length is decremented by one. 5110 /// 5111 /// If you don't need to preserve the order of the remaining elements, <see cref="Unity.Collections.FixedList512BytesExtensions.RemoveSwapBack{T, U}"/> is a cheaper alternative. 5112 /// </remarks> 5113 /// <typeparam name="T">The type of elements in this list.</typeparam> 5114 /// <typeparam name="U">The value type.</typeparam> 5115 /// <param name="list">The list to search.</param> 5116 /// <param name="value">The value to locate and remove.</param> 5117 /// <returns>True if the value was found and removed.</returns> 5118 [GenerateTestsForBurstCompatibility(GenericTypeArguments = new [] { typeof(int), typeof(int) })] 5119 public static bool Remove<T, U>(this ref FixedList512Bytes<T> list, U value) where T : unmanaged, IEquatable<U> 5120 { 5121 int index = list.IndexOf(value); 5122 if (index < 0) 5123 { 5124 return false; 5125 } 5126 5127 list.RemoveAt(index); 5128 5129 return true; 5130 } 5131 5132 /// <summary> 5133 /// Removes the first occurrence of a particular value in this list. 5134 /// </summary> 5135 /// <remarks> 5136 /// 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. 5137 /// 5138 /// This is cheaper than <see cref="Remove"/>, but the order of the remaining elements is not preserved. 5139 /// </remarks> 5140 /// <typeparam name="T">The type of elements in this list.</typeparam> 5141 /// <typeparam name="U">The value type.</typeparam> 5142 /// <param name="list">The list to search.</param> 5143 /// <param name="value">The value to locate and remove.</param> 5144 /// <returns>Returns true if the item is removed.</returns> 5145 [GenerateTestsForBurstCompatibility(GenericTypeArguments = new [] { typeof(int), typeof(int) })] 5146 public static bool RemoveSwapBack<T, U>(this ref FixedList512Bytes<T> list, U value) where T : unmanaged, IEquatable<U> 5147 { 5148 var index = list.IndexOf(value); 5149 if (index == -1) 5150 { 5151 return false; 5152 } 5153 5154 list.RemoveAtSwapBack(index); 5155 5156 return true; 5157 } 5158 } 5159 5160 sealed class FixedList512BytesDebugView<T> where T : unmanaged 5161 { 5162 FixedList512Bytes<T> m_List; 5163 public FixedList512BytesDebugView(FixedList512Bytes<T> list) 5164 { 5165 m_List = list; 5166 } 5167 public T[] Items => m_List.ToArray(); 5168 } 5169 /// <summary> 5170 /// An unmanaged, resizable list whose content is all stored directly in the 4096-byte struct. Useful for small lists. 5171 /// </summary> 5172 /// <typeparam name="T">The type of the elements.</typeparam> 5173 [Serializable] 5174 [DebuggerTypeProxy(typeof(FixedList4096BytesDebugView<>))] 5175 [GenerateTestsForBurstCompatibility(GenericTypeArguments = new [] { typeof(int) })] 5176 public struct FixedList4096Bytes<T> 5177 : INativeList<T> 5178 , IEnumerable<T> // Used by collection initializers. 5179 , IEquatable<FixedList32Bytes<T>> 5180 , IComparable<FixedList32Bytes<T>> 5181 , IEquatable<FixedList64Bytes<T>> 5182 , IComparable<FixedList64Bytes<T>> 5183 , IEquatable<FixedList128Bytes<T>> 5184 , IComparable<FixedList128Bytes<T>> 5185 , IEquatable<FixedList512Bytes<T>> 5186 , IComparable<FixedList512Bytes<T>> 5187 , IEquatable<FixedList4096Bytes<T>> 5188 , IComparable<FixedList4096Bytes<T>> 5189 where T : unmanaged 5190 { 5191 [SerializeField] internal FixedBytes4096Align8 data; 5192 5193 internal ushort length 5194 { 5195 [MethodImpl(MethodImplOptions.AggressiveInlining)] 5196 readonly get 5197 { 5198 unsafe 5199 { 5200 fixed(void* ptr = &data) 5201 return *((ushort*)ptr); 5202 } 5203 } 5204 5205 [MethodImpl(MethodImplOptions.AggressiveInlining)] 5206 set 5207 { 5208 unsafe 5209 { 5210 fixed (void* ptr = &data) 5211 *((ushort*)ptr) = value; 5212 } 5213 } 5214 } 5215 5216 internal readonly unsafe byte* buffer 5217 { 5218 [MethodImpl(MethodImplOptions.AggressiveInlining)] 5219 get 5220 { 5221 unsafe 5222 { 5223 fixed (void* ptr = &data) 5224 return ((byte*)ptr) + UnsafeUtility.SizeOf<ushort>(); 5225 } 5226 } 5227 } 5228 5229 /// <summary> 5230 /// The current number of items in this list. 5231 /// </summary> 5232 /// <value>The current number of items in this list.</value> 5233 [CreateProperty] 5234 public int Length 5235 { 5236 [MethodImpl(MethodImplOptions.AggressiveInlining)] 5237 readonly get => length; 5238 set 5239 { 5240 FixedList.CheckResize<FixedBytes4096Align8,T>(value); 5241 length = (ushort)value; 5242 } 5243 } 5244 5245 /// <summary> 5246 /// A property in order to display items in the Entity Inspector. 5247 /// </summary> 5248 [CreateProperty] IEnumerable<T> Elements => this.ToArray(); 5249 5250 /// <summary> 5251 /// Whether this list is empty. 5252 /// </summary> 5253 /// <value>True if this string has no characters or if the container has not been constructed.</value> 5254 public readonly bool IsEmpty 5255 { 5256 [MethodImpl(MethodImplOptions.AggressiveInlining)] 5257 get => Length == 0; 5258 } 5259 5260 internal int LengthInBytes => Length * UnsafeUtility.SizeOf<T>(); 5261 5262 /// <summary> 5263 /// Returns a pointer to the first element of the list buffer. 5264 /// </summary> 5265 /// <remarks> 5266 /// The pointer returned by this method points into the internals of the target list object. It is the 5267 /// caller's responsibility to ensure that the pointer is not used after the list is destroyed or goes 5268 /// out of scope. 5269 /// </remarks> 5270 /// <returns>A pointer to the first element of the list buffer.</returns> 5271 internal readonly unsafe byte* Buffer 5272 { 5273 [MethodImpl(MethodImplOptions.AggressiveInlining)] 5274 get 5275 { 5276 return buffer + FixedList.PaddingBytes<T>(); 5277 } 5278 } 5279 5280 /// <summary> 5281 /// The number of elements that can fit in this list. 5282 /// </summary> 5283 /// <value>The number of elements that can fit in this list.</value> 5284 /// <remarks>The capacity of a FixedList cannot be changed. The setter is included only for conformity with <see cref="INativeList{T}"/>.</remarks> 5285 /// <exception cref="ArgumentOutOfRangeException">Thrown if the new value does not match the current capacity.</exception> 5286 public int Capacity 5287 { 5288 [MethodImpl(MethodImplOptions.AggressiveInlining)] 5289 readonly get 5290 { 5291 return FixedList.Capacity<FixedBytes4096Align8,T>(); 5292 } 5293 5294 set 5295 { 5296 CollectionHelper.CheckCapacityInRange(value, Length); 5297 } 5298 } 5299 5300 /// <summary> 5301 /// The element at a given index. 5302 /// </summary> 5303 /// <param name="index">An index.</param> 5304 /// <value>The value to store at the index.</value> 5305 /// <exception cref="IndexOutOfRangeException">Thrown if the index is out of bounds.</exception> 5306 public T this[int index] 5307 { 5308 [MethodImpl(MethodImplOptions.AggressiveInlining)] 5309 readonly get 5310 { 5311 CollectionHelper.CheckIndexInRange(index, length); 5312 unsafe 5313 { 5314 return UnsafeUtility.ReadArrayElement<T>(Buffer, CollectionHelper.AssumePositive(index)); 5315 } 5316 } 5317 5318 [MethodImpl(MethodImplOptions.AggressiveInlining)] 5319 set 5320 { 5321 CollectionHelper.CheckIndexInRange(index, length); 5322 unsafe 5323 { 5324 UnsafeUtility.WriteArrayElement<T>(Buffer, CollectionHelper.AssumePositive(index), value); 5325 } 5326 } 5327 } 5328 5329 /// <summary> 5330 /// Returns the element at a given index. 5331 /// </summary> 5332 /// <param name="index">An index.</param> 5333 /// <returns>The list element at the index.</returns> 5334 [MethodImpl(MethodImplOptions.AggressiveInlining)] 5335 public ref T ElementAt(int index) 5336 { 5337 CollectionHelper.CheckIndexInRange(index, length); 5338 unsafe 5339 { 5340 return ref UnsafeUtility.ArrayElementAsRef<T>(Buffer, index); 5341 } 5342 } 5343 5344 /// <summary> 5345 /// Returns the hash code of this list. 5346 /// </summary> 5347 /// <remarks> 5348 /// 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> 5349 /// <returns>The hash code of this list.</returns> 5350 public override int GetHashCode() 5351 { 5352 unsafe 5353 { 5354 return (int)CollectionHelper.Hash(Buffer, LengthInBytes); 5355 } 5356 } 5357 5358 /// <summary> 5359 /// Appends an element to the end of this list. Increments the length by 1. 5360 /// </summary> 5361 /// <remarks> 5362 /// The same as <see cref="AddNoResize"/>. Included only for consistency with the other list types. 5363 /// If the element exceeds the capacity, throws cref="IndexOutOfRangeException", and the list is unchanged. 5364 /// </remarks> 5365 /// <param name="item">The element to append at the end of the list.</param> 5366 /// <exception cref="IndexOutOfRangeException">Thrown if the append exceeds the capacity.</exception> 5367 public void Add(in T item) => AddNoResize(in item); 5368 5369 /// <summary> 5370 /// Appends elements from a buffer to the end of this list. Increments the length by the number of appended elements. 5371 /// </summary> 5372 /// <remarks> 5373 /// The same as <see cref="AddRangeNoResize"/>. Included only for consistency with the other list types. 5374 /// If the elements exceeds the capacity, throws cref="IndexOutOfRangeException", and the list is unchanged. 5375 /// </remarks> 5376 /// <param name="ptr">A buffer.</param> 5377 /// <param name="length">The number of elements from the buffer to append.</param> 5378 /// <exception cref="IndexOutOfRangeException">Thrown if the append exceeds the capacity.</exception> 5379 public unsafe void AddRange(void* ptr, int length) => AddRangeNoResize(ptr, length); 5380 5381 /// <summary> 5382 /// Appends an element to the end of this list. Increments the length by 1. 5383 /// </summary> 5384 /// <remarks> 5385 /// If the element exceeds the capacity, throws cref="IndexOutOfRangeException", and the list is unchanged. 5386 /// </remarks> 5387 /// <param name="item">The element to append at the end of the list.</param> 5388 /// <exception cref="IndexOutOfRangeException">Thrown if the append exceeds the capacity.</exception> 5389 [MethodImpl(MethodImplOptions.AggressiveInlining)] 5390 public void AddNoResize(in T item) 5391 { 5392 this[Length++] = item; 5393 } 5394 5395 /// <summary> 5396 /// Appends elements from a buffer to the end of this list. Increments the length by the number of appended elements. 5397 /// </summary> 5398 /// <remarks> 5399 /// If the elements exceeds the capacity, throws cref="IndexOutOfRangeException", and the list is unchanged. 5400 /// </remarks> 5401 /// <param name="ptr">A buffer.</param> 5402 /// <param name="length">The number of elements from the buffer to append.</param> 5403 /// <exception cref="IndexOutOfRangeException">Thrown if the append exceeds the capacity.</exception> 5404 public unsafe void AddRangeNoResize(void* ptr, int length) 5405 { 5406 var idx = Length; 5407 Length += length; 5408 UnsafeUtility.MemCpy((T*)Buffer + idx, ptr, UnsafeUtility.SizeOf<T>() * length); 5409 } 5410 5411 /// <summary> 5412 /// Appends value count times to the end of this list. 5413 /// </summary> 5414 /// <param name="value">The value to add to the end of this list.</param> 5415 /// <param name="count">The number of times to replicate the value.</param> 5416 /// <exception cref="IndexOutOfRangeException">Thrown if the append exceeds the capacity.</exception> 5417 public unsafe void AddReplicate(in T value, int count) 5418 { 5419 var idx = Length; 5420 Length += count; 5421 fixed (T* ptr = &value) 5422 UnsafeUtility.MemCpyReplicate((T*)Buffer + idx, ptr, UnsafeUtility.SizeOf<T>(), count); 5423 } 5424 5425 /// <summary> 5426 /// Sets the length to 0. 5427 /// </summary> 5428 /// <remarks> Does *not* zero out the bytes.</remarks> 5429 public void Clear() 5430 { 5431 Length = 0; 5432 } 5433 5434 /// <summary> 5435 /// Shifts elements toward the end of this list, increasing its length. 5436 /// </summary> 5437 /// <remarks> 5438 /// Right-shifts elements in the list so as to create 'free' slots at the beginning or in the middle. 5439 /// 5440 /// The length is increased by `end - begin`. 5441 /// 5442 /// If `end` equals `begin`, the method does nothing. 5443 /// 5444 /// 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. 5445 /// 5446 /// The indexes `begin` up to `end` are not cleared: they will contain whatever values they held prior. 5447 /// </remarks> 5448 /// <param name="begin">The index of the first element that will be shifted up.</param> 5449 /// <param name="end">The index where the first shifted element will end up.</param> 5450 /// <exception cref="IndexOutOfRangeException">Thrown if the new length exceeds the capacity.</exception> 5451 public void InsertRangeWithBeginEnd(int begin, int end) 5452 { 5453 int items = end - begin; 5454 if(items < 1) 5455 return; 5456 int itemsToCopy = length - begin; 5457 Length += items; 5458 if(itemsToCopy < 1) 5459 return; 5460 int bytesToCopy = itemsToCopy * UnsafeUtility.SizeOf<T>(); 5461 unsafe 5462 { 5463 byte *b = Buffer; 5464 byte *dest = b + end * UnsafeUtility.SizeOf<T>(); 5465 byte *src = b + begin * UnsafeUtility.SizeOf<T>(); 5466 UnsafeUtility.MemMove(dest, src, bytesToCopy); 5467 } 5468 } 5469 5470 /// <summary> 5471 /// Shifts elements toward the end of this list, increasing its length. 5472 /// </summary> 5473 /// <remarks> 5474 /// Right-shifts elements in the list so as to create 'free' slots at the beginning or in the middle. 5475 /// 5476 /// The length is increased by `count`. If necessary, the capacity will be increased accordingly. 5477 /// 5478 /// If `count` equals `0`, the method does nothing. 5479 /// 5480 /// 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. 5481 /// 5482 /// The indexes `index` up to `index + count` are not cleared: they will contain whatever values they held prior. 5483 /// </remarks> 5484 /// <param name="index">The index of the first element that will be shifted up.</param> 5485 /// <param name="count">The number of elements to insert.</param> 5486 /// <exception cref="ArgumentException">Thrown if `count` is negative.</exception> 5487 /// <exception cref="ArgumentOutOfRangeException">Thrown if `index` is out of bounds.</exception> 5488 public void InsertRange(int index, int count) => InsertRangeWithBeginEnd(index, index + count); 5489 5490 /// <summary> 5491 /// Inserts a single element at an index. Increments the length by 1. 5492 /// </summary> 5493 /// <param name="index">The index at which to insert the element.</param> 5494 /// <param name="item">The element to insert.</param> 5495 /// <exception cref="ArgumentOutOfRangeException">Thrown if the index is out of bounds.</exception> 5496 public void Insert(int index, in T item) 5497 { 5498 InsertRangeWithBeginEnd(index, index+1); 5499 this[index] = item; 5500 } 5501 5502 /// <summary> 5503 /// Copies the last element of this list to an index. Decrements the length by 1. 5504 /// </summary> 5505 /// <remarks>Useful as a cheap way to remove elements from a list when you don't care about preserving order.</remarks> 5506 /// <param name="index">The index to overwrite with the last element.</param> 5507 /// <exception cref="ArgumentOutOfRangeException">Thrown if the index is out of bounds.</exception> 5508 public void RemoveAtSwapBack(int index) 5509 { 5510 RemoveRangeSwapBack(index, 1); 5511 } 5512 5513 /// <summary> 5514 /// Copies the last *N* elements of this list to a range in this list. Decrements the length by *N*. 5515 /// </summary> 5516 /// <remarks> 5517 /// Copies the last `count`-numbered elements to the range starting at `index`. 5518 /// 5519 /// Useful as a cheap way to remove elements from a list when you don't care about preserving order. 5520 /// 5521 /// Does nothing if the count is less than 1. 5522 /// </remarks> 5523 /// <param name="index">The first index of the destination range.</param> 5524 /// <param name="count">The number of elements to copy and the amount by which to decrement the length.</param> 5525 /// <exception cref="ArgumentOutOfRangeException">Thrown if the index is out of bounds.</exception> 5526 public void RemoveRangeSwapBack(int index, int count) 5527 { 5528 if (count > 0) 5529 { 5530 int copyFrom = math.max(Length - count, index + count); 5531 5532 unsafe 5533 { 5534 var sizeOf = UnsafeUtility.SizeOf<T>(); 5535 void* dst = Buffer + index * sizeOf; 5536 void* src = Buffer + copyFrom * sizeOf; 5537 UnsafeUtility.MemCpy(dst, src, (Length - copyFrom) * sizeOf); 5538 } 5539 5540 Length -= count; 5541 } 5542 } 5543 5544 /// <summary> 5545 /// Removes the element at an index. Shifts everything above the index down by one and decrements the length by 1. 5546 /// </summary> 5547 /// <param name="index">The index of the element to remove.</param> 5548 /// <remarks> 5549 /// If you don't care about preserving the order of the elements, `RemoveAtSwapBack` is a more efficient way to remove an element. 5550 /// </remarks> 5551 /// <exception cref="ArgumentOutOfRangeException">Thrown if the index is out of bounds.</exception> 5552 public void RemoveAt(int index) 5553 { 5554 RemoveRange(index, 1); 5555 } 5556 5557 /// <summary> 5558 /// Removes *N* elements of a range. Shifts everything above the range down by *N* and decrements the length by *N*. 5559 /// </summary> 5560 /// <remarks> 5561 /// If you don't care about preserving the order of the elements, `RemoveAtSwapBack` is a more efficient way to remove elements. 5562 /// </remarks> 5563 /// <param name="index">The first index of the range to remove.</param> 5564 /// <param name="count">The number of elements to remove.</param> 5565 /// <exception cref="ArgumentOutOfRangeException">Thrown if the index is out of bounds.</exception> 5566 public void RemoveRange(int index, int count) 5567 { 5568 if (count > 0) 5569 { 5570 int copyFrom = math.min(index + count, Length); 5571 5572 unsafe 5573 { 5574 var sizeOf = UnsafeUtility.SizeOf<T>(); 5575 void* dst = Buffer + index * sizeOf; 5576 void* src = Buffer + copyFrom * sizeOf; 5577 UnsafeUtility.MemCpy(dst, src, (Length - copyFrom) * sizeOf); 5578 } 5579 5580 Length -= count; 5581 } 5582 } 5583 5584 /// <summary> 5585 /// Returns a managed array that is a copy of this list. 5586 /// </summary> 5587 /// <returns>A managed array that is a copy of this list.</returns> 5588 [ExcludeFromBurstCompatTesting("Returns managed array")] 5589 public T[] ToArray() 5590 { 5591 var result = new T[Length]; 5592 unsafe 5593 { 5594 byte* s = Buffer; 5595 fixed(T* d = result) 5596 UnsafeUtility.MemCpy(d, s, LengthInBytes); 5597 } 5598 return result; 5599 } 5600 5601 /// <summary> 5602 /// Returns an array that is a copy of this list. 5603 /// </summary> 5604 /// <param name="allocator">The allocator to use.</param> 5605 /// <returns>An array that is a copy of this list.</returns> 5606 public NativeArray<T> ToNativeArray(AllocatorManager.AllocatorHandle allocator) 5607 { 5608 unsafe 5609 { 5610 var copy = CollectionHelper.CreateNativeArray<T>(Length, allocator, NativeArrayOptions.UninitializedMemory); 5611 UnsafeUtility.MemCpy(copy.GetUnsafePtr(), Buffer, LengthInBytes); 5612 return copy; 5613 } 5614 } 5615 5616 5617 /// <summary> 5618 /// Returns true if two lists are equal. 5619 /// </summary> 5620 /// <remarks>Two lists are equal if their length and bytes are equal.</remarks> 5621 /// <param name="a">The first list to compare for equality.</param> 5622 /// <param name="b">The second list to compare for equality.</param> 5623 /// <returns>True if the two lists are equal.</returns> 5624 public static bool operator ==(in FixedList4096Bytes<T> a, in FixedList32Bytes<T> b) 5625 { 5626 unsafe 5627 { 5628 if(a.length != b.length) 5629 return false; 5630 return UnsafeUtility.MemCmp(a.Buffer, b.Buffer, a.LengthInBytes) == 0; 5631 } 5632 } 5633 5634 /// <summary> 5635 /// Returns true if two lists are unequal. 5636 /// </summary> 5637 /// <remarks>Two lists are equal if their length and bytes are equal.</remarks> 5638 /// <param name="a">The first list to compare for inequality.</param> 5639 /// <param name="b">The second list to compare for inequality.</param> 5640 /// <returns>True if the two lists are unequal.</returns> 5641 public static bool operator !=(in FixedList4096Bytes<T> a, in FixedList32Bytes<T> b) 5642 { 5643 return !(a == b); 5644 } 5645 5646 /// <summary> 5647 /// Returns a number denoting whether this list should be placed before or after another list in a sort. 5648 /// </summary> 5649 /// <param name="other">A list to to compare with.</param> 5650 /// <returns>An integer denoting the respective sort position of the list relative to the other: 5651 /// 5652 /// 0 denotes that both lists should have the same position in a sort. 5653 /// -1 denotes that this list should precede the other list in a sort. 5654 /// +1 denotes that this list should follow the other list in a sort. 5655 /// </returns> 5656 public int CompareTo(FixedList32Bytes<T> other) 5657 { 5658 unsafe 5659 { 5660 byte* a = buffer; 5661 byte* b = other.buffer; 5662 var aa = a + FixedList.PaddingBytes<T>(); 5663 var bb = b + FixedList.PaddingBytes<T>(); 5664 var mini = math.min(Length, other.Length); 5665 for(var i = 0; i < mini; ++i) 5666 { 5667 var j = UnsafeUtility.MemCmp(aa + sizeof(T) * i, bb + sizeof(T) * i, sizeof(T)); 5668 if(j != 0) 5669 return j; 5670 } 5671 return Length.CompareTo(other.Length); 5672 } 5673 } 5674 5675 /// <summary> 5676 /// Returns true if this list and another list are equal. 5677 /// </summary> 5678 /// <remarks>Two lists are equal if their length and bytes are equal.</remarks> 5679 /// <param name="other">The list to compare for equality.</param> 5680 /// <returns>True if the two lists are equal.</returns> 5681 public bool Equals(FixedList32Bytes<T> other) 5682 { 5683 return CompareTo(other) == 0; 5684 } 5685 5686 5687 /// <summary> 5688 /// Initializes and returns an instance of FixedList4096Bytes with content copied from another list. 5689 /// </summary> 5690 /// <param name="other">The list to copy.</param> 5691 /// <exception cref="IndexOutOfRangeException">Throws if the other list's length exceeds the capacity of FixedList4096Bytes&lt;T&gt;.</exception> 5692 public FixedList4096Bytes(in FixedList32Bytes<T> other) 5693 { 5694 this = default; 5695 var error = Initialize(other); 5696 if(error != 0) 5697 FixedList.CheckResize<FixedBytes4096Align8,T>(other.Length); 5698 } 5699 5700 /// <summary> 5701 /// Initializes an instance of FixedList4096Bytes with content copied from another list. 5702 /// </summary> 5703 /// <param name="other">The list to copy.</param> 5704 /// <returns>zero on success, or non-zero on error.</returns> 5705 internal int Initialize(in FixedList32Bytes<T> other) 5706 { 5707 if(other.Length > Capacity) 5708 return (int)CopyError.Truncation; 5709 length = other.length; 5710 unsafe 5711 { 5712 UnsafeUtility.MemCpy(Buffer, other.Buffer, LengthInBytes); 5713 } 5714 return 0; 5715 } 5716 5717 /// <summary> 5718 /// Returns a new list that is a copy of another list. 5719 /// </summary> 5720 /// <param name="other">The list to copy.</param> 5721 /// <returns>A new list that is a copy of the other.</returns> 5722 /// <exception cref="IndexOutOfRangeException">Throws if the other list's length exceeds the capacity of FixedList4096Bytes&lt;T&gt;.</exception> 5723 public static implicit operator FixedList4096Bytes<T>(in FixedList32Bytes<T> other) 5724 { 5725 return new FixedList4096Bytes<T>(other); 5726 } 5727 5728 /// <summary> 5729 /// Returns true if two lists are equal. 5730 /// </summary> 5731 /// <remarks>Two lists are equal if their length and bytes are equal.</remarks> 5732 /// <param name="a">The first list to compare for equality.</param> 5733 /// <param name="b">The second list to compare for equality.</param> 5734 /// <returns>True if the two lists are equal.</returns> 5735 public static bool operator ==(in FixedList4096Bytes<T> a, in FixedList64Bytes<T> b) 5736 { 5737 unsafe 5738 { 5739 if(a.length != b.length) 5740 return false; 5741 return UnsafeUtility.MemCmp(a.Buffer, b.Buffer, a.LengthInBytes) == 0; 5742 } 5743 } 5744 5745 /// <summary> 5746 /// Returns true if two lists are unequal. 5747 /// </summary> 5748 /// <remarks>Two lists are equal if their length and bytes are equal.</remarks> 5749 /// <param name="a">The first list to compare for inequality.</param> 5750 /// <param name="b">The second list to compare for inequality.</param> 5751 /// <returns>True if the two lists are unequal.</returns> 5752 public static bool operator !=(in FixedList4096Bytes<T> a, in FixedList64Bytes<T> b) 5753 { 5754 return !(a == b); 5755 } 5756 5757 /// <summary> 5758 /// Returns a number denoting whether this list should be placed before or after another list in a sort. 5759 /// </summary> 5760 /// <param name="other">A list to to compare with.</param> 5761 /// <returns>An integer denoting the respective sort position of the list relative to the other: 5762 /// 5763 /// 0 denotes that both lists should have the same position in a sort. 5764 /// -1 denotes that this list should precede the other list in a sort. 5765 /// +1 denotes that this list should follow the other list in a sort. 5766 /// </returns> 5767 public int CompareTo(FixedList64Bytes<T> other) 5768 { 5769 unsafe 5770 { 5771 byte* a = buffer; 5772 byte* b = other.buffer; 5773 var aa = a + FixedList.PaddingBytes<T>(); 5774 var bb = b + FixedList.PaddingBytes<T>(); 5775 var mini = math.min(Length, other.Length); 5776 for(var i = 0; i < mini; ++i) 5777 { 5778 var j = UnsafeUtility.MemCmp(aa + sizeof(T) * i, bb + sizeof(T) * i, sizeof(T)); 5779 if(j != 0) 5780 return j; 5781 } 5782 return Length.CompareTo(other.Length); 5783 } 5784 } 5785 5786 /// <summary> 5787 /// Returns true if this list and another list are equal. 5788 /// </summary> 5789 /// <remarks>Two lists are equal if their length and bytes are equal.</remarks> 5790 /// <param name="other">The list to compare for equality.</param> 5791 /// <returns>True if the two lists are equal.</returns> 5792 public bool Equals(FixedList64Bytes<T> other) 5793 { 5794 return CompareTo(other) == 0; 5795 } 5796 5797 5798 /// <summary> 5799 /// Initializes and returns an instance of FixedList4096Bytes with content copied from another list. 5800 /// </summary> 5801 /// <param name="other">The list to copy.</param> 5802 /// <exception cref="IndexOutOfRangeException">Throws if the other list's length exceeds the capacity of FixedList4096Bytes&lt;T&gt;.</exception> 5803 public FixedList4096Bytes(in FixedList64Bytes<T> other) 5804 { 5805 this = default; 5806 var error = Initialize(other); 5807 if(error != 0) 5808 FixedList.CheckResize<FixedBytes4096Align8,T>(other.Length); 5809 } 5810 5811 /// <summary> 5812 /// Initializes an instance of FixedList4096Bytes with content copied from another list. 5813 /// </summary> 5814 /// <param name="other">The list to copy.</param> 5815 /// <returns>zero on success, or non-zero on error.</returns> 5816 internal int Initialize(in FixedList64Bytes<T> other) 5817 { 5818 if(other.Length > Capacity) 5819 return (int)CopyError.Truncation; 5820 length = other.length; 5821 unsafe 5822 { 5823 UnsafeUtility.MemCpy(Buffer, other.Buffer, LengthInBytes); 5824 } 5825 return 0; 5826 } 5827 5828 /// <summary> 5829 /// Returns a new list that is a copy of another list. 5830 /// </summary> 5831 /// <param name="other">The list to copy.</param> 5832 /// <returns>A new list that is a copy of the other.</returns> 5833 /// <exception cref="IndexOutOfRangeException">Throws if the other list's length exceeds the capacity of FixedList4096Bytes&lt;T&gt;.</exception> 5834 public static implicit operator FixedList4096Bytes<T>(in FixedList64Bytes<T> other) 5835 { 5836 return new FixedList4096Bytes<T>(other); 5837 } 5838 5839 /// <summary> 5840 /// Returns true if two lists are equal. 5841 /// </summary> 5842 /// <remarks>Two lists are equal if their length and bytes are equal.</remarks> 5843 /// <param name="a">The first list to compare for equality.</param> 5844 /// <param name="b">The second list to compare for equality.</param> 5845 /// <returns>True if the two lists are equal.</returns> 5846 public static bool operator ==(in FixedList4096Bytes<T> a, in FixedList128Bytes<T> b) 5847 { 5848 unsafe 5849 { 5850 if(a.length != b.length) 5851 return false; 5852 return UnsafeUtility.MemCmp(a.Buffer, b.Buffer, a.LengthInBytes) == 0; 5853 } 5854 } 5855 5856 /// <summary> 5857 /// Returns true if two lists are unequal. 5858 /// </summary> 5859 /// <remarks>Two lists are equal if their length and bytes are equal.</remarks> 5860 /// <param name="a">The first list to compare for inequality.</param> 5861 /// <param name="b">The second list to compare for inequality.</param> 5862 /// <returns>True if the two lists are unequal.</returns> 5863 public static bool operator !=(in FixedList4096Bytes<T> a, in FixedList128Bytes<T> b) 5864 { 5865 return !(a == b); 5866 } 5867 5868 /// <summary> 5869 /// Returns a number denoting whether this list should be placed before or after another list in a sort. 5870 /// </summary> 5871 /// <param name="other">A list to to compare with.</param> 5872 /// <returns>An integer denoting the respective sort position of the list relative to the other: 5873 /// 5874 /// 0 denotes that both lists should have the same position in a sort. 5875 /// -1 denotes that this list should precede the other list in a sort. 5876 /// +1 denotes that this list should follow the other list in a sort. 5877 /// </returns> 5878 public int CompareTo(FixedList128Bytes<T> other) 5879 { 5880 unsafe 5881 { 5882 byte* a = buffer; 5883 byte* b = other.buffer; 5884 var aa = a + FixedList.PaddingBytes<T>(); 5885 var bb = b + FixedList.PaddingBytes<T>(); 5886 var mini = math.min(Length, other.Length); 5887 for(var i = 0; i < mini; ++i) 5888 { 5889 var j = UnsafeUtility.MemCmp(aa + sizeof(T) * i, bb + sizeof(T) * i, sizeof(T)); 5890 if(j != 0) 5891 return j; 5892 } 5893 return Length.CompareTo(other.Length); 5894 } 5895 } 5896 5897 /// <summary> 5898 /// Returns true if this list and another list are equal. 5899 /// </summary> 5900 /// <remarks>Two lists are equal if their length and bytes are equal.</remarks> 5901 /// <param name="other">The list to compare for equality.</param> 5902 /// <returns>True if the two lists are equal.</returns> 5903 public bool Equals(FixedList128Bytes<T> other) 5904 { 5905 return CompareTo(other) == 0; 5906 } 5907 5908 5909 /// <summary> 5910 /// Initializes and returns an instance of FixedList4096Bytes with content copied from another list. 5911 /// </summary> 5912 /// <param name="other">The list to copy.</param> 5913 /// <exception cref="IndexOutOfRangeException">Throws if the other list's length exceeds the capacity of FixedList4096Bytes&lt;T&gt;.</exception> 5914 public FixedList4096Bytes(in FixedList128Bytes<T> other) 5915 { 5916 this = default; 5917 var error = Initialize(other); 5918 if(error != 0) 5919 FixedList.CheckResize<FixedBytes4096Align8,T>(other.Length); 5920 } 5921 5922 /// <summary> 5923 /// Initializes an instance of FixedList4096Bytes with content copied from another list. 5924 /// </summary> 5925 /// <param name="other">The list to copy.</param> 5926 /// <returns>zero on success, or non-zero on error.</returns> 5927 internal int Initialize(in FixedList128Bytes<T> other) 5928 { 5929 if(other.Length > Capacity) 5930 return (int)CopyError.Truncation; 5931 length = other.length; 5932 unsafe 5933 { 5934 UnsafeUtility.MemCpy(Buffer, other.Buffer, LengthInBytes); 5935 } 5936 return 0; 5937 } 5938 5939 /// <summary> 5940 /// Returns a new list that is a copy of another list. 5941 /// </summary> 5942 /// <param name="other">The list to copy.</param> 5943 /// <returns>A new list that is a copy of the other.</returns> 5944 /// <exception cref="IndexOutOfRangeException">Throws if the other list's length exceeds the capacity of FixedList4096Bytes&lt;T&gt;.</exception> 5945 public static implicit operator FixedList4096Bytes<T>(in FixedList128Bytes<T> other) 5946 { 5947 return new FixedList4096Bytes<T>(other); 5948 } 5949 5950 /// <summary> 5951 /// Returns true if two lists are equal. 5952 /// </summary> 5953 /// <remarks>Two lists are equal if their length and bytes are equal.</remarks> 5954 /// <param name="a">The first list to compare for equality.</param> 5955 /// <param name="b">The second list to compare for equality.</param> 5956 /// <returns>True if the two lists are equal.</returns> 5957 public static bool operator ==(in FixedList4096Bytes<T> a, in FixedList512Bytes<T> b) 5958 { 5959 unsafe 5960 { 5961 if(a.length != b.length) 5962 return false; 5963 return UnsafeUtility.MemCmp(a.Buffer, b.Buffer, a.LengthInBytes) == 0; 5964 } 5965 } 5966 5967 /// <summary> 5968 /// Returns true if two lists are unequal. 5969 /// </summary> 5970 /// <remarks>Two lists are equal if their length and bytes are equal.</remarks> 5971 /// <param name="a">The first list to compare for inequality.</param> 5972 /// <param name="b">The second list to compare for inequality.</param> 5973 /// <returns>True if the two lists are unequal.</returns> 5974 public static bool operator !=(in FixedList4096Bytes<T> a, in FixedList512Bytes<T> b) 5975 { 5976 return !(a == b); 5977 } 5978 5979 /// <summary> 5980 /// Returns a number denoting whether this list should be placed before or after another list in a sort. 5981 /// </summary> 5982 /// <param name="other">A list to to compare with.</param> 5983 /// <returns>An integer denoting the respective sort position of the list relative to the other: 5984 /// 5985 /// 0 denotes that both lists should have the same position in a sort. 5986 /// -1 denotes that this list should precede the other list in a sort. 5987 /// +1 denotes that this list should follow the other list in a sort. 5988 /// </returns> 5989 public int CompareTo(FixedList512Bytes<T> other) 5990 { 5991 unsafe 5992 { 5993 byte* a = buffer; 5994 byte* b = other.buffer; 5995 var aa = a + FixedList.PaddingBytes<T>(); 5996 var bb = b + FixedList.PaddingBytes<T>(); 5997 var mini = math.min(Length, other.Length); 5998 for(var i = 0; i < mini; ++i) 5999 { 6000 var j = UnsafeUtility.MemCmp(aa + sizeof(T) * i, bb + sizeof(T) * i, sizeof(T)); 6001 if(j != 0) 6002 return j; 6003 } 6004 return Length.CompareTo(other.Length); 6005 } 6006 } 6007 6008 /// <summary> 6009 /// Returns true if this list and another list are equal. 6010 /// </summary> 6011 /// <remarks>Two lists are equal if their length and bytes are equal.</remarks> 6012 /// <param name="other">The list to compare for equality.</param> 6013 /// <returns>True if the two lists are equal.</returns> 6014 public bool Equals(FixedList512Bytes<T> other) 6015 { 6016 return CompareTo(other) == 0; 6017 } 6018 6019 6020 /// <summary> 6021 /// Initializes and returns an instance of FixedList4096Bytes with content copied from another list. 6022 /// </summary> 6023 /// <param name="other">The list to copy.</param> 6024 /// <exception cref="IndexOutOfRangeException">Throws if the other list's length exceeds the capacity of FixedList4096Bytes&lt;T&gt;.</exception> 6025 public FixedList4096Bytes(in FixedList512Bytes<T> other) 6026 { 6027 this = default; 6028 var error = Initialize(other); 6029 if(error != 0) 6030 FixedList.CheckResize<FixedBytes4096Align8,T>(other.Length); 6031 } 6032 6033 /// <summary> 6034 /// Initializes an instance of FixedList4096Bytes with content copied from another list. 6035 /// </summary> 6036 /// <param name="other">The list to copy.</param> 6037 /// <returns>zero on success, or non-zero on error.</returns> 6038 internal int Initialize(in FixedList512Bytes<T> other) 6039 { 6040 if(other.Length > Capacity) 6041 return (int)CopyError.Truncation; 6042 length = other.length; 6043 unsafe 6044 { 6045 UnsafeUtility.MemCpy(Buffer, other.Buffer, LengthInBytes); 6046 } 6047 return 0; 6048 } 6049 6050 /// <summary> 6051 /// Returns a new list that is a copy of another list. 6052 /// </summary> 6053 /// <param name="other">The list to copy.</param> 6054 /// <returns>A new list that is a copy of the other.</returns> 6055 /// <exception cref="IndexOutOfRangeException">Throws if the other list's length exceeds the capacity of FixedList4096Bytes&lt;T&gt;.</exception> 6056 public static implicit operator FixedList4096Bytes<T>(in FixedList512Bytes<T> other) 6057 { 6058 return new FixedList4096Bytes<T>(other); 6059 } 6060 6061 /// <summary> 6062 /// Returns true if two lists are equal. 6063 /// </summary> 6064 /// <remarks>Two lists are equal if their length and bytes are equal.</remarks> 6065 /// <param name="a">The first list to compare for equality.</param> 6066 /// <param name="b">The second list to compare for equality.</param> 6067 /// <returns>True if the two lists are equal.</returns> 6068 public static bool operator ==(in FixedList4096Bytes<T> a, in FixedList4096Bytes<T> b) 6069 { 6070 unsafe 6071 { 6072 if(a.length != b.length) 6073 return false; 6074 return UnsafeUtility.MemCmp(a.Buffer, b.Buffer, a.LengthInBytes) == 0; 6075 } 6076 } 6077 6078 /// <summary> 6079 /// Returns true if two lists are unequal. 6080 /// </summary> 6081 /// <remarks>Two lists are equal if their length and bytes are equal.</remarks> 6082 /// <param name="a">The first list to compare for inequality.</param> 6083 /// <param name="b">The second list to compare for inequality.</param> 6084 /// <returns>True if the two lists are unequal.</returns> 6085 public static bool operator !=(in FixedList4096Bytes<T> a, in FixedList4096Bytes<T> b) 6086 { 6087 return !(a == b); 6088 } 6089 6090 /// <summary> 6091 /// Returns a number denoting whether this list should be placed before or after another list in a sort. 6092 /// </summary> 6093 /// <param name="other">A list to to compare with.</param> 6094 /// <returns>An integer denoting the respective sort position of the list relative to the other: 6095 /// 6096 /// 0 denotes that both lists should have the same position in a sort. 6097 /// -1 denotes that this list should precede the other list in a sort. 6098 /// +1 denotes that this list should follow the other list in a sort. 6099 /// </returns> 6100 public int CompareTo(FixedList4096Bytes<T> other) 6101 { 6102 unsafe 6103 { 6104 byte* a = buffer; 6105 byte* b = other.buffer; 6106 var aa = a + FixedList.PaddingBytes<T>(); 6107 var bb = b + FixedList.PaddingBytes<T>(); 6108 var mini = math.min(Length, other.Length); 6109 for(var i = 0; i < mini; ++i) 6110 { 6111 var j = UnsafeUtility.MemCmp(aa + sizeof(T) * i, bb + sizeof(T) * i, sizeof(T)); 6112 if(j != 0) 6113 return j; 6114 } 6115 return Length.CompareTo(other.Length); 6116 } 6117 } 6118 6119 /// <summary> 6120 /// Returns true if this list and another list are equal. 6121 /// </summary> 6122 /// <remarks>Two lists are equal if their length and bytes are equal.</remarks> 6123 /// <param name="other">The list to compare for equality.</param> 6124 /// <returns>True if the two lists are equal.</returns> 6125 public bool Equals(FixedList4096Bytes<T> other) 6126 { 6127 return CompareTo(other) == 0; 6128 } 6129 6130 6131 /// <summary> 6132 /// Returns true if the list is equal to an object. 6133 /// </summary> 6134 /// <remarks>Two lists are equal if their length and bytes are equal. 6135 /// 6136 /// A FixedList*N*&lt;T&gt; can only be equal to another FixedList*N*&lt;T&gt; with the same *N* and T. 6137 /// </remarks> 6138 /// <param name="obj">An object to compare for equality.</param> 6139 /// <returns>True if the list is equal to the object.</returns> 6140 [ExcludeFromBurstCompatTesting("Takes managed object")] 6141 public override bool Equals(object obj) 6142 { 6143 if(obj is FixedList32Bytes<T> aFixedList32Bytes) return Equals(aFixedList32Bytes); 6144 if(obj is FixedList64Bytes<T> aFixedList64Bytes) return Equals(aFixedList64Bytes); 6145 if(obj is FixedList128Bytes<T> aFixedList128Bytes) return Equals(aFixedList128Bytes); 6146 if(obj is FixedList512Bytes<T> aFixedList512Bytes) return Equals(aFixedList512Bytes); 6147 if(obj is FixedList4096Bytes<T> aFixedList4096Bytes) return Equals(aFixedList4096Bytes); 6148 return false; 6149 } 6150 6151 /// <summary> 6152 /// An enumerator over the elements of a FixedList4096Bytes&lt;T&gt;. 6153 /// </summary> 6154 /// <remarks> 6155 /// In an enumerator's initial state, `Current` cannot be read. The first <see cref="MoveNext"/> call advances the enumerator to the first element. 6156 /// </remarks> 6157 public struct Enumerator : IEnumerator<T> 6158 { 6159 FixedList4096Bytes<T> m_List; 6160 int m_Index; 6161 6162 /// <summary> 6163 /// Initializes and returns an instance of FixedList4096Bytes&lt;T&gt;. 6164 /// </summary> 6165 /// <param name="list">The list for which to create an enumerator.</param> 6166 public Enumerator(ref FixedList4096Bytes<T> list) 6167 { 6168 m_List = list; 6169 m_Index = -1; 6170 } 6171 6172 /// <summary> 6173 /// Does nothing. 6174 /// </summary> 6175 public void Dispose() 6176 { 6177 } 6178 6179 /// <summary> 6180 /// Advances the enumerator to the next element. 6181 /// </summary> 6182 /// <returns>True if <see cref="Current"/> is valid to read after the call.</returns> 6183 [MethodImpl(MethodImplOptions.AggressiveInlining)] 6184 public bool MoveNext() 6185 { 6186 m_Index++; 6187 return m_Index < m_List.Length; 6188 } 6189 6190 /// <summary> 6191 /// Resets the enumerator to its initial state. 6192 /// </summary> 6193 public void Reset() 6194 { 6195 m_Index = -1; 6196 } 6197 6198 /// <summary> 6199 /// The current element. 6200 /// </summary> 6201 /// <value>The current element.</value> 6202 public T Current 6203 { 6204 [MethodImpl(MethodImplOptions.AggressiveInlining)] 6205 get => m_List[m_Index]; // Let FixedList4096Bytes<T> indexer check for out of range. 6206 } 6207 6208 object IEnumerator.Current => Current; 6209 } 6210 6211 /// <summary> 6212 /// Returns an enumerator for iterating over the elements of this list. 6213 /// </summary> 6214 /// <returns>An enumerator for iterating over the elements of this list.</returns> 6215 public Enumerator GetEnumerator() 6216 { 6217 return new Enumerator(ref this); 6218 } 6219 6220 /// <summary> 6221 /// This method is not implemented. Use <see cref="GetEnumerator"/> instead. 6222 /// </summary> 6223 /// <returns>Nothing because it always throws <see cref="NotImplementedException"/>.</returns> 6224 /// <exception cref="NotImplementedException">Method is not implemented.</exception> 6225 IEnumerator IEnumerable.GetEnumerator() 6226 { 6227 throw new NotImplementedException(); 6228 } 6229 6230 /// <summary> 6231 /// This method is not implemented. Use <see cref="GetEnumerator"/> instead. 6232 /// </summary> 6233 /// <returns>Nothing because it always throws <see cref="NotImplementedException"/>.</returns> 6234 /// <exception cref="NotImplementedException">Method is not implemented.</exception> 6235 IEnumerator<T> IEnumerable<T>.GetEnumerator() 6236 { 6237 throw new NotImplementedException(); 6238 } 6239 } 6240 6241 /// <summary> 6242 /// Provides extension methods for FixedList4096Bytes. 6243 /// </summary> 6244 [GenerateTestsForBurstCompatibility] 6245 public unsafe static class FixedList4096BytesExtensions 6246 { 6247 /// <summary> 6248 /// Finds the index of the first occurrence of a particular value in this list. 6249 /// </summary> 6250 /// <typeparam name="T">The type of elements in this list.</typeparam> 6251 /// <typeparam name="U">The value type.</typeparam> 6252 /// <param name="list">The list to search.</param> 6253 /// <param name="value">The value to locate.</param> 6254 /// <returns>The index of the first occurrence of the value. Returns -1 if no occurrence is found.</returns> 6255 [GenerateTestsForBurstCompatibility(GenericTypeArguments = new [] { typeof(int), typeof(int) })] 6256 public static int IndexOf<T, U>(this ref FixedList4096Bytes<T> list, U value) where T : unmanaged, IEquatable<U> 6257 { 6258 return NativeArrayExtensions.IndexOf<T, U>(list.Buffer, list.Length, value); 6259 } 6260 6261 /// <summary> 6262 /// Returns true if a particular value is present in this list. 6263 /// </summary> 6264 /// <typeparam name="T">The type of elements in this list.</typeparam> 6265 /// <typeparam name="U">The value type.</typeparam> 6266 /// <param name="list">The list to search.</param> 6267 /// <param name="value">The value to locate.</param> 6268 /// <returns>True if the value is present in this list.</returns> 6269 [GenerateTestsForBurstCompatibility(GenericTypeArguments = new [] { typeof(int), typeof(int) })] 6270 public static bool Contains<T, U>(this ref FixedList4096Bytes<T> list, U value) where T : unmanaged, IEquatable<U> 6271 { 6272 return list.IndexOf(value) != -1; 6273 } 6274 6275 /// <summary> 6276 /// Removes the first occurrence of a particular value in this list. 6277 /// </summary> 6278 /// <remarks> 6279 /// If a value is removed, all elements after it are shifted down by one, and the list's length is decremented by one. 6280 /// 6281 /// If you don't need to preserve the order of the remaining elements, <see cref="Unity.Collections.FixedList4096BytesExtensions.RemoveSwapBack{T, U}"/> is a cheaper alternative. 6282 /// </remarks> 6283 /// <typeparam name="T">The type of elements in this list.</typeparam> 6284 /// <typeparam name="U">The value type.</typeparam> 6285 /// <param name="list">The list to search.</param> 6286 /// <param name="value">The value to locate and remove.</param> 6287 /// <returns>True if the value was found and removed.</returns> 6288 [GenerateTestsForBurstCompatibility(GenericTypeArguments = new [] { typeof(int), typeof(int) })] 6289 public static bool Remove<T, U>(this ref FixedList4096Bytes<T> list, U value) where T : unmanaged, IEquatable<U> 6290 { 6291 int index = list.IndexOf(value); 6292 if (index < 0) 6293 { 6294 return false; 6295 } 6296 6297 list.RemoveAt(index); 6298 6299 return true; 6300 } 6301 6302 /// <summary> 6303 /// Removes the first occurrence of a particular value in this list. 6304 /// </summary> 6305 /// <remarks> 6306 /// 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. 6307 /// 6308 /// This is cheaper than <see cref="Remove"/>, but the order of the remaining elements is not preserved. 6309 /// </remarks> 6310 /// <typeparam name="T">The type of elements in this list.</typeparam> 6311 /// <typeparam name="U">The value type.</typeparam> 6312 /// <param name="list">The list to search.</param> 6313 /// <param name="value">The value to locate and remove.</param> 6314 /// <returns>Returns true if the item is removed.</returns> 6315 [GenerateTestsForBurstCompatibility(GenericTypeArguments = new [] { typeof(int), typeof(int) })] 6316 public static bool RemoveSwapBack<T, U>(this ref FixedList4096Bytes<T> list, U value) where T : unmanaged, IEquatable<U> 6317 { 6318 var index = list.IndexOf(value); 6319 if (index == -1) 6320 { 6321 return false; 6322 } 6323 6324 list.RemoveAtSwapBack(index); 6325 6326 return true; 6327 } 6328 } 6329 6330 sealed class FixedList4096BytesDebugView<T> where T : unmanaged 6331 { 6332 FixedList4096Bytes<T> m_List; 6333 public FixedList4096BytesDebugView(FixedList4096Bytes<T> list) 6334 { 6335 m_List = list; 6336 } 6337 public T[] Items => m_List.ToArray(); 6338 } 6339 6340 6341 6342 6343 6344 6345 6346 6347 6348 6349 6350 6351 6352 6353 6354 6355 6356 6357 6358 6359 6360 6361 6362 6363 6364 6365 6366 6367 6368 6369 6370 /// <summary> 6371 /// Provides extension methods for FixedList*N*. 6372 /// </summary> 6373 public static class FixedListExtensions 6374 { 6375 6376 /// <summary> 6377 /// Sorts the elements in this list in ascending order. 6378 /// </summary> 6379 /// <typeparam name="T">The type of the elements.</typeparam> 6380 /// <param name="list">The list to sort.</param> 6381 [GenerateTestsForBurstCompatibility(GenericTypeArguments = new [] { typeof(int) })] 6382 public static void Sort<T>(this ref FixedList32Bytes<T> list) 6383 where T : unmanaged, IComparable<T> 6384 { 6385 unsafe 6386 { 6387 var c = list.buffer + FixedList.PaddingBytes<T>(); 6388 NativeSortExtension.Sort((T*)c, list.Length); 6389 } 6390 } 6391 6392 /// <summary> 6393 /// Sorts the elements in this list using a custom comparison. 6394 /// </summary> 6395 /// <typeparam name="T">The type of the elements.</typeparam> 6396 /// <typeparam name="U">The type of the comparer.</typeparam> 6397 /// <param name="list">The list to sort.</param> 6398 /// <param name="comp">The comparison function used to determine the relative order of the elements.</param> 6399 [GenerateTestsForBurstCompatibility(GenericTypeArguments = new [] { typeof(int), typeof(NativeSortExtension.DefaultComparer<int>) })] 6400 public static void Sort<T, U>(this ref FixedList32Bytes<T> list, U comp) 6401 where T : unmanaged, IComparable<T> 6402 where U : IComparer<T> 6403 { 6404 unsafe 6405 { 6406 var c = list.buffer + FixedList.PaddingBytes<T>(); 6407 NativeSortExtension.Sort((T*)c, list.Length, comp); 6408 } 6409 } 6410 6411 6412 /// <summary> 6413 /// Sorts the elements in this list in ascending order. 6414 /// </summary> 6415 /// <typeparam name="T">The type of the elements.</typeparam> 6416 /// <param name="list">The list to sort.</param> 6417 [GenerateTestsForBurstCompatibility(GenericTypeArguments = new [] { typeof(int) })] 6418 public static void Sort<T>(this ref FixedList64Bytes<T> list) 6419 where T : unmanaged, IComparable<T> 6420 { 6421 unsafe 6422 { 6423 var c = list.buffer + FixedList.PaddingBytes<T>(); 6424 NativeSortExtension.Sort((T*)c, list.Length); 6425 } 6426 } 6427 6428 /// <summary> 6429 /// Sorts the elements in this list using a custom comparison. 6430 /// </summary> 6431 /// <typeparam name="T">The type of the elements.</typeparam> 6432 /// <typeparam name="U">The type of the comparer.</typeparam> 6433 /// <param name="list">The list to sort.</param> 6434 /// <param name="comp">The comparison function used to determine the relative order of the elements.</param> 6435 [GenerateTestsForBurstCompatibility(GenericTypeArguments = new [] { typeof(int), typeof(NativeSortExtension.DefaultComparer<int>) })] 6436 public static void Sort<T, U>(this ref FixedList64Bytes<T> list, U comp) 6437 where T : unmanaged, IComparable<T> 6438 where U : IComparer<T> 6439 { 6440 unsafe 6441 { 6442 var c = list.buffer + FixedList.PaddingBytes<T>(); 6443 NativeSortExtension.Sort((T*)c, list.Length, comp); 6444 } 6445 } 6446 6447 6448 /// <summary> 6449 /// Sorts the elements in this list in ascending order. 6450 /// </summary> 6451 /// <typeparam name="T">The type of the elements.</typeparam> 6452 /// <param name="list">The list to sort.</param> 6453 [GenerateTestsForBurstCompatibility(GenericTypeArguments = new [] { typeof(int) })] 6454 public static void Sort<T>(this ref FixedList128Bytes<T> list) 6455 where T : unmanaged, IComparable<T> 6456 { 6457 unsafe 6458 { 6459 var c = list.buffer + FixedList.PaddingBytes<T>(); 6460 NativeSortExtension.Sort((T*)c, list.Length); 6461 } 6462 } 6463 6464 /// <summary> 6465 /// Sorts the elements in this list using a custom comparison. 6466 /// </summary> 6467 /// <typeparam name="T">The type of the elements.</typeparam> 6468 /// <typeparam name="U">The type of the comparer.</typeparam> 6469 /// <param name="list">The list to sort.</param> 6470 /// <param name="comp">The comparison function used to determine the relative order of the elements.</param> 6471 [GenerateTestsForBurstCompatibility(GenericTypeArguments = new [] { typeof(int), typeof(NativeSortExtension.DefaultComparer<int>) })] 6472 public static void Sort<T, U>(this ref FixedList128Bytes<T> list, U comp) 6473 where T : unmanaged, IComparable<T> 6474 where U : IComparer<T> 6475 { 6476 unsafe 6477 { 6478 var c = list.buffer + FixedList.PaddingBytes<T>(); 6479 NativeSortExtension.Sort((T*)c, list.Length, comp); 6480 } 6481 } 6482 6483 6484 /// <summary> 6485 /// Sorts the elements in this list in ascending order. 6486 /// </summary> 6487 /// <typeparam name="T">The type of the elements.</typeparam> 6488 /// <param name="list">The list to sort.</param> 6489 [GenerateTestsForBurstCompatibility(GenericTypeArguments = new [] { typeof(int) })] 6490 public static void Sort<T>(this ref FixedList512Bytes<T> list) 6491 where T : unmanaged, IComparable<T> 6492 { 6493 unsafe 6494 { 6495 var c = list.buffer + FixedList.PaddingBytes<T>(); 6496 NativeSortExtension.Sort((T*)c, list.Length); 6497 } 6498 } 6499 6500 /// <summary> 6501 /// Sorts the elements in this list using a custom comparison. 6502 /// </summary> 6503 /// <typeparam name="T">The type of the elements.</typeparam> 6504 /// <typeparam name="U">The type of the comparer.</typeparam> 6505 /// <param name="list">The list to sort.</param> 6506 /// <param name="comp">The comparison function used to determine the relative order of the elements.</param> 6507 [GenerateTestsForBurstCompatibility(GenericTypeArguments = new [] { typeof(int), typeof(NativeSortExtension.DefaultComparer<int>) })] 6508 public static void Sort<T, U>(this ref FixedList512Bytes<T> list, U comp) 6509 where T : unmanaged, IComparable<T> 6510 where U : IComparer<T> 6511 { 6512 unsafe 6513 { 6514 var c = list.buffer + FixedList.PaddingBytes<T>(); 6515 NativeSortExtension.Sort((T*)c, list.Length, comp); 6516 } 6517 } 6518 6519 6520 /// <summary> 6521 /// Sorts the elements in this list in ascending order. 6522 /// </summary> 6523 /// <typeparam name="T">The type of the elements.</typeparam> 6524 /// <param name="list">The list to sort.</param> 6525 [GenerateTestsForBurstCompatibility(GenericTypeArguments = new [] { typeof(int) })] 6526 public static void Sort<T>(this ref FixedList4096Bytes<T> list) 6527 where T : unmanaged, IComparable<T> 6528 { 6529 unsafe 6530 { 6531 var c = list.buffer + FixedList.PaddingBytes<T>(); 6532 NativeSortExtension.Sort((T*)c, list.Length); 6533 } 6534 } 6535 6536 /// <summary> 6537 /// Sorts the elements in this list using a custom comparison. 6538 /// </summary> 6539 /// <typeparam name="T">The type of the elements.</typeparam> 6540 /// <typeparam name="U">The type of the comparer.</typeparam> 6541 /// <param name="list">The list to sort.</param> 6542 /// <param name="comp">The comparison function used to determine the relative order of the elements.</param> 6543 [GenerateTestsForBurstCompatibility(GenericTypeArguments = new [] { typeof(int), typeof(NativeSortExtension.DefaultComparer<int>) })] 6544 public static void Sort<T, U>(this ref FixedList4096Bytes<T> list, U comp) 6545 where T : unmanaged, IComparable<T> 6546 where U : IComparer<T> 6547 { 6548 unsafe 6549 { 6550 var c = list.buffer + FixedList.PaddingBytes<T>(); 6551 NativeSortExtension.Sort((T*)c, list.Length, comp); 6552 } 6553 } 6554 6555 } 6556}