uuid.lua 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  1. local bit = require "bit"
  2. local ffi = require "ffi"
  3. local log = require "resty.t1k.log"
  4. local _M = {
  5. _VERSION = '1.0.0'
  6. }
  7. local C = ffi.C
  8. local N_BYTES = 32
  9. local random = math.random
  10. local nlog = ngx.log
  11. local warn_fmt = log.warn_fmt
  12. ffi.cdef [[
  13. int RAND_bytes(unsigned char *buf, int num);
  14. ]]
  15. local function _rand_bytes(buf, len)
  16. return C.RAND_bytes(buf, len)
  17. end
  18. local function rand_bytes(len)
  19. local buf = ffi.new("char[?]", len)
  20. local ok, ret = pcall(_rand_bytes, buf, len)
  21. if not ok or ret ~= 1 then
  22. nlog(warn_fmt("call RAND_bytes failed: %s", ret))
  23. return nil
  24. end
  25. return ffi.string(buf, len)
  26. end
  27. do
  28. local band = bit.band
  29. local bor = bit.bor
  30. local tohex = bit.tohex
  31. local fmt = string.format
  32. local byte = string.byte
  33. function _M.generate_v4()
  34. local bytes = rand_bytes(N_BYTES)
  35. -- fallback to math.random based method
  36. if not bytes then
  37. return (fmt('%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s',
  38. tohex(random(0, 255), 2),
  39. tohex(random(0, 255), 2),
  40. tohex(random(0, 255), 2),
  41. tohex(random(0, 255), 2),
  42. tohex(random(0, 255), 2),
  43. tohex(random(0, 255), 2),
  44. tohex(bor(band(random(0, 255), 0x0F), 0x40), 2),
  45. tohex(random(0, 255), 2),
  46. tohex(bor(band(random(0, 255), 0x3F), 0x80), 2),
  47. tohex(random(0, 255), 2),
  48. tohex(random(0, 255), 2),
  49. tohex(random(0, 255), 2),
  50. tohex(random(0, 255), 2),
  51. tohex(random(0, 255), 2),
  52. tohex(random(0, 255), 2),
  53. tohex(random(0, 255), 2)))
  54. end
  55. return fmt('%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s',
  56. tohex(byte(bytes, 1, 2), 2),
  57. tohex(byte(bytes, 3, 4), 2),
  58. tohex(byte(bytes, 5, 6), 2),
  59. tohex(byte(bytes, 7, 8), 2),
  60. tohex(byte(bytes, 9, 10), 2),
  61. tohex(byte(bytes, 11, 12), 2),
  62. tohex(bor(band(byte(bytes, 13, 14), 0x0F), 0x40), 2),
  63. tohex(byte(bytes, 15, 16), 2),
  64. tohex(bor(band(byte(bytes, 17, 18), 0x3F), 0x80), 2),
  65. tohex(byte(bytes, 19, 20), 2),
  66. tohex(byte(bytes, 21, 22), 2),
  67. tohex(byte(bytes, 23, 24), 2),
  68. tohex(byte(bytes, 25, 26), 2),
  69. tohex(byte(bytes, 27, 28), 2),
  70. tohex(byte(bytes, 29, 30), 2),
  71. tohex(byte(bytes, 31, 32), 2))
  72. end
  73. end
  74. return setmetatable(_M, {
  75. __call = _M.generate_v4
  76. })