uuid.go 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. package column
  2. import (
  3. "encoding/hex"
  4. "errors"
  5. "fmt"
  6. "reflect"
  7. "github.com/ClickHouse/clickhouse-go/lib/binary"
  8. )
  9. const (
  10. UUIDLen = 16
  11. NullUUID = "00000000-0000-0000-0000-000000000000"
  12. )
  13. var ErrInvalidUUIDFormat = errors.New("invalid UUID format")
  14. type UUID struct {
  15. base
  16. scanType reflect.Type
  17. }
  18. func (*UUID) Read(decoder *binary.Decoder, isNull bool) (interface{}, error) {
  19. src, err := decoder.Fixed(UUIDLen)
  20. if err != nil {
  21. return "", err
  22. }
  23. src = swap(src)
  24. var uuid [36]byte
  25. {
  26. hex.Encode(uuid[:], src[:4])
  27. uuid[8] = '-'
  28. hex.Encode(uuid[9:13], src[4:6])
  29. uuid[13] = '-'
  30. hex.Encode(uuid[14:18], src[6:8])
  31. uuid[18] = '-'
  32. hex.Encode(uuid[19:23], src[8:10])
  33. uuid[23] = '-'
  34. hex.Encode(uuid[24:], src[10:])
  35. }
  36. return string(uuid[:]), nil
  37. }
  38. func (u *UUID) Write(encoder *binary.Encoder, v interface{}) (err error) {
  39. var uuid []byte
  40. switch v := v.(type) {
  41. case string:
  42. if uuid, err = uuid2bytes(v); err != nil {
  43. return err
  44. }
  45. case []byte:
  46. if len(v) != UUIDLen {
  47. return fmt.Errorf("invalid raw UUID len '%s' (expected %d, got %d)", uuid, UUIDLen, len(uuid))
  48. }
  49. uuid = make([]byte, 16)
  50. copy(uuid, v)
  51. default:
  52. return &ErrUnexpectedType{
  53. T: v,
  54. Column: u,
  55. }
  56. }
  57. uuid = swap(uuid)
  58. if _, err := encoder.Write(uuid); err != nil {
  59. return err
  60. }
  61. return nil
  62. }
  63. func swap(src []byte) []byte {
  64. _ = src[15]
  65. src[0], src[7] = src[7], src[0]
  66. src[1], src[6] = src[6], src[1]
  67. src[2], src[5] = src[5], src[2]
  68. src[3], src[4] = src[4], src[3]
  69. src[8], src[15] = src[15], src[8]
  70. src[9], src[14] = src[14], src[9]
  71. src[10], src[13] = src[13], src[10]
  72. src[11], src[12] = src[12], src[11]
  73. return src
  74. }
  75. func uuid2bytes(str string) ([]byte, error) {
  76. var uuid [16]byte
  77. strLength := len(str)
  78. if strLength == 0 {
  79. str = NullUUID
  80. } else if strLength != 36 {
  81. return nil, ErrInvalidUUIDFormat
  82. }
  83. if str[8] != '-' || str[13] != '-' || str[18] != '-' || str[23] != '-' {
  84. return nil, ErrInvalidUUIDFormat
  85. }
  86. for i, x := range [16]int{
  87. 0, 2, 4, 6,
  88. 9, 11, 14, 16,
  89. 19, 21, 24, 26,
  90. 28, 30, 32, 34,
  91. } {
  92. if v, ok := xtob(str[x], str[x+1]); !ok {
  93. return nil, ErrInvalidUUIDFormat
  94. } else {
  95. uuid[i] = v
  96. }
  97. }
  98. return uuid[:], nil
  99. }
  100. // xvalues returns the value of a byte as a hexadecimal digit or 255.
  101. var xvalues = [256]byte{
  102. 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
  103. 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
  104. 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
  105. 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 255, 255, 255, 255, 255, 255,
  106. 255, 10, 11, 12, 13, 14, 15, 255, 255, 255, 255, 255, 255, 255, 255, 255,
  107. 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
  108. 255, 10, 11, 12, 13, 14, 15, 255, 255, 255, 255, 255, 255, 255, 255, 255,
  109. 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
  110. 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
  111. 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
  112. 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
  113. 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
  114. 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
  115. 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
  116. 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
  117. 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
  118. }
  119. // xtob converts hex characters x1 and x2 into a byte.
  120. func xtob(x1, x2 byte) (byte, bool) {
  121. b1 := xvalues[x1]
  122. b2 := xvalues[x2]
  123. return (b1 << 4) | b2, b1 != 255 && b2 != 255
  124. }