helpers.lua 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. local helpers = require('test.unit.helpers')(nil)
  2. local eval_helpers = require('test.unit.eval.helpers')
  3. local cimport = helpers.cimport
  4. local to_cstr = helpers.to_cstr
  5. local ffi = helpers.ffi
  6. local list_type = eval_helpers.list_type
  7. local dict_type = eval_helpers.dict_type
  8. local func_type = eval_helpers.func_type
  9. local nil_value = eval_helpers.nil_value
  10. local int_type = eval_helpers.int_type
  11. local flt_type = eval_helpers.flt_type
  12. local type_key = eval_helpers.type_key
  13. local api = cimport('./src/nvim/api/private/defs.h',
  14. './src/nvim/api/private/helpers.h',
  15. './src/nvim/memory.h')
  16. local obj2lua
  17. local obj2lua_tab = nil
  18. local function init_obj2lua_tab()
  19. if obj2lua_tab then
  20. return
  21. end
  22. obj2lua_tab = {
  23. [tonumber(api.kObjectTypeArray)] = function(obj)
  24. local ret = {[type_key]=list_type}
  25. for i = 1,tonumber(obj.data.array.size) do
  26. ret[i] = obj2lua(obj.data.array.items[i - 1])
  27. end
  28. if ret[1] then
  29. ret[type_key] = nil
  30. end
  31. return ret
  32. end,
  33. [tonumber(api.kObjectTypeDictionary)] = function(obj)
  34. local ret = {}
  35. for i = 1,tonumber(obj.data.dictionary.size) do
  36. local kv_pair = obj.data.dictionary.items[i - 1]
  37. ret[ffi.string(kv_pair.key.data, kv_pair.key.size)] = obj2lua(kv_pair.value)
  38. end
  39. return ret
  40. end,
  41. [tonumber(api.kObjectTypeBoolean)] = function(obj)
  42. if obj.data.boolean == false then
  43. return false
  44. else
  45. return true
  46. end
  47. end,
  48. [tonumber(api.kObjectTypeNil)] = function(_)
  49. return nil_value
  50. end,
  51. [tonumber(api.kObjectTypeFloat)] = function(obj)
  52. return tonumber(obj.data.floating)
  53. end,
  54. [tonumber(api.kObjectTypeInteger)] = function(obj)
  55. return {[type_key]=int_type, value=tonumber(obj.data.integer)}
  56. end,
  57. [tonumber(api.kObjectTypeString)] = function(obj)
  58. return ffi.string(obj.data.string.data, obj.data.string.size)
  59. end,
  60. }
  61. end
  62. obj2lua = function(obj)
  63. init_obj2lua_tab()
  64. return ((obj2lua_tab[tonumber(obj['type'])] or function(obj_inner)
  65. assert(false, 'Converting ' .. tostring(tonumber(obj_inner['type'])) .. ' is not implementing yet')
  66. end)(obj))
  67. end
  68. local obj = function(typ, data)
  69. return ffi.gc(ffi.new('Object', {['type']=typ, data=data}),
  70. api.api_free_object)
  71. end
  72. local lua2obj
  73. local lua2obj_type_tab = {
  74. [int_type] = function(l)
  75. return obj(api.kObjectTypeInteger, {integer=l.value})
  76. end,
  77. [flt_type] = function(l)
  78. return obj(api.kObjectTypeFloat, {floating=l})
  79. end,
  80. [list_type] = function(l)
  81. local len = #l
  82. local arr = obj(api.kObjectTypeArray, {array={
  83. size=len,
  84. capacity=len,
  85. items=ffi.cast('Object *', api.xmalloc(len * ffi.sizeof('Object'))),
  86. }})
  87. for i = 1, len do
  88. arr.data.array.items[i - 1] = ffi.gc(lua2obj(l[i]), nil)
  89. end
  90. return arr
  91. end,
  92. [dict_type] = function(l)
  93. local kvs = {}
  94. for k, v in pairs(l) do
  95. if type(k) == 'string' then
  96. kvs[#kvs + 1] = {k, v}
  97. end
  98. end
  99. local len = #kvs
  100. local dct = obj(api.kObjectTypeDictionary, {dictionary={
  101. size=len,
  102. capacity=len,
  103. items=ffi.cast('KeyValuePair *',
  104. api.xmalloc(len * ffi.sizeof('KeyValuePair'))),
  105. }})
  106. for i = 1, len do
  107. local key, val = unpack(kvs[i])
  108. dct.data.dictionary.items[i - 1] = ffi.new(
  109. 'KeyValuePair', {key=ffi.gc(lua2obj(key), nil).data.string,
  110. value=ffi.gc(lua2obj(val), nil)})
  111. end
  112. return dct
  113. end,
  114. }
  115. lua2obj = function(l)
  116. if type(l) == 'table' then
  117. if l[type_key] then
  118. return lua2obj_type_tab[l[type_key]](l)
  119. else
  120. if l[1] then
  121. return lua2obj_type_tab[list_type](l)
  122. else
  123. return lua2obj_type_tab[dict_type](l)
  124. end
  125. end
  126. elseif type(l) == 'number' then
  127. return lua2obj_type_tab[flt_type](l)
  128. elseif type(l) == 'boolean' then
  129. return obj(api.kObjectTypeBoolean, {boolean=l})
  130. elseif type(l) == 'string' then
  131. return obj(api.kObjectTypeString, {string={
  132. size=#l,
  133. data=api.xmemdupz(to_cstr(l), #l),
  134. }})
  135. elseif l == nil or l == nil_value then
  136. return obj(api.kObjectTypeNil, {integer=0})
  137. end
  138. end
  139. return {
  140. list_type=list_type,
  141. dict_type=dict_type,
  142. func_type=func_type,
  143. int_type=int_type,
  144. flt_type=flt_type,
  145. nil_value=nil_value,
  146. type_key=type_key,
  147. obj2lua=obj2lua,
  148. lua2obj=lua2obj,
  149. }