OneOrMore.cs 2.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. using System;
  2. using System.Collections;
  3. using System.Collections.Generic;
  4. namespace UnityEngine.InputSystem.Utilities
  5. {
  6. /// <summary>
  7. /// Helper when having either a single element or a list of elements. Avoids
  8. /// having to allocate GC heap garbage or having to alternatively split code paths.
  9. /// </summary>
  10. /// <typeparam name="TValue"></typeparam>
  11. internal struct OneOrMore<TValue, TList> : IReadOnlyList<TValue>
  12. where TList : IReadOnlyList<TValue>
  13. {
  14. private readonly bool m_IsSingle;
  15. private readonly TValue m_Single;
  16. private readonly TList m_Multiple;
  17. public int Count => m_IsSingle ? 1 : m_Multiple.Count;
  18. public TValue this[int index]
  19. {
  20. get
  21. {
  22. if (!m_IsSingle)
  23. return m_Multiple[index];
  24. if (index < 0 || index > 1)
  25. throw new ArgumentOutOfRangeException(nameof(index));
  26. return m_Single;
  27. }
  28. }
  29. public OneOrMore(TValue single)
  30. {
  31. m_IsSingle = true;
  32. m_Single = single;
  33. m_Multiple = default;
  34. }
  35. public OneOrMore(TList multiple)
  36. {
  37. m_IsSingle = false;
  38. m_Single = default;
  39. m_Multiple = multiple;
  40. }
  41. public static implicit operator OneOrMore<TValue, TList>(TValue single)
  42. {
  43. return new OneOrMore<TValue, TList>(single);
  44. }
  45. public static implicit operator OneOrMore<TValue, TList>(TList multiple)
  46. {
  47. return new OneOrMore<TValue, TList>(multiple);
  48. }
  49. public IEnumerator<TValue> GetEnumerator()
  50. {
  51. return new Enumerator { m_List = this };
  52. }
  53. IEnumerator IEnumerable.GetEnumerator()
  54. {
  55. return GetEnumerator();
  56. }
  57. private class Enumerator : IEnumerator<TValue>
  58. {
  59. internal int m_Index = -1;
  60. internal OneOrMore<TValue, TList> m_List;
  61. public bool MoveNext()
  62. {
  63. if (m_Index >= m_List.Count)
  64. return false;
  65. ++m_Index;
  66. return true;
  67. }
  68. public void Reset()
  69. {
  70. m_Index = -1;
  71. }
  72. public TValue Current => m_List[m_Index];
  73. object IEnumerator.Current => Current;
  74. public void Dispose()
  75. {
  76. }
  77. }
  78. }
  79. }