volume_ttl.go 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247
  1. package needle
  2. import (
  3. "fmt"
  4. "strconv"
  5. )
  6. const (
  7. // stored unit types
  8. Empty byte = iota
  9. Minute
  10. Hour
  11. Day
  12. Week
  13. Month
  14. Year
  15. )
  16. type TTL struct {
  17. Count byte
  18. Unit byte
  19. }
  20. var EMPTY_TTL = &TTL{}
  21. // translate a readable ttl to internal ttl
  22. // Supports format example:
  23. // 3m: 3 minutes
  24. // 4h: 4 hours
  25. // 5d: 5 days
  26. // 6w: 6 weeks
  27. // 7M: 7 months
  28. // 8y: 8 years
  29. func ReadTTL(ttlString string) (*TTL, error) {
  30. if ttlString == "" {
  31. return EMPTY_TTL, nil
  32. }
  33. ttlBytes := []byte(ttlString)
  34. unitByte := ttlBytes[len(ttlBytes)-1]
  35. countBytes := ttlBytes[0 : len(ttlBytes)-1]
  36. if '0' <= unitByte && unitByte <= '9' {
  37. countBytes = ttlBytes
  38. unitByte = 'm'
  39. }
  40. count, err := strconv.Atoi(string(countBytes))
  41. unit := toStoredByte(unitByte)
  42. return fitTtlCount(count, unit), err
  43. }
  44. func fitTtlCount(count int, unit byte) *TTL {
  45. seconds := ToSeconds(count, unit)
  46. if seconds == 0 {
  47. return EMPTY_TTL
  48. }
  49. if seconds%(3600*24*365) == 0 && seconds/(3600*24*365) < 256 {
  50. return &TTL{Count: byte(seconds / (3600 * 24 * 365)), Unit: Year}
  51. }
  52. if seconds%(3600*24*30) == 0 && seconds/(3600*24*30) < 256 {
  53. return &TTL{Count: byte(seconds / (3600 * 24 * 30)), Unit: Month}
  54. }
  55. if seconds%(3600*24*7) == 0 && seconds/(3600*24*7) < 256 {
  56. return &TTL{Count: byte(seconds / (3600 * 24 * 7)), Unit: Week}
  57. }
  58. if seconds%(3600*24) == 0 && seconds/(3600*24) < 256 {
  59. return &TTL{Count: byte(seconds / (3600 * 24)), Unit: Day}
  60. }
  61. if seconds%(3600) == 0 && seconds/(3600) < 256 {
  62. return &TTL{Count: byte(seconds / (3600)), Unit: Hour}
  63. }
  64. if seconds/60 < 256 {
  65. return &TTL{Count: byte(seconds / 60), Unit: Minute}
  66. }
  67. if seconds/(3600) < 256 {
  68. return &TTL{Count: byte(seconds / (3600)), Unit: Hour}
  69. }
  70. if seconds/(3600*24) < 256 {
  71. return &TTL{Count: byte(seconds / (3600 * 24)), Unit: Day}
  72. }
  73. if seconds/(3600*24*7) < 256 {
  74. return &TTL{Count: byte(seconds / (3600 * 24 * 7)), Unit: Week}
  75. }
  76. if seconds/(3600*24*30) < 256 {
  77. return &TTL{Count: byte(seconds / (3600 * 24 * 30)), Unit: Month}
  78. }
  79. if seconds/(3600*24*365) < 256 {
  80. return &TTL{Count: byte(seconds / (3600 * 24 * 365)), Unit: Year}
  81. }
  82. return EMPTY_TTL
  83. }
  84. // read stored bytes to a ttl
  85. func LoadTTLFromBytes(input []byte) (t *TTL) {
  86. if input[0] == 0 && input[1] == 0 {
  87. return EMPTY_TTL
  88. }
  89. return &TTL{Count: input[0], Unit: input[1]}
  90. }
  91. // read stored bytes to a ttl
  92. func LoadTTLFromUint32(ttl uint32) (t *TTL) {
  93. input := make([]byte, 2)
  94. input[1] = byte(ttl)
  95. input[0] = byte(ttl >> 8)
  96. return LoadTTLFromBytes(input)
  97. }
  98. // save stored bytes to an output with 2 bytes
  99. func (t *TTL) ToBytes(output []byte) {
  100. output[0] = t.Count
  101. output[1] = t.Unit
  102. }
  103. func (t *TTL) ToUint32() (output uint32) {
  104. if t == nil || t.Count == 0 {
  105. return 0
  106. }
  107. output = uint32(t.Count) << 8
  108. output += uint32(t.Unit)
  109. return output
  110. }
  111. func (t *TTL) String() string {
  112. if t == nil || t.Count == 0 {
  113. return ""
  114. }
  115. if t.Unit == Empty {
  116. return ""
  117. }
  118. countString := strconv.Itoa(int(t.Count))
  119. switch t.Unit {
  120. case Minute:
  121. return countString + "m"
  122. case Hour:
  123. return countString + "h"
  124. case Day:
  125. return countString + "d"
  126. case Week:
  127. return countString + "w"
  128. case Month:
  129. return countString + "M"
  130. case Year:
  131. return countString + "y"
  132. }
  133. return ""
  134. }
  135. func (t *TTL) ToSeconds() uint64 {
  136. return ToSeconds(int(t.Count), t.Unit)
  137. }
  138. func ToSeconds(count int, unit byte) uint64 {
  139. switch unit {
  140. case Empty:
  141. return 0
  142. case Minute:
  143. return uint64(count) * 60
  144. case Hour:
  145. return uint64(count) * 60 * 60
  146. case Day:
  147. return uint64(count) * 60 * 24 * 60
  148. case Week:
  149. return uint64(count) * 60 * 24 * 7 * 60
  150. case Month:
  151. return uint64(count) * 60 * 24 * 30 * 60
  152. case Year:
  153. return uint64(count) * 60 * 24 * 365 * 60
  154. }
  155. return 0
  156. }
  157. func toStoredByte(readableUnitByte byte) byte {
  158. switch readableUnitByte {
  159. case 'm':
  160. return Minute
  161. case 'h':
  162. return Hour
  163. case 'd':
  164. return Day
  165. case 'w':
  166. return Week
  167. case 'M':
  168. return Month
  169. case 'y':
  170. return Year
  171. }
  172. return 0
  173. }
  174. func (t TTL) Minutes() uint32 {
  175. switch t.Unit {
  176. case Empty:
  177. return 0
  178. case Minute:
  179. return uint32(t.Count)
  180. case Hour:
  181. return uint32(t.Count) * 60
  182. case Day:
  183. return uint32(t.Count) * 60 * 24
  184. case Week:
  185. return uint32(t.Count) * 60 * 24 * 7
  186. case Month:
  187. return uint32(t.Count) * 60 * 24 * 30
  188. case Year:
  189. return uint32(t.Count) * 60 * 24 * 365
  190. }
  191. return 0
  192. }
  193. func SecondsToTTL(seconds int32) string {
  194. if seconds == 0 {
  195. return ""
  196. }
  197. if seconds%(3600*24*365) == 0 && seconds/(3600*24*365) < 256 {
  198. return fmt.Sprintf("%dy", seconds/(3600*24*365))
  199. }
  200. if seconds%(3600*24*30) == 0 && seconds/(3600*24*30) < 256 {
  201. return fmt.Sprintf("%dM", seconds/(3600*24*30))
  202. }
  203. if seconds%(3600*24*7) == 0 && seconds/(3600*24*7) < 256 {
  204. return fmt.Sprintf("%dw", seconds/(3600*24*7))
  205. }
  206. if seconds%(3600*24) == 0 && seconds/(3600*24) < 256 {
  207. return fmt.Sprintf("%dd", seconds/(3600*24))
  208. }
  209. if seconds%(3600) == 0 && seconds/(3600) < 256 {
  210. return fmt.Sprintf("%dh", seconds/(3600))
  211. }
  212. if seconds/60 < 256 {
  213. return fmt.Sprintf("%dm", seconds/60)
  214. }
  215. if seconds/(3600) < 256 {
  216. return fmt.Sprintf("%dh", seconds/(3600))
  217. }
  218. if seconds/(3600*24) < 256 {
  219. return fmt.Sprintf("%dd", seconds/(3600*24))
  220. }
  221. if seconds/(3600*24*7) < 256 {
  222. return fmt.Sprintf("%dw", seconds/(3600*24*7))
  223. }
  224. if seconds/(3600*24*30) < 256 {
  225. return fmt.Sprintf("%dM", seconds/(3600*24*30))
  226. }
  227. if seconds/(3600*24*365) < 256 {
  228. return fmt.Sprintf("%dy", seconds/(3600*24*365))
  229. }
  230. return ""
  231. }