ranges.go 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. package utils
  2. import (
  3. "errors"
  4. "fmt"
  5. "strconv"
  6. "strings"
  7. "golang.org/x/exp/constraints"
  8. )
  9. type IntRanges[T constraints.Integer] []Range[T]
  10. var errIntRanges = errors.New("intRanges error")
  11. func newIntRanges[T constraints.Integer](expected string, parseFn func(string) (T, error)) (IntRanges[T], error) {
  12. // example: 200 or 200/302 or 200-400 or 200/204/401-429/501-503
  13. expected = strings.TrimSpace(expected)
  14. if len(expected) == 0 || expected == "*" {
  15. return nil, nil
  16. }
  17. // support: 200,302 or 200,204,401-429,501-503
  18. expected = strings.ReplaceAll(expected, ",", "/")
  19. list := strings.Split(expected, "/")
  20. if len(list) > 28 {
  21. return nil, fmt.Errorf("%w, too many ranges to use, maximum support 28 ranges", errIntRanges)
  22. }
  23. return newIntRangesFromList[T](list, parseFn)
  24. }
  25. func newIntRangesFromList[T constraints.Integer](list []string, parseFn func(string) (T, error)) (IntRanges[T], error) {
  26. var ranges IntRanges[T]
  27. for _, s := range list {
  28. if s == "" {
  29. continue
  30. }
  31. status := strings.Split(s, "-")
  32. statusLen := len(status)
  33. if statusLen > 2 {
  34. return nil, errIntRanges
  35. }
  36. start, err := parseFn(strings.Trim(status[0], "[ ]"))
  37. if err != nil {
  38. return nil, errIntRanges
  39. }
  40. switch statusLen {
  41. case 1: // Port range
  42. ranges = append(ranges, NewRange(T(start), T(start)))
  43. case 2: // Single port
  44. end, err := parseFn(strings.Trim(status[1], "[ ]"))
  45. if err != nil {
  46. return nil, errIntRanges
  47. }
  48. ranges = append(ranges, NewRange(T(start), T(end)))
  49. }
  50. }
  51. return ranges, nil
  52. }
  53. func parseUnsigned[T constraints.Unsigned](s string) (T, error) {
  54. if val, err := strconv.ParseUint(s, 10, 64); err == nil {
  55. return T(val), nil
  56. } else {
  57. return 0, err
  58. }
  59. }
  60. func NewUnsignedRanges[T constraints.Unsigned](expected string) (IntRanges[T], error) {
  61. return newIntRanges(expected, parseUnsigned[T])
  62. }
  63. func NewUnsignedRangesFromList[T constraints.Unsigned](list []string) (IntRanges[T], error) {
  64. return newIntRangesFromList(list, parseUnsigned[T])
  65. }
  66. func parseSigned[T constraints.Signed](s string) (T, error) {
  67. if val, err := strconv.ParseInt(s, 10, 64); err == nil {
  68. return T(val), nil
  69. } else {
  70. return 0, err
  71. }
  72. }
  73. func NewSignedRanges[T constraints.Signed](expected string) (IntRanges[T], error) {
  74. return newIntRanges(expected, parseSigned[T])
  75. }
  76. func NewSignedRangesFromList[T constraints.Signed](list []string) (IntRanges[T], error) {
  77. return newIntRangesFromList(list, parseSigned[T])
  78. }
  79. func (ranges IntRanges[T]) Check(status T) bool {
  80. if len(ranges) == 0 {
  81. return true
  82. }
  83. for _, segment := range ranges {
  84. if segment.Contains(status) {
  85. return true
  86. }
  87. }
  88. return false
  89. }
  90. func (ranges IntRanges[T]) String() string {
  91. if len(ranges) == 0 {
  92. return "*"
  93. }
  94. terms := make([]string, len(ranges))
  95. for i, r := range ranges {
  96. start := r.Start()
  97. end := r.End()
  98. var term string
  99. if start == end {
  100. term = strconv.Itoa(int(start))
  101. } else {
  102. term = strconv.Itoa(int(start)) + "-" + strconv.Itoa(int(end))
  103. }
  104. terms[i] = term
  105. }
  106. return strings.Join(terms, "/")
  107. }
  108. func (ranges IntRanges[T]) Range(f func(t T) bool) {
  109. if len(ranges) == 0 {
  110. return
  111. }
  112. for _, r := range ranges {
  113. for i := r.Start(); i <= r.End(); i++ {
  114. if !f(i) {
  115. return
  116. }
  117. }
  118. }
  119. }