neovim

Neovim text editor
git clone https://git.dasho.dev/neovim.git
Log | Files | Refs | README

testutil.lua (4453B)


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