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.

util.go 4.0KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  1. // Copyright 2017 The Gitea Authors. All rights reserved.
  2. // Use of this source code is governed by a MIT-style
  3. // license that can be found in the LICENSE file.
  4. package util
  5. import (
  6. "bytes"
  7. "crypto/rand"
  8. "errors"
  9. "math/big"
  10. "strconv"
  11. "strings"
  12. )
  13. // OptionalBool a boolean that can be "null"
  14. type OptionalBool byte
  15. const (
  16. // OptionalBoolNone a "null" boolean value
  17. OptionalBoolNone OptionalBool = iota
  18. // OptionalBoolTrue a "true" boolean value
  19. OptionalBoolTrue
  20. // OptionalBoolFalse a "false" boolean value
  21. OptionalBoolFalse
  22. )
  23. // IsTrue return true if equal to OptionalBoolTrue
  24. func (o OptionalBool) IsTrue() bool {
  25. return o == OptionalBoolTrue
  26. }
  27. // IsFalse return true if equal to OptionalBoolFalse
  28. func (o OptionalBool) IsFalse() bool {
  29. return o == OptionalBoolFalse
  30. }
  31. // IsNone return true if equal to OptionalBoolNone
  32. func (o OptionalBool) IsNone() bool {
  33. return o == OptionalBoolNone
  34. }
  35. // OptionalBoolOf get the corresponding OptionalBool of a bool
  36. func OptionalBoolOf(b bool) OptionalBool {
  37. if b {
  38. return OptionalBoolTrue
  39. }
  40. return OptionalBoolFalse
  41. }
  42. // OptionalBoolParse get the corresponding OptionalBool of a string using strconv.ParseBool
  43. func OptionalBoolParse(s string) OptionalBool {
  44. b, e := strconv.ParseBool(s)
  45. if e != nil {
  46. return OptionalBoolNone
  47. }
  48. return OptionalBoolOf(b)
  49. }
  50. // Max max of two ints
  51. func Max(a, b int) int {
  52. if a < b {
  53. return b
  54. }
  55. return a
  56. }
  57. // Min min of two ints
  58. func Min(a, b int) int {
  59. if a > b {
  60. return b
  61. }
  62. return a
  63. }
  64. // IsEmptyString checks if the provided string is empty
  65. func IsEmptyString(s string) bool {
  66. return len(strings.TrimSpace(s)) == 0
  67. }
  68. // NormalizeEOL will convert Windows (CRLF) and Mac (CR) EOLs to UNIX (LF)
  69. func NormalizeEOL(input []byte) []byte {
  70. var right, left, pos int
  71. if right = bytes.IndexByte(input, '\r'); right == -1 {
  72. return input
  73. }
  74. length := len(input)
  75. tmp := make([]byte, length)
  76. // We know that left < length because otherwise right would be -1 from IndexByte.
  77. copy(tmp[pos:pos+right], input[left:left+right])
  78. pos += right
  79. tmp[pos] = '\n'
  80. left += right + 1
  81. pos++
  82. for left < length {
  83. if input[left] == '\n' {
  84. left++
  85. }
  86. right = bytes.IndexByte(input[left:], '\r')
  87. if right == -1 {
  88. copy(tmp[pos:], input[left:])
  89. pos += length - left
  90. break
  91. }
  92. copy(tmp[pos:pos+right], input[left:left+right])
  93. pos += right
  94. tmp[pos] = '\n'
  95. left += right + 1
  96. pos++
  97. }
  98. return tmp[:pos]
  99. }
  100. // MergeInto merges pairs of values into a "dict"
  101. func MergeInto(dict map[string]interface{}, values ...interface{}) (map[string]interface{}, error) {
  102. for i := 0; i < len(values); i++ {
  103. switch key := values[i].(type) {
  104. case string:
  105. i++
  106. if i == len(values) {
  107. return nil, errors.New("specify the key for non array values")
  108. }
  109. dict[key] = values[i]
  110. case map[string]interface{}:
  111. m := values[i].(map[string]interface{})
  112. for i, v := range m {
  113. dict[i] = v
  114. }
  115. default:
  116. return nil, errors.New("dict values must be maps")
  117. }
  118. }
  119. return dict, nil
  120. }
  121. // CryptoRandomInt returns a crypto random integer between 0 and limit, inclusive
  122. func CryptoRandomInt(limit int64) (int64, error) {
  123. rInt, err := rand.Int(rand.Reader, big.NewInt(limit))
  124. if err != nil {
  125. return 0, err
  126. }
  127. return rInt.Int64(), nil
  128. }
  129. const alphanumericalChars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
  130. // CryptoRandomString generates a crypto random alphanumerical string, each byte is generated by [0,61] range
  131. func CryptoRandomString(length int64) (string, error) {
  132. buf := make([]byte, length)
  133. limit := int64(len(alphanumericalChars))
  134. for i := range buf {
  135. num, err := CryptoRandomInt(limit)
  136. if err != nil {
  137. return "", err
  138. }
  139. buf[i] = alphanumericalChars[num]
  140. }
  141. return string(buf), nil
  142. }
  143. // CryptoRandomBytes generates `length` crypto bytes
  144. // This differs from CryptoRandomString, as each byte in CryptoRandomString is generated by [0,61] range
  145. // This function generates totally random bytes, each byte is generated by [0,255] range
  146. func CryptoRandomBytes(length int64) ([]byte, error) {
  147. buf := make([]byte, length)
  148. _, err := rand.Read(buf)
  149. return buf, err
  150. }