Stable APIs for Go. https://go.code.as
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

118 lines
2.1 KiB

  1. package main
  2. import (
  3. "fmt"
  4. )
  5. type Version struct {
  6. Major, Minor, Patch int
  7. }
  8. func (v Version) String() string {
  9. if v.Major < 0 {
  10. panic(fmt.Sprintf("cannot stringify invalid version (major is %d)", v.Major))
  11. }
  12. if v.Minor < 0 {
  13. return fmt.Sprintf("v%d", v.Major)
  14. }
  15. if v.Patch < 0 {
  16. return fmt.Sprintf("v%d.%d", v.Major, v.Minor)
  17. }
  18. return fmt.Sprintf("v%d.%d.%d", v.Major, v.Minor, v.Patch)
  19. }
  20. func (v Version) Less(other Version) bool {
  21. if v.Major != other.Major {
  22. return v.Major < other.Major
  23. }
  24. if v.Minor != other.Minor {
  25. return v.Minor < other.Minor
  26. }
  27. return v.Patch < other.Patch
  28. }
  29. func (v Version) Contains(other Version) bool {
  30. if v.Patch != -1 {
  31. return v == other
  32. }
  33. if v.Minor != -1 {
  34. return v.Major == other.Major && v.Minor == other.Minor
  35. }
  36. return v.Major == other.Major
  37. }
  38. func (v Version) IsValid() bool {
  39. return v == InvalidVersion
  40. }
  41. var InvalidVersion = Version{-1, -1, -1}
  42. func parseVersion(s string) (Version, bool) {
  43. if len(s) < 2 {
  44. return InvalidVersion, false
  45. }
  46. if s[0] != 'v' {
  47. return InvalidVersion, false
  48. }
  49. v := Version{-1, -1, -1}
  50. i := 1
  51. v.Major, i = parseVersionPart(s, i)
  52. if i < 0 {
  53. return InvalidVersion, false
  54. }
  55. if i == len(s) {
  56. return v, true
  57. }
  58. v.Minor, i = parseVersionPart(s, i)
  59. if i < 0 {
  60. return InvalidVersion, false
  61. }
  62. if i == len(s) {
  63. return v, true
  64. }
  65. v.Patch, i = parseVersionPart(s, i)
  66. if i < 0 || i < len(s) {
  67. return InvalidVersion, false
  68. }
  69. return v, true
  70. }
  71. func parseVersionPart(s string, i int) (part int, newi int) {
  72. dot := i
  73. for dot < len(s) && s[dot] != '.' {
  74. dot++
  75. }
  76. if dot == i || dot-i > 1 && s[i] == '0' {
  77. return -1, -1
  78. }
  79. for i < len(s) {
  80. if s[i] < '0' || s[i] > '9' {
  81. return -1, -1
  82. }
  83. part *= 10
  84. part += int(s[i] - '0')
  85. if part < 0 {
  86. return -1, -1
  87. }
  88. i++
  89. if i+1 < len(s) && s[i] == '.' {
  90. return part, i + 1
  91. }
  92. }
  93. return part, i
  94. }
  95. // VersionList implements sort.Interface
  96. type VersionList []Version
  97. func (vl VersionList) Len() int {
  98. return len(vl)
  99. }
  100. func (vl VersionList) Less(i, j int) bool {
  101. return vl[i].Less(vl[j])
  102. }
  103. func (vl VersionList) Swap(i, j int) {
  104. vl[i], vl[j] = vl[j], vl[i]
  105. }