1- #if ! NETCOREAPP && ! NETSTANDARD2_1
2- using System . Runtime . CompilerServices ;
3- using Microsoft . CodeAnalysis ;
4-
5- namespace System ;
6-
7- /// <summary>Represent a range has start and end indexes.</summary>
8- /// <remarks>
9- /// Range is used by the C# compiler to support the range syntax.
10- /// <code>
11- /// int[] someArray = new int[5] { 1, 2, 3, 4, 5 };
12- /// int[] subArray1 = someArray[0..2]; // { 1, 2 }
13- /// int[] subArray2 = someArray[1..^0]; // { 2, 3, 4, 5 }
14- /// </code>
15- /// </remarks>
16- #if EMBED_SYSTEM_TYPES
17- [ Embedded ]
18- #endif
19- internal readonly struct Range : IEquatable < Range >
20- {
21- /// <summary>Represent the inclusive start index of the Range.</summary>
22- public Index Start { get ; }
23-
24- /// <summary>Represent the exclusive end index of the Range.</summary>
25- public Index End { get ; }
26-
27- /// <summary>Construct a Range object using the start and end indexes.</summary>
28- /// <param name="start">Represent the inclusive start index of the range.</param>
29- /// <param name="end">Represent the exclusive end index of the range.</param>
30- public Range ( Index start , Index end )
31- {
32- Start = start ;
33- End = end ;
34- }
35-
36- /// <summary>Indicates whether the current Range object is equal to another object of the same type.</summary>
37- /// <param name="value">An object to compare with this object</param>
38- public override bool Equals ( object ? value )
39- => value is Range r &&
40- r . Start . Equals ( Start ) &&
41- r . End . Equals ( End ) ;
42-
43- /// <summary>Indicates whether the current Range object is equal to another Range object.</summary>
44- /// <param name="other">An object to compare with this object</param>
45- public bool Equals ( Range other ) => other . Start . Equals ( Start ) && other . End . Equals ( End ) ;
46-
47- /// <summary>Returns the hash code for this instance.</summary>
48- public override int GetHashCode ( )
49- {
50- return Start . GetHashCode ( ) * 31 + End . GetHashCode ( ) ;
51- }
52-
53- /// <summary>Converts the value of the current Range object to its equivalent string representation.</summary>
54- public override string ToString ( )
55- {
56- return Start + ".." + End ;
57- }
58-
59- /// <summary>Create a Range object starting from start index to the end of the collection.</summary>
60- public static Range StartAt ( Index start ) => new ( start , Index . End ) ;
61-
62- /// <summary>Create a Range object starting from first element in the collection to the end Index.</summary>
63- public static Range EndAt ( Index end ) => new ( Index . Start , end ) ;
64-
65- /// <summary>Create a Range object starting from first element to the end.</summary>
66- public static Range All => new ( Index . Start , Index . End ) ;
67-
68- /// <summary>Calculate the start offset and length of range object using a collection length.</summary>
69- /// <param name="length">The length of the collection that the range will be used with. length has to be a positive value.</param>
70- /// <remarks>
71- /// For performance reason, we don't validate the input length parameter against negative values.
72- /// It is expected Range will be used with collections which always have non negative length/count.
73- /// We validate the range is inside the length scope though.
74- /// </remarks>
75- [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
76- public ( int Offset , int Length ) GetOffsetAndLength ( int length )
77- {
78- int start ;
79- var startIndex = Start ;
80-
81- if ( startIndex . IsFromEnd )
82- {
83- start = length - startIndex . Value ;
84- }
85- else
86- {
87- start = startIndex . Value ;
88- }
89-
90- int end ;
91- var endIndex = End ;
92-
93- if ( endIndex . IsFromEnd )
94- {
95- end = length - endIndex . Value ;
96- }
97- else
98- {
99- end = endIndex . Value ;
100- }
101-
102- if ( ( uint ) end > ( uint ) length || ( uint ) start > ( uint ) end )
103- {
104- throw new ArgumentOutOfRangeException ( nameof ( length ) ) ;
105- }
106-
107- return ( start , end - start ) ;
108- }
109- }
1+ #if ! NETCOREAPP && ! NETSTANDARD2_1 && ! USING_SYSTEM_BCL_MEMORY
2+ using System . Runtime . CompilerServices ;
3+ using Microsoft . CodeAnalysis ;
4+
5+ namespace System ;
6+
7+ /// <summary>Represent a range has start and end indexes.</summary>
8+ /// <remarks>
9+ /// Range is used by the C# compiler to support the range syntax.
10+ /// <code>
11+ /// int[] someArray = new int[5] { 1, 2, 3, 4, 5 };
12+ /// int[] subArray1 = someArray[0..2]; // { 1, 2 }
13+ /// int[] subArray2 = someArray[1..^0]; // { 2, 3, 4, 5 }
14+ /// </code>
15+ /// </remarks>
16+ #if EMBED_SYSTEM_TYPES
17+ [ Embedded ]
18+ #endif
19+ internal readonly struct Range : IEquatable < Range >
20+ {
21+ /// <summary>Represent the inclusive start index of the Range.</summary>
22+ public Index Start { get ; }
23+
24+ /// <summary>Represent the exclusive end index of the Range.</summary>
25+ public Index End { get ; }
26+
27+ /// <summary>Construct a Range object using the start and end indexes.</summary>
28+ /// <param name="start">Represent the inclusive start index of the range.</param>
29+ /// <param name="end">Represent the exclusive end index of the range.</param>
30+ public Range ( Index start , Index end )
31+ {
32+ Start = start ;
33+ End = end ;
34+ }
35+
36+ /// <summary>Indicates whether the current Range object is equal to another object of the same type.</summary>
37+ /// <param name="value">An object to compare with this object</param>
38+ public override bool Equals ( object ? value )
39+ => value is Range r &&
40+ r . Start . Equals ( Start ) &&
41+ r . End . Equals ( End ) ;
42+
43+ /// <summary>Indicates whether the current Range object is equal to another Range object.</summary>
44+ /// <param name="other">An object to compare with this object</param>
45+ public bool Equals ( Range other ) => other . Start . Equals ( Start ) && other . End . Equals ( End ) ;
46+
47+ /// <summary>Returns the hash code for this instance.</summary>
48+ public override int GetHashCode ( )
49+ {
50+ return Start . GetHashCode ( ) * 31 + End . GetHashCode ( ) ;
51+ }
52+
53+ /// <summary>Converts the value of the current Range object to its equivalent string representation.</summary>
54+ public override string ToString ( )
55+ {
56+ return Start + ".." + End ;
57+ }
58+
59+ /// <summary>Create a Range object starting from start index to the end of the collection.</summary>
60+ public static Range StartAt ( Index start ) => new ( start , Index . End ) ;
61+
62+ /// <summary>Create a Range object starting from first element in the collection to the end Index.</summary>
63+ public static Range EndAt ( Index end ) => new ( Index . Start , end ) ;
64+
65+ /// <summary>Create a Range object starting from first element to the end.</summary>
66+ public static Range All => new ( Index . Start , Index . End ) ;
67+
68+ /// <summary>Calculate the start offset and length of range object using a collection length.</summary>
69+ /// <param name="length">The length of the collection that the range will be used with. length has to be a positive value.</param>
70+ /// <remarks>
71+ /// For performance reason, we don't validate the input length parameter against negative values.
72+ /// It is expected Range will be used with collections which always have non negative length/count.
73+ /// We validate the range is inside the length scope though.
74+ /// </remarks>
75+ [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
76+ public ( int Offset , int Length ) GetOffsetAndLength ( int length )
77+ {
78+ int start ;
79+ var startIndex = Start ;
80+
81+ if ( startIndex . IsFromEnd )
82+ {
83+ start = length - startIndex . Value ;
84+ }
85+ else
86+ {
87+ start = startIndex . Value ;
88+ }
89+
90+ int end ;
91+ var endIndex = End ;
92+
93+ if ( endIndex . IsFromEnd )
94+ {
95+ end = length - endIndex . Value ;
96+ }
97+ else
98+ {
99+ end = endIndex . Value ;
100+ }
101+
102+ if ( ( uint ) end > ( uint ) length || ( uint ) start > ( uint ) end )
103+ {
104+ throw new ArgumentOutOfRangeException ( nameof ( length ) ) ;
105+ }
106+
107+ return ( start , end - start ) ;
108+ }
109+ }
110110#endif
0 commit comments