1
1
// Licensed to the .NET Foundation under one or more agreements.
2
2
// The .NET Foundation licenses this file to you under the MIT license.
3
3
4
+ using System ;
5
+ using System . Diagnostics ;
4
6
using System . Text ;
5
7
6
8
namespace Microsoft . NETCore . Platforms . BuildTasks
7
9
{
8
- internal class RID
10
+ public class RID
9
11
{
12
+ internal const char VersionDelimiter = '.' ;
13
+ internal const char ArchitectureDelimiter = '-' ;
14
+ internal const char QualifierDelimiter = '-' ;
15
+
10
16
public string BaseRID { get ; set ; }
11
- public string VersionDelimiter { get ; set ; }
12
- public string Version { get ; set ; }
13
- public string ArchitectureDelimiter { get ; set ; }
17
+ public bool OmitVersionDelimiter { get ; set ; }
18
+ public RuntimeVersion Version { get ; set ; }
14
19
public string Architecture { get ; set ; }
15
- public string QualifierDelimiter { get ; set ; }
16
20
public string Qualifier { get ; set ; }
17
21
18
22
public override string ToString ( )
19
23
{
20
24
StringBuilder builder = new StringBuilder ( BaseRID ) ;
21
25
22
- if ( HasVersion ( ) )
26
+ if ( HasVersion )
23
27
{
24
- builder . Append ( VersionDelimiter ) ;
28
+ if ( ! OmitVersionDelimiter )
29
+ {
30
+ builder . Append ( VersionDelimiter ) ;
31
+ }
25
32
builder . Append ( Version ) ;
26
33
}
27
34
28
- if ( HasArchitecture ( ) )
35
+ if ( HasArchitecture )
29
36
{
30
37
builder . Append ( ArchitectureDelimiter ) ;
31
38
builder . Append ( Architecture ) ;
32
39
}
33
40
34
- if ( HasQualifier ( ) )
41
+ if ( HasQualifier )
35
42
{
36
43
builder . Append ( QualifierDelimiter ) ;
37
44
builder . Append ( Qualifier ) ;
@@ -40,20 +47,153 @@ public override string ToString()
40
47
return builder . ToString ( ) ;
41
48
}
42
49
43
- public bool HasVersion ( )
50
+ private enum RIDPart : int
51
+ {
52
+ Base = 0 ,
53
+ Version ,
54
+ Architcture ,
55
+ Qualifier ,
56
+ Max = Qualifier
57
+ }
58
+
59
+ public static RID Parse ( string runtimeIdentifier )
60
+ {
61
+ string [ ] parts = new string [ ( int ) RIDPart . Max + 1 ] ;
62
+ bool omitVersionDelimiter = true ;
63
+ RIDPart parseState = RIDPart . Base ;
64
+
65
+ int partStart = 0 , partLength = 0 ;
66
+
67
+ // qualifier is indistinguishable from arch so we cannot distinguish it for parsing purposes
68
+ Debug . Assert ( ArchitectureDelimiter == QualifierDelimiter ) ;
69
+
70
+ for ( int i = 0 ; i < runtimeIdentifier . Length ; i ++ )
71
+ {
72
+ char current = runtimeIdentifier [ i ] ;
73
+ partLength = i - partStart ;
74
+
75
+ switch ( parseState )
76
+ {
77
+ case RIDPart . Base :
78
+ // treat any number as the start of the version
79
+ if ( current == VersionDelimiter || ( current >= '0' && current <= '9' ) )
80
+ {
81
+ SetPart ( ) ;
82
+ partStart = i ;
83
+ if ( current == VersionDelimiter )
84
+ {
85
+ omitVersionDelimiter = false ;
86
+ partStart = i + 1 ;
87
+ }
88
+ parseState = RIDPart . Version ;
89
+ }
90
+ // version might be omitted
91
+ else if ( current == ArchitectureDelimiter )
92
+ {
93
+ // ensure there's no version later in the string
94
+ if ( - 1 != runtimeIdentifier . IndexOf ( VersionDelimiter , i ) )
95
+ {
96
+ break ;
97
+ }
98
+ SetPart ( ) ;
99
+ partStart = i + 1 ; // skip delimiter
100
+ parseState = RIDPart . Architcture ;
101
+ }
102
+ break ;
103
+ case RIDPart . Version :
104
+ if ( current == ArchitectureDelimiter )
105
+ {
106
+ SetPart ( ) ;
107
+ partStart = i + 1 ; // skip delimiter
108
+ parseState = RIDPart . Architcture ;
109
+ }
110
+ break ;
111
+ case RIDPart . Architcture :
112
+ if ( current == QualifierDelimiter )
113
+ {
114
+ SetPart ( ) ;
115
+ partStart = i + 1 ; // skip delimiter
116
+ parseState = RIDPart . Qualifier ;
117
+ }
118
+ break ;
119
+ default :
120
+ break ;
121
+ }
122
+ }
123
+
124
+ partLength = runtimeIdentifier . Length - partStart ;
125
+ if ( partLength > 0 )
126
+ {
127
+ SetPart ( ) ;
128
+ }
129
+
130
+ string GetPart ( RIDPart part )
131
+ {
132
+ return parts [ ( int ) part ] ;
133
+ }
134
+
135
+ void SetPart ( )
136
+ {
137
+ if ( partLength == 0 )
138
+ {
139
+ throw new ArgumentException ( $ "unexpected delimiter at position { partStart } in { runtimeIdentifier } ") ;
140
+ }
141
+
142
+ parts [ ( int ) parseState ] = runtimeIdentifier . Substring ( partStart , partLength ) ;
143
+ }
144
+
145
+ string version = GetPart ( RIDPart . Version ) ;
146
+
147
+ if ( version == null )
148
+ {
149
+ omitVersionDelimiter = false ;
150
+ }
151
+
152
+ return new RID ( )
153
+ {
154
+ BaseRID = GetPart ( RIDPart . Base ) ,
155
+ OmitVersionDelimiter = omitVersionDelimiter ,
156
+ Version = version == null ? null : new RuntimeVersion ( version ) ,
157
+ Architecture = GetPart ( RIDPart . Architcture ) ,
158
+ Qualifier = GetPart ( RIDPart . Qualifier )
159
+ } ;
160
+ }
161
+
162
+ public bool HasVersion => Version != null ;
163
+
164
+ public bool HasArchitecture => Architecture != null ;
165
+
166
+ public bool HasQualifier => Qualifier != null ;
167
+
168
+ public override bool Equals ( object obj )
44
169
{
45
- return Version != null ;
170
+ return Equals ( obj as RID ) ;
46
171
}
47
172
48
- public bool HasArchitecture ( )
173
+ public bool Equals ( RID obj )
49
174
{
50
- return Architecture != null ;
175
+ return object . ReferenceEquals ( obj , this ) ||
176
+ ( ! ( obj is null ) &&
177
+ BaseRID == obj . BaseRID &&
178
+ ( Version == null || OmitVersionDelimiter == obj . OmitVersionDelimiter ) &&
179
+ Version == obj . Version &&
180
+ Architecture == obj . Architecture &&
181
+ Qualifier == obj . Qualifier ) ;
182
+
51
183
}
52
184
53
- public bool HasQualifier ( )
185
+ public override int GetHashCode ( )
54
186
{
55
- return Qualifier != null ;
187
+ #if NETFRAMEWORK
188
+ return BaseRID . GetHashCode ( ) ;
189
+ #else
190
+ HashCode hashCode = default ;
191
+ hashCode . Add ( BaseRID ) ;
192
+ hashCode . Add ( Version ) ;
193
+ hashCode . Add ( Architecture ) ;
194
+ hashCode . Add ( Qualifier ) ;
195
+ return hashCode . ToHashCode ( ) ;
196
+ #endif
56
197
}
57
198
}
58
-
59
199
}
0 commit comments