.gitignore added
[dotfiles/.git] / .config / coc / extensions / coc-go-data / tools / pkg / mod / golang.org / x / mod@v0.4.1 / semver / semver.go
1 // Copyright 2018 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
4
5 // Package semver implements comparison of semantic version strings.
6 // In this package, semantic version strings must begin with a leading "v",
7 // as in "v1.0.0".
8 //
9 // The general form of a semantic version string accepted by this package is
10 //
11 //      vMAJOR[.MINOR[.PATCH[-PRERELEASE][+BUILD]]]
12 //
13 // where square brackets indicate optional parts of the syntax;
14 // MAJOR, MINOR, and PATCH are decimal integers without extra leading zeros;
15 // PRERELEASE and BUILD are each a series of non-empty dot-separated identifiers
16 // using only alphanumeric characters and hyphens; and
17 // all-numeric PRERELEASE identifiers must not have leading zeros.
18 //
19 // This package follows Semantic Versioning 2.0.0 (see semver.org)
20 // with two exceptions. First, it requires the "v" prefix. Second, it recognizes
21 // vMAJOR and vMAJOR.MINOR (with no prerelease or build suffixes)
22 // as shorthands for vMAJOR.0.0 and vMAJOR.MINOR.0.
23 package semver
24
25 // parsed returns the parsed form of a semantic version string.
26 type parsed struct {
27         major      string
28         minor      string
29         patch      string
30         short      string
31         prerelease string
32         build      string
33         err        string
34 }
35
36 // IsValid reports whether v is a valid semantic version string.
37 func IsValid(v string) bool {
38         _, ok := parse(v)
39         return ok
40 }
41
42 // Canonical returns the canonical formatting of the semantic version v.
43 // It fills in any missing .MINOR or .PATCH and discards build metadata.
44 // Two semantic versions compare equal only if their canonical formattings
45 // are identical strings.
46 // The canonical invalid semantic version is the empty string.
47 func Canonical(v string) string {
48         p, ok := parse(v)
49         if !ok {
50                 return ""
51         }
52         if p.build != "" {
53                 return v[:len(v)-len(p.build)]
54         }
55         if p.short != "" {
56                 return v + p.short
57         }
58         return v
59 }
60
61 // Major returns the major version prefix of the semantic version v.
62 // For example, Major("v2.1.0") == "v2".
63 // If v is an invalid semantic version string, Major returns the empty string.
64 func Major(v string) string {
65         pv, ok := parse(v)
66         if !ok {
67                 return ""
68         }
69         return v[:1+len(pv.major)]
70 }
71
72 // MajorMinor returns the major.minor version prefix of the semantic version v.
73 // For example, MajorMinor("v2.1.0") == "v2.1".
74 // If v is an invalid semantic version string, MajorMinor returns the empty string.
75 func MajorMinor(v string) string {
76         pv, ok := parse(v)
77         if !ok {
78                 return ""
79         }
80         i := 1 + len(pv.major)
81         if j := i + 1 + len(pv.minor); j <= len(v) && v[i] == '.' && v[i+1:j] == pv.minor {
82                 return v[:j]
83         }
84         return v[:i] + "." + pv.minor
85 }
86
87 // Prerelease returns the prerelease suffix of the semantic version v.
88 // For example, Prerelease("v2.1.0-pre+meta") == "-pre".
89 // If v is an invalid semantic version string, Prerelease returns the empty string.
90 func Prerelease(v string) string {
91         pv, ok := parse(v)
92         if !ok {
93                 return ""
94         }
95         return pv.prerelease
96 }
97
98 // Build returns the build suffix of the semantic version v.
99 // For example, Build("v2.1.0+meta") == "+meta".
100 // If v is an invalid semantic version string, Build returns the empty string.
101 func Build(v string) string {
102         pv, ok := parse(v)
103         if !ok {
104                 return ""
105         }
106         return pv.build
107 }
108
109 // Compare returns an integer comparing two versions according to
110 // semantic version precedence.
111 // The result will be 0 if v == w, -1 if v < w, or +1 if v > w.
112 //
113 // An invalid semantic version string is considered less than a valid one.
114 // All invalid semantic version strings compare equal to each other.
115 func Compare(v, w string) int {
116         pv, ok1 := parse(v)
117         pw, ok2 := parse(w)
118         if !ok1 && !ok2 {
119                 return 0
120         }
121         if !ok1 {
122                 return -1
123         }
124         if !ok2 {
125                 return +1
126         }
127         if c := compareInt(pv.major, pw.major); c != 0 {
128                 return c
129         }
130         if c := compareInt(pv.minor, pw.minor); c != 0 {
131                 return c
132         }
133         if c := compareInt(pv.patch, pw.patch); c != 0 {
134                 return c
135         }
136         return comparePrerelease(pv.prerelease, pw.prerelease)
137 }
138
139 // Max canonicalizes its arguments and then returns the version string
140 // that compares greater.
141 //
142 // Deprecated: use Compare instead. In most cases, returning a canonicalized
143 // version is not expected or desired.
144 func Max(v, w string) string {
145         v = Canonical(v)
146         w = Canonical(w)
147         if Compare(v, w) > 0 {
148                 return v
149         }
150         return w
151 }
152
153 func parse(v string) (p parsed, ok bool) {
154         if v == "" || v[0] != 'v' {
155                 p.err = "missing v prefix"
156                 return
157         }
158         p.major, v, ok = parseInt(v[1:])
159         if !ok {
160                 p.err = "bad major version"
161                 return
162         }
163         if v == "" {
164                 p.minor = "0"
165                 p.patch = "0"
166                 p.short = ".0.0"
167                 return
168         }
169         if v[0] != '.' {
170                 p.err = "bad minor prefix"
171                 ok = false
172                 return
173         }
174         p.minor, v, ok = parseInt(v[1:])
175         if !ok {
176                 p.err = "bad minor version"
177                 return
178         }
179         if v == "" {
180                 p.patch = "0"
181                 p.short = ".0"
182                 return
183         }
184         if v[0] != '.' {
185                 p.err = "bad patch prefix"
186                 ok = false
187                 return
188         }
189         p.patch, v, ok = parseInt(v[1:])
190         if !ok {
191                 p.err = "bad patch version"
192                 return
193         }
194         if len(v) > 0 && v[0] == '-' {
195                 p.prerelease, v, ok = parsePrerelease(v)
196                 if !ok {
197                         p.err = "bad prerelease"
198                         return
199                 }
200         }
201         if len(v) > 0 && v[0] == '+' {
202                 p.build, v, ok = parseBuild(v)
203                 if !ok {
204                         p.err = "bad build"
205                         return
206                 }
207         }
208         if v != "" {
209                 p.err = "junk on end"
210                 ok = false
211                 return
212         }
213         ok = true
214         return
215 }
216
217 func parseInt(v string) (t, rest string, ok bool) {
218         if v == "" {
219                 return
220         }
221         if v[0] < '0' || '9' < v[0] {
222                 return
223         }
224         i := 1
225         for i < len(v) && '0' <= v[i] && v[i] <= '9' {
226                 i++
227         }
228         if v[0] == '0' && i != 1 {
229                 return
230         }
231         return v[:i], v[i:], true
232 }
233
234 func parsePrerelease(v string) (t, rest string, ok bool) {
235         // "A pre-release version MAY be denoted by appending a hyphen and
236         // a series of dot separated identifiers immediately following the patch version.
237         // Identifiers MUST comprise only ASCII alphanumerics and hyphen [0-9A-Za-z-].
238         // Identifiers MUST NOT be empty. Numeric identifiers MUST NOT include leading zeroes."
239         if v == "" || v[0] != '-' {
240                 return
241         }
242         i := 1
243         start := 1
244         for i < len(v) && v[i] != '+' {
245                 if !isIdentChar(v[i]) && v[i] != '.' {
246                         return
247                 }
248                 if v[i] == '.' {
249                         if start == i || isBadNum(v[start:i]) {
250                                 return
251                         }
252                         start = i + 1
253                 }
254                 i++
255         }
256         if start == i || isBadNum(v[start:i]) {
257                 return
258         }
259         return v[:i], v[i:], true
260 }
261
262 func parseBuild(v string) (t, rest string, ok bool) {
263         if v == "" || v[0] != '+' {
264                 return
265         }
266         i := 1
267         start := 1
268         for i < len(v) {
269                 if !isIdentChar(v[i]) && v[i] != '.' {
270                         return
271                 }
272                 if v[i] == '.' {
273                         if start == i {
274                                 return
275                         }
276                         start = i + 1
277                 }
278                 i++
279         }
280         if start == i {
281                 return
282         }
283         return v[:i], v[i:], true
284 }
285
286 func isIdentChar(c byte) bool {
287         return 'A' <= c && c <= 'Z' || 'a' <= c && c <= 'z' || '0' <= c && c <= '9' || c == '-'
288 }
289
290 func isBadNum(v string) bool {
291         i := 0
292         for i < len(v) && '0' <= v[i] && v[i] <= '9' {
293                 i++
294         }
295         return i == len(v) && i > 1 && v[0] == '0'
296 }
297
298 func isNum(v string) bool {
299         i := 0
300         for i < len(v) && '0' <= v[i] && v[i] <= '9' {
301                 i++
302         }
303         return i == len(v)
304 }
305
306 func compareInt(x, y string) int {
307         if x == y {
308                 return 0
309         }
310         if len(x) < len(y) {
311                 return -1
312         }
313         if len(x) > len(y) {
314                 return +1
315         }
316         if x < y {
317                 return -1
318         } else {
319                 return +1
320         }
321 }
322
323 func comparePrerelease(x, y string) int {
324         // "When major, minor, and patch are equal, a pre-release version has
325         // lower precedence than a normal version.
326         // Example: 1.0.0-alpha < 1.0.0.
327         // Precedence for two pre-release versions with the same major, minor,
328         // and patch version MUST be determined by comparing each dot separated
329         // identifier from left to right until a difference is found as follows:
330         // identifiers consisting of only digits are compared numerically and
331         // identifiers with letters or hyphens are compared lexically in ASCII
332         // sort order. Numeric identifiers always have lower precedence than
333         // non-numeric identifiers. A larger set of pre-release fields has a
334         // higher precedence than a smaller set, if all of the preceding
335         // identifiers are equal.
336         // Example: 1.0.0-alpha < 1.0.0-alpha.1 < 1.0.0-alpha.beta <
337         // 1.0.0-beta < 1.0.0-beta.2 < 1.0.0-beta.11 < 1.0.0-rc.1 < 1.0.0."
338         if x == y {
339                 return 0
340         }
341         if x == "" {
342                 return +1
343         }
344         if y == "" {
345                 return -1
346         }
347         for x != "" && y != "" {
348                 x = x[1:] // skip - or .
349                 y = y[1:] // skip - or .
350                 var dx, dy string
351                 dx, x = nextIdent(x)
352                 dy, y = nextIdent(y)
353                 if dx != dy {
354                         ix := isNum(dx)
355                         iy := isNum(dy)
356                         if ix != iy {
357                                 if ix {
358                                         return -1
359                                 } else {
360                                         return +1
361                                 }
362                         }
363                         if ix {
364                                 if len(dx) < len(dy) {
365                                         return -1
366                                 }
367                                 if len(dx) > len(dy) {
368                                         return +1
369                                 }
370                         }
371                         if dx < dy {
372                                 return -1
373                         } else {
374                                 return +1
375                         }
376                 }
377         }
378         if x == "" {
379                 return -1
380         } else {
381                 return +1
382         }
383 }
384
385 func nextIdent(x string) (dx, rest string) {
386         i := 0
387         for i < len(x) && x[i] != '.' {
388                 i++
389         }
390         return x[:i], x[i:]
391 }