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.

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556
  1. // Copyright (c) 2022 Shivaram Lingamneni <slingamn@cs.stanford.edu>
  2. // released under the MIT license
  3. package utils
  4. import (
  5. "crypto/rand"
  6. "encoding/base64"
  7. "errors"
  8. )
  9. var (
  10. ErrInvalidUUID = errors.New("Invalid uuid")
  11. )
  12. // Technically a UUIDv4 has version bits set, but this doesn't matter in practice
  13. type UUID [16]byte
  14. func (u UUID) MarshalJSON() (b []byte, err error) {
  15. b = make([]byte, 24)
  16. b[0] = '"'
  17. base64.RawURLEncoding.Encode(b[1:], u[:])
  18. b[23] = '"'
  19. return
  20. }
  21. func (u *UUID) UnmarshalJSON(b []byte) (err error) {
  22. if len(b) != 24 {
  23. return ErrInvalidUUID
  24. }
  25. readLen, err := base64.RawURLEncoding.Decode(u[:], b[1:23])
  26. if err != nil || readLen != 16 {
  27. return ErrInvalidUUID
  28. }
  29. return nil
  30. }
  31. func (u *UUID) String() string {
  32. return base64.RawURLEncoding.EncodeToString(u[:])
  33. }
  34. func GenerateUUIDv4() (result UUID) {
  35. _, err := rand.Read(result[:])
  36. if err != nil {
  37. panic(err)
  38. }
  39. return
  40. }
  41. func DecodeUUID(ustr string) (result UUID, err error) {
  42. length, err := base64.RawURLEncoding.Decode(result[:], []byte(ustr))
  43. if err == nil && length != 16 {
  44. err = ErrInvalidUUID
  45. }
  46. return
  47. }