volume_ttl.go 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  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 &TTL{Count: byte(count), Unit: unit}, err
  43. }
  44. // read stored bytes to a ttl
  45. func LoadTTLFromBytes(input []byte) (t *TTL) {
  46. if input[0] == 0 && input[1] == 0 {
  47. return EMPTY_TTL
  48. }
  49. return &TTL{Count: input[0], Unit: input[1]}
  50. }
  51. // read stored bytes to a ttl
  52. func LoadTTLFromUint32(ttl uint32) (t *TTL) {
  53. input := make([]byte, 2)
  54. input[1] = byte(ttl)
  55. input[0] = byte(ttl >> 8)
  56. return LoadTTLFromBytes(input)
  57. }
  58. // save stored bytes to an output with 2 bytes
  59. func (t *TTL) ToBytes(output []byte) {
  60. output[0] = t.Count
  61. output[1] = t.Unit
  62. }
  63. func (t *TTL) ToUint32() (output uint32) {
  64. if t == nil || t.Count == 0 {
  65. return 0
  66. }
  67. output = uint32(t.Count) << 8
  68. output += uint32(t.Unit)
  69. return output
  70. }
  71. func (t *TTL) String() string {
  72. if t == nil || t.Count == 0 {
  73. return ""
  74. }
  75. if t.Unit == Empty {
  76. return ""
  77. }
  78. countString := strconv.Itoa(int(t.Count))
  79. switch t.Unit {
  80. case Minute:
  81. return countString + "m"
  82. case Hour:
  83. return countString + "h"
  84. case Day:
  85. return countString + "d"
  86. case Week:
  87. return countString + "w"
  88. case Month:
  89. return countString + "M"
  90. case Year:
  91. return countString + "y"
  92. }
  93. return ""
  94. }
  95. func toStoredByte(readableUnitByte byte) byte {
  96. switch readableUnitByte {
  97. case 'm':
  98. return Minute
  99. case 'h':
  100. return Hour
  101. case 'd':
  102. return Day
  103. case 'w':
  104. return Week
  105. case 'M':
  106. return Month
  107. case 'y':
  108. return Year
  109. }
  110. return 0
  111. }
  112. func (t TTL) Minutes() uint32 {
  113. switch t.Unit {
  114. case Empty:
  115. return 0
  116. case Minute:
  117. return uint32(t.Count)
  118. case Hour:
  119. return uint32(t.Count) * 60
  120. case Day:
  121. return uint32(t.Count) * 60 * 24
  122. case Week:
  123. return uint32(t.Count) * 60 * 24 * 7
  124. case Month:
  125. return uint32(t.Count) * 60 * 24 * 31
  126. case Year:
  127. return uint32(t.Count) * 60 * 24 * 365
  128. }
  129. return 0
  130. }
  131. func SecondsToTTL(seconds int32) string {
  132. if seconds == 0 {
  133. return ""
  134. }
  135. return fmt.Sprintf("%dm", seconds/60)
  136. }