refactor(typval)!: remove distinction of binary and nonbinary strings

This is a breaking change which will make refactor of typval and shada
code a lot easier. In particular, code that would use or check for
v:msgpack_types.binary in the wild would be broken. This appears to be
rarely used in existing plugins.

Also some cases where v:msgpack_type.string would be used to represent a
binary string of "string" type, we use a BLOB instead, which is
vimscripts native type for binary blobs, and already was used for BIN
formats when necessary.

msgpackdump(msgpackparse(data)) no longer preserves the distinction
of BIN and STR strings. This is very common behavior for
language-specific msgpack bindings. Nvim uses msgpack as a tool to
serialize its data. Nvim is not a tool to bit-perfectly manipulate
arbitrary msgpack data out in the wild.

The changed tests should indicate how behavior changes in various edge
cases.
This commit is contained in:
bfredl 2024-06-25 15:33:47 +02:00
parent 9e436251de
commit bda63d5b97
19 changed files with 137 additions and 269 deletions

View File

@ -361,7 +361,7 @@ endfunction
let s:MSGPACK_STANDARD_TYPES = { let s:MSGPACK_STANDARD_TYPES = {
\type(0): 'integer', \type(0): 'integer',
\type(0.0): 'float', \type(0.0): 'float',
\type(''): 'binary', \type(''): 'string',
\type([]): 'array', \type([]): 'array',
\type({}): 'map', \type({}): 'map',
\type(v:true): 'boolean', \type(v:true): 'boolean',
@ -412,9 +412,15 @@ endfunction
"" ""
" Dump |msgpack-special-dict| that represents a string. If any additional " Dump |msgpack-special-dict| that represents a string. If any additional
" parameter is given then it dumps binary string. " parameter is given then it dumps binary string.
function s:msgpack_dump_string(v, ...) abort function s:msgpack_dump_string(v) abort
let ret = [a:0 ? '"' : '="'] if type(a:v) == type({})
for v in a:v._VAL let val = a:v
else
let val = {'_VAL': split(a:v, "\n", 1)}
end
let ret = ['"']
for v in val._VAL
call add( call add(
\ret, \ret,
\substitute( \substitute(
@ -426,16 +432,6 @@ function s:msgpack_dump_string(v, ...) abort
return join(ret, '') return join(ret, '')
endfunction endfunction
""
" Dump binary string.
function s:msgpack_dump_binary(v) abort
if type(a:v) == type({})
return s:msgpack_dump_string(a:v, 1)
else
return s:msgpack_dump_string({'_VAL': split(a:v, "\n", 1)}, 1)
endif
endfunction
"" ""
" Dump array value. " Dump array value.
function s:msgpack_dump_array(v) abort function s:msgpack_dump_array(v) abort
@ -449,7 +445,7 @@ function s:msgpack_dump_map(v) abort
let ret = ['{'] let ret = ['{']
if msgpack#special_type(a:v) is 0 if msgpack#special_type(a:v) is 0
for [k, v] in items(a:v) for [k, v] in items(a:v)
let ret += [s:msgpack_dump_string({'_VAL': split(k, "\n", 1)}), let ret += [s:msgpack_dump_string({'_VAL': split(k, "\n")}),
\': ', \': ',
\msgpack#string(v), \msgpack#string(v),
\', '] \', ']
@ -479,7 +475,7 @@ endfunction
" Dump extension value. " Dump extension value.
function s:msgpack_dump_ext(v) abort function s:msgpack_dump_ext(v) abort
return printf('+(%i)%s', a:v._VAL[0], return printf('+(%i)%s', a:v._VAL[0],
\s:msgpack_dump_string({'_VAL': a:v._VAL[1]}, 1)) \s:msgpack_dump_string({'_VAL': a:v._VAL[1]}))
endfunction endfunction
"" ""
@ -619,9 +615,7 @@ function msgpack#eval(s, special_objs) abort
throw '"-invalid:Invalid string: ' . s throw '"-invalid:Invalid string: ' . s
endif endif
call add(expr, '{''_TYPE'': v:msgpack_types.') call add(expr, '{''_TYPE'': v:msgpack_types.')
if empty(match[1]) if empty(match[1]) || match[1] is# '='
call add(expr, 'binary')
elseif match[1] is# '='
call add(expr, 'string') call add(expr, 'string')
else else
call add(expr, 'ext') call add(expr, 'ext')
@ -772,7 +766,7 @@ function msgpack#equal(a, b)
let a = aspecial is 0 ? a:a : a:a._VAL let a = aspecial is 0 ? a:a : a:a._VAL
let b = bspecial is 0 ? a:b : a:b._VAL let b = bspecial is 0 ? a:b : a:b._VAL
return msgpack#equal(a, b) return msgpack#equal(a, b)
elseif atype is# 'binary' elseif atype is# 'string'
let a = (aspecial is 0 ? split(a:a, "\n", 1) : a:a._VAL) let a = (aspecial is 0 ? split(a:a, "\n", 1) : a:a._VAL)
let b = (bspecial is 0 ? split(a:b, "\n", 1) : a:b._VAL) let b = (bspecial is 0 ? split(a:b, "\n", 1) : a:b._VAL)
return a ==# b return a ==# b
@ -787,13 +781,17 @@ function msgpack#equal(a, b)
" Non-special mapping cannot have non-string keys " Non-special mapping cannot have non-string keys
return 0 return 0
endif endif
if (empty(k._VAL) if type(k) == type({})
\|| k._VAL ==# [""] if (empty(k._VAL)
\|| !empty(filter(copy(k._VAL), 'stridx(v:val, "\n") != -1'))) \|| k._VAL ==# [""]
" Non-special mapping cannot have zero byte in key or an empty key \|| !empty(filter(copy(k._VAL), 'stridx(v:val, "\n") != -1')))
return 0 " Non-special mapping cannot have zero byte in key or an empty key
return 0
endif
let kstr = join(k._VAL, "\n")
else
let kstr = k
endif endif
let kstr = join(k._VAL, "\n")
if !has_key(akeys, kstr) if !has_key(akeys, kstr)
" Protects from both missing and duplicate keys " Protects from both missing and duplicate keys
return 0 return 0

View File

@ -230,7 +230,7 @@ function s:shada_check_type(type, val) abort
return 0 return 0
elseif a:type is# 'bin' elseif a:type is# 'bin'
" Binary string without zero bytes " Binary string without zero bytes
if type isnot# 'binary' if type isnot# 'string'
return 'Expected binary string' return 'Expected binary string'
elseif (type(a:val) == type({}) elseif (type(a:val) == type({})
\&& !empty(filter(copy(a:val._VAL), 'stridx(v:val, "\n") != -1'))) \&& !empty(filter(copy(a:val._VAL), 'stridx(v:val, "\n") != -1')))
@ -247,7 +247,7 @@ function s:shada_check_type(type, val) abort
if type isnot# 'array' if type isnot# 'array'
return 'Expected array value' return 'Expected array value'
elseif !empty(filter(copy(type(a:val) == type({}) ? a:val._VAL : a:val), elseif !empty(filter(copy(type(a:val) == type({}) ? a:val._VAL : a:val),
\'msgpack#type(v:val) isnot# "binary"')) \'msgpack#type(v:val) isnot# "string"'))
return 'Expected array of binary strings' return 'Expected array of binary strings'
else else
for element in (type(a:val) == type({}) ? a:val._VAL : a:val) for element in (type(a:val) == type({}) ? a:val._VAL : a:val)

View File

@ -5152,12 +5152,7 @@ msgpackparse({data}) *msgpackparse()*
C parser does not support such values. C parser does not support such values.
float |Float|. This value cannot possibly appear in float |Float|. This value cannot possibly appear in
|msgpackparse()| output. |msgpackparse()| output.
string |readfile()|-style list of strings. This value will string |String|, or |Blob| if binary string contains zero
appear in |msgpackparse()| output if string contains
zero byte or if string is a mapping key and mapping is
being represented as special dictionary for other
reasons.
binary |String|, or |Blob| if binary string contains zero
byte. This value cannot appear in |msgpackparse()| byte. This value cannot appear in |msgpackparse()|
output since blobs were introduced. output since blobs were introduced.
array |List|. This value cannot appear in |msgpackparse()| array |List|. This value cannot appear in |msgpackparse()|

View File

@ -50,6 +50,12 @@ EDITOR
• |hl-CurSearch| now behaves the same as Vim and no longer updates on every • |hl-CurSearch| now behaves the same as Vim and no longer updates on every
cursor movement. cursor movement.
VIM SCRIPT
• |v:msgpack_types| has the type "binary" removed. |msgpackparse()| no longer
treats BIN, STR and FIXSTR as separate types. Any of these is returned as a
string if possible, or a |blob| if the value contained embedded NUL:s.
EVENTS EVENTS
• TODO • TODO

View File

@ -6177,12 +6177,7 @@ function vim.fn.msgpackdump(list, type) end
--- C parser does not support such values. --- C parser does not support such values.
--- float |Float|. This value cannot possibly appear in --- float |Float|. This value cannot possibly appear in
--- |msgpackparse()| output. --- |msgpackparse()| output.
--- string |readfile()|-style list of strings. This value will --- string |String|, or |Blob| if binary string contains zero
--- appear in |msgpackparse()| output if string contains
--- zero byte or if string is a mapping key and mapping is
--- being represented as special dictionary for other
--- reasons.
--- binary |String|, or |Blob| if binary string contains zero
--- byte. This value cannot appear in |msgpackparse()| --- byte. This value cannot appear in |msgpackparse()|
--- output since blobs were introduced. --- output since blobs were introduced.
--- array |List|. This value cannot appear in |msgpackparse()| --- array |List|. This value cannot appear in |msgpackparse()|

View File

@ -7,7 +7,9 @@
#include "nvim/api/private/converter.h" #include "nvim/api/private/converter.h"
#include "nvim/api/private/defs.h" #include "nvim/api/private/defs.h"
#include "nvim/api/private/helpers.h" #include "nvim/api/private/helpers.h"
#include "nvim/ascii_defs.h"
#include "nvim/assert_defs.h" #include "nvim/assert_defs.h"
#include "nvim/eval/decode.h"
#include "nvim/eval/typval.h" #include "nvim/eval/typval.h"
#include "nvim/eval/typval_defs.h" #include "nvim/eval/typval_defs.h"
#include "nvim/eval/userfunc.h" #include "nvim/eval/userfunc.h"
@ -302,15 +304,11 @@ void object_to_vim_take_luaref(Object *obj, typval_T *tv, bool take_luaref, Erro
tv->vval.v_float = obj->data.floating; tv->vval.v_float = obj->data.floating;
break; break;
case kObjectTypeString: case kObjectTypeString: {
tv->v_type = VAR_STRING; String s = obj->data.string;
if (obj->data.string.data == NULL) { *tv = decode_string(s.data, s.size, false, false);
tv->vval.v_string = NULL;
} else {
tv->vval.v_string = xmemdupz(obj->data.string.data,
obj->data.string.size);
}
break; break;
}
case kObjectTypeArray: { case kObjectTypeArray: {
list_T *const list = tv_list_alloc((ptrdiff_t)obj->data.array.size); list_T *const list = tv_list_alloc((ptrdiff_t)obj->data.array.size);

View File

@ -331,7 +331,6 @@ static const char *const msgpack_type_names[] = {
[kMPInteger] = "integer", [kMPInteger] = "integer",
[kMPFloat] = "float", [kMPFloat] = "float",
[kMPString] = "string", [kMPString] = "string",
[kMPBinary] = "binary",
[kMPArray] = "array", [kMPArray] = "array",
[kMPMap] = "map", [kMPMap] = "map",
[kMPExt] = "ext", [kMPExt] = "ext",
@ -342,7 +341,6 @@ const list_T *eval_msgpack_type_lists[] = {
[kMPInteger] = NULL, [kMPInteger] = NULL,
[kMPFloat] = NULL, [kMPFloat] = NULL,
[kMPString] = NULL, [kMPString] = NULL,
[kMPBinary] = NULL,
[kMPArray] = NULL, [kMPArray] = NULL,
[kMPMap] = NULL, [kMPMap] = NULL,
[kMPExt] = NULL, [kMPExt] = NULL,

View File

@ -7444,12 +7444,7 @@ M.funcs = {
C parser does not support such values. C parser does not support such values.
float |Float|. This value cannot possibly appear in float |Float|. This value cannot possibly appear in
|msgpackparse()| output. |msgpackparse()| output.
string |readfile()|-style list of strings. This value will string |String|, or |Blob| if binary string contains zero
appear in |msgpackparse()| output if string contains
zero byte or if string is a mapping key and mapping is
being represented as special dictionary for other
reasons.
binary |String|, or |Blob| if binary string contains zero
byte. This value cannot appear in |msgpackparse()| byte. This value cannot appear in |msgpackparse()|
output since blobs were introduced. output since blobs were introduced.
array |List|. This value cannot appear in |msgpackparse()| array |List|. This value cannot appear in |msgpackparse()|

View File

@ -247,45 +247,29 @@ list_T *decode_create_map_special_dict(typval_T *const ret_tv, const ptrdiff_t l
/// ///
/// @param[in] s String to decode. /// @param[in] s String to decode.
/// @param[in] len String length. /// @param[in] len String length.
/// @param[in] hasnul Whether string has NUL byte, not or it was not yet /// @param[in] force_blob whether string always should be decoded as a blob,
/// determined. /// or only when embedded NUL bytes were present
/// @param[in] binary Determines decode type if string has NUL bytes.
/// If true convert string to VAR_BLOB, otherwise to the
/// kMPString special type.
/// @param[in] s_allocated If true, then `s` was allocated and can be saved in /// @param[in] s_allocated If true, then `s` was allocated and can be saved in
/// a returned structure. If it is not saved there, it /// a returned structure. If it is not saved there, it
/// will be freed. /// will be freed.
/// ///
/// @return Decoded string. /// @return Decoded string.
typval_T decode_string(const char *const s, const size_t len, const TriState hasnul, typval_T decode_string(const char *const s, const size_t len, bool force_blob,
const bool binary, const bool s_allocated) const bool s_allocated)
FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_WARN_UNUSED_RESULT
{ {
assert(s != NULL || len == 0); assert(s != NULL || len == 0);
const bool really_hasnul = (hasnul == kNone const bool use_blob = force_blob || ((s != NULL) && (memchr(s, NUL, len) != NULL));
? ((s != NULL) && (memchr(s, NUL, len) != NULL)) if (use_blob) {
: (bool)hasnul);
if (really_hasnul) {
typval_T tv; typval_T tv;
tv.v_lock = VAR_UNLOCKED; tv.v_lock = VAR_UNLOCKED;
if (binary) { blob_T *b = tv_blob_alloc_ret(&tv);
tv_blob_alloc_ret(&tv); if (s_allocated) {
ga_concat_len(&tv.vval.v_blob->bv_ga, s, len); b->bv_ga.ga_data = (void *)s;
b->bv_ga.ga_len = (int)len;
b->bv_ga.ga_maxlen = (int)len;
} else { } else {
list_T *const list = tv_list_alloc(kListLenMayKnow); ga_concat_len(&b->bv_ga, s, len);
tv_list_ref(list);
create_special_dict(&tv, kMPString,
(typval_T){ .v_type = VAR_LIST,
.v_lock = VAR_UNLOCKED,
.vval = { .v_list = list } });
const int elw_ret = encode_list_write((void *)list, s, len);
if (s_allocated) {
xfree((void *)s);
}
if (elw_ret == -1) {
tv_clear(&tv);
return (typval_T) { .v_type = VAR_UNKNOWN, .v_lock = VAR_UNLOCKED };
}
} }
return tv; return tv;
} }
@ -405,7 +389,6 @@ static inline int parse_json_string(const char *const buf, const size_t buf_len,
char *str = xmalloc(len + 1); char *str = xmalloc(len + 1);
int fst_in_pair = 0; int fst_in_pair = 0;
char *str_end = str; char *str_end = str;
bool hasnul = false;
#define PUT_FST_IN_PAIR(fst_in_pair, str_end) \ #define PUT_FST_IN_PAIR(fst_in_pair, str_end) \
do { \ do { \
if ((fst_in_pair) != 0) { \ if ((fst_in_pair) != 0) { \
@ -426,9 +409,6 @@ static inline int parse_json_string(const char *const buf, const size_t buf_len,
uvarnumber_T ch; uvarnumber_T ch;
vim_str2nr(ubuf, NULL, NULL, vim_str2nr(ubuf, NULL, NULL,
STR2NR_HEX | STR2NR_FORCE, NULL, &ch, 4, true, NULL); STR2NR_HEX | STR2NR_FORCE, NULL, &ch, 4, true, NULL);
if (ch == 0) {
hasnul = true;
}
if (SURROGATE_HI_START <= ch && ch <= SURROGATE_HI_END) { if (SURROGATE_HI_START <= ch && ch <= SURROGATE_HI_END) {
PUT_FST_IN_PAIR(fst_in_pair, str_end); PUT_FST_IN_PAIR(fst_in_pair, str_end);
fst_in_pair = (int)ch; fst_in_pair = (int)ch;
@ -476,10 +456,7 @@ static inline int parse_json_string(const char *const buf, const size_t buf_len,
PUT_FST_IN_PAIR(fst_in_pair, str_end); PUT_FST_IN_PAIR(fst_in_pair, str_end);
#undef PUT_FST_IN_PAIR #undef PUT_FST_IN_PAIR
*str_end = NUL; *str_end = NUL;
typval_T obj = decode_string(str, (size_t)(str_end - str), hasnul ? kTrue : kFalse, false, true); typval_T obj = decode_string(str, (size_t)(str_end - str), false, true);
if (obj.v_type == VAR_UNKNOWN) {
goto parse_json_string_fail;
}
POP(obj, obj.v_type != VAR_STRING); POP(obj, obj.v_type != VAR_STRING);
goto parse_json_string_ret; goto parse_json_string_ret;
parse_json_string_fail: parse_json_string_fail:
@ -982,18 +959,8 @@ int msgpack_to_vim(const msgpack_object mobj, typval_T *const rettv)
}; };
break; break;
case MSGPACK_OBJECT_STR: case MSGPACK_OBJECT_STR:
*rettv = decode_string(mobj.via.bin.ptr, mobj.via.bin.size, kTrue, false,
false);
if (rettv->v_type == VAR_UNKNOWN) {
return FAIL;
}
break;
case MSGPACK_OBJECT_BIN: case MSGPACK_OBJECT_BIN:
*rettv = decode_string(mobj.via.bin.ptr, mobj.via.bin.size, kNone, true, *rettv = decode_string(mobj.via.bin.ptr, mobj.via.bin.size, false, false);
false);
if (rettv->v_type == VAR_UNKNOWN) {
return FAIL;
}
break; break;
case MSGPACK_OBJECT_ARRAY: { case MSGPACK_OBJECT_ARRAY: {
list_T *const list = tv_list_alloc((ptrdiff_t)mobj.via.array.size); list_T *const list = tv_list_alloc((ptrdiff_t)mobj.via.array.size);
@ -1016,7 +983,8 @@ int msgpack_to_vim(const msgpack_object mobj, typval_T *const rettv)
} }
case MSGPACK_OBJECT_MAP: { case MSGPACK_OBJECT_MAP: {
for (size_t i = 0; i < mobj.via.map.size; i++) { for (size_t i = 0; i < mobj.via.map.size; i++) {
if (mobj.via.map.ptr[i].key.type != MSGPACK_OBJECT_STR if ((mobj.via.map.ptr[i].key.type != MSGPACK_OBJECT_STR
&& mobj.via.map.ptr[i].key.type != MSGPACK_OBJECT_BIN)
|| mobj.via.map.ptr[i].key.via.str.size == 0 || mobj.via.map.ptr[i].key.via.str.size == 0
|| memchr(mobj.via.map.ptr[i].key.via.str.ptr, NUL, || memchr(mobj.via.map.ptr[i].key.via.str.ptr, NUL,
mobj.via.map.ptr[i].key.via.str.size) != NULL) { mobj.via.map.ptr[i].key.via.str.size) != NULL) {

View File

@ -776,8 +776,7 @@ bool encode_check_json_key(const typval_T *const tv)
const dictitem_T *val_di; const dictitem_T *val_di;
if ((type_di = tv_dict_find(spdict, S_LEN("_TYPE"))) == NULL if ((type_di = tv_dict_find(spdict, S_LEN("_TYPE"))) == NULL
|| type_di->di_tv.v_type != VAR_LIST || type_di->di_tv.v_type != VAR_LIST
|| (type_di->di_tv.vval.v_list != eval_msgpack_type_lists[kMPString] || type_di->di_tv.vval.v_list != eval_msgpack_type_lists[kMPString]
&& type_di->di_tv.vval.v_list != eval_msgpack_type_lists[kMPBinary])
|| (val_di = tv_dict_find(spdict, S_LEN("_VAL"))) == NULL || (val_di = tv_dict_find(spdict, S_LEN("_VAL"))) == NULL
|| val_di->di_tv.v_type != VAR_LIST) { || val_di->di_tv.v_type != VAR_LIST) {
return false; return false;

View File

@ -501,9 +501,7 @@ static int TYPVAL_ENCODE_CONVERT_ONE_VALUE(
} }
TYPVAL_ENCODE_CONV_FLOAT(tv, val_di->di_tv.vval.v_float); TYPVAL_ENCODE_CONV_FLOAT(tv, val_di->di_tv.vval.v_float);
break; break;
case kMPString: case kMPString: {
case kMPBinary: {
const bool is_string = ((MessagePackType)i == kMPString);
if (val_di->di_tv.v_type != VAR_LIST) { if (val_di->di_tv.v_type != VAR_LIST) {
goto _convert_one_value_regular_dict; goto _convert_one_value_regular_dict;
} }
@ -513,11 +511,7 @@ static int TYPVAL_ENCODE_CONVERT_ONE_VALUE(
&buf)) { &buf)) {
goto _convert_one_value_regular_dict; goto _convert_one_value_regular_dict;
} }
if (is_string) { TYPVAL_ENCODE_CONV_STR_STRING(tv, buf, len);
TYPVAL_ENCODE_CONV_STR_STRING(tv, buf, len);
} else {
TYPVAL_ENCODE_CONV_STRING(tv, buf, len);
}
xfree(buf); xfree(buf);
break; break;
} }

View File

@ -9,7 +9,6 @@ typedef enum {
kMPInteger, kMPInteger,
kMPFloat, kMPFloat,
kMPString, kMPString,
kMPBinary,
kMPArray, kMPArray,
kMPMap, kMPMap,
kMPExt, kMPExt,

View File

@ -219,12 +219,7 @@ bool nlua_pop_typval(lua_State *lstate, typval_T *ret_tv)
if (cur.special) { if (cur.special) {
list_T *const kv_pair = tv_list_alloc(2); list_T *const kv_pair = tv_list_alloc(2);
typval_T s_tv = decode_string(s, len, kTrue, false, false); typval_T s_tv = decode_string(s, len, true, false);
if (s_tv.v_type == VAR_UNKNOWN) {
ret = false;
tv_list_unref(kv_pair);
continue;
}
tv_list_append_owned_tv(kv_pair, s_tv); tv_list_append_owned_tv(kv_pair, s_tv);
// Value: not populated yet, need to create list item to push. // Value: not populated yet, need to create list item to push.
@ -280,10 +275,7 @@ bool nlua_pop_typval(lua_State *lstate, typval_T *ret_tv)
case LUA_TSTRING: { case LUA_TSTRING: {
size_t len; size_t len;
const char *s = lua_tolstring(lstate, -1, &len); const char *s = lua_tolstring(lstate, -1, &len);
*cur.tv = decode_string(s, len, kNone, true, false); *cur.tv = decode_string(s, len, false, false);
if (cur.tv->v_type == VAR_UNKNOWN) {
ret = false;
}
break; break;
} }
case LUA_TNUMBER: { case LUA_TNUMBER: {

View File

@ -1571,9 +1571,9 @@ describe('API', function()
eq(val2, request('vim_del_var', 'lua')) eq(val2, request('vim_del_var', 'lua'))
end) end)
it('truncates values with NULs in them', function() it('preserves values with NULs in them', function()
api.nvim_set_var('xxx', 'ab\0cd') api.nvim_set_var('xxx', 'ab\0cd')
eq('ab', api.nvim_get_var('xxx')) eq('ab\000cd', api.nvim_get_var('xxx'))
end) end)
end) end)

View File

@ -72,9 +72,9 @@ describe('luaeval()', function()
end) end)
it('are successfully converted to special dictionaries in table keys', function() it('are successfully converted to special dictionaries in table keys', function()
command([[let d = luaeval('{["\0"]=1}')]]) command([[let d = luaeval('{["\0"]=1}')]])
eq({_TYPE={}, _VAL={{{_TYPE={}, _VAL={'\n'}}, 1}}}, api.nvim_get_var('d')) eq({_TYPE={}, _VAL={{'\000', 1}}}, api.nvim_get_var('d'))
eq(1, fn.eval('d._TYPE is v:msgpack_types.map')) eq(1, fn.eval('d._TYPE is v:msgpack_types.map'))
eq(1, fn.eval('d._VAL[0][0]._TYPE is v:msgpack_types.string')) eq(eval('v:t_blob'), fn.eval('type(d._VAL[0][0])'))
end) end)
it('are successfully converted to blobs from a list', function() it('are successfully converted to blobs from a list', function()
command([[let l = luaeval('{"abc", "a\0b", "c\0d", "def"}')]]) command([[let l = luaeval('{"abc", "a\0b", "c\0d", "def"}')]])
@ -125,11 +125,11 @@ describe('luaeval()', function()
local level = 30 local level = 30
eq(nested_by_level[level].o, fn.luaeval(nested_by_level[level].s)) eq(nested_by_level[level].o, fn.luaeval(nested_by_level[level].s))
eq({_TYPE={}, _VAL={{{_TYPE={}, _VAL={'\n', '\n'}}, '\000\n\000\000'}}}, eq({_TYPE={}, _VAL={{'\000\n\000', '\000\n\000\000'}}},
fn.luaeval([[{['\0\n\0']='\0\n\0\0'}]])) fn.luaeval([[{['\0\n\0']='\0\n\0\0'}]]))
eq(1, eval([[luaeval('{["\0\n\0"]="\0\n\0\0"}')._TYPE is v:msgpack_types.map]])) eq(1, eval([[luaeval('{["\0\n\0"]="\0\n\0\0"}')._TYPE is v:msgpack_types.map]]))
eq(1, eval([[luaeval('{["\0\n\0"]="\0\n\0\0"}')._VAL[0][0]._TYPE is v:msgpack_types.string]])) eq(eval("v:t_blob"), eval([[type(luaeval('{["\0\n\0"]="\0\n\0\0"}')._VAL[0][0])]]))
eq({nested={{_TYPE={}, _VAL={{{_TYPE={}, _VAL={'\n', '\n'}}, '\000\n\000\000'}}}}}, eq({nested={{_TYPE={}, _VAL={{'\000\n\000', '\000\n\000\000'}}}}},
fn.luaeval([[{nested={{['\0\n\0']='\0\n\0\0'}}}]])) fn.luaeval([[{nested={{['\0\n\0']='\0\n\0\0'}}}]]))
end) end)
@ -177,12 +177,10 @@ describe('luaeval()', function()
end end
it('correctly passes special dictionaries', function() it('correctly passes special dictionaries', function()
eq({0, '\000\n\000'}, luaevalarg(sp('binary', '["\\n", "\\n"]')))
eq({0, '\000\n\000'}, luaevalarg(sp('string', '["\\n", "\\n"]'))) eq({0, '\000\n\000'}, luaevalarg(sp('string', '["\\n", "\\n"]')))
eq({0, true}, luaevalarg(sp('boolean', 1))) eq({0, true}, luaevalarg(sp('boolean', 1)))
eq({0, false}, luaevalarg(sp('boolean', 0))) eq({0, false}, luaevalarg(sp('boolean', 0)))
eq({0, NIL}, luaevalarg(sp('nil', 0))) eq({0, NIL}, luaevalarg(sp('nil', 0)))
eq({0, {[""]=""}}, luaevalarg(mapsp(sp('binary', '[""]'), '""')))
eq({0, {[""]=""}}, luaevalarg(mapsp(sp('string', '[""]'), '""'))) eq({0, {[""]=""}}, luaevalarg(mapsp(sp('string', '[""]'), '""')))
end) end)

View File

@ -58,23 +58,11 @@ describe('autoload/msgpack.vim', function()
msgpack_eq(1, '"abc\\ndef"', '"abc\\ndef"') msgpack_eq(1, '"abc\\ndef"', '"abc\\ndef"')
msgpack_eq(0, '"abc\\ndef"', '"abc\\nghi"') msgpack_eq(0, '"abc\\ndef"', '"abc\\nghi"')
end) end)
it('compares binary specials correctly', function()
msgpack_eq(1, sp('binary', '["abc\\n", "def"]'), sp('binary', '["abc\\n", "def"]'))
msgpack_eq(0, sp('binary', '["abc", "def"]'), sp('binary', '["abc\\n", "def"]'))
end)
it('compares binary specials with raw binaries correctly', function()
msgpack_eq(1, sp('binary', '["abc", "def"]'), '"abc\\ndef"')
msgpack_eq(0, sp('binary', '["abc", "def"]'), '"abcdef"')
end)
it('compares string specials correctly', function() it('compares string specials correctly', function()
msgpack_eq(1, sp('string', '["abc\\n", "def"]'), sp('string', '["abc\\n", "def"]')) msgpack_eq(1, sp('string', '["abc\\n", "def"]'), sp('string', '["abc\\n", "def"]'))
msgpack_eq(0, sp('string', '["abc", "def"]'), sp('string', '["abc\\n", "def"]')) msgpack_eq(0, sp('string', '["abc", "def"]'), sp('string', '["abc\\n", "def"]'))
end) msgpack_eq(1, sp('string', '["abc", "def"]'), '"abc\\ndef"')
it('compares string specials with binary correctly', function() msgpack_eq(1, '"abc\\ndef"', sp('string', '["abc", "def"]'))
msgpack_eq(0, sp('string', '["abc\\n", "def"]'), sp('binary', '["abc\\n", "def"]'))
msgpack_eq(0, sp('string', '["abc", "def"]'), '"abc\\ndef"')
msgpack_eq(0, sp('binary', '["abc\\n", "def"]'), sp('string', '["abc\\n", "def"]'))
msgpack_eq(0, '"abc\\ndef"', sp('string', '["abc", "def"]'))
end) end)
it('compares ext specials correctly', function() it('compares ext specials correctly', function()
msgpack_eq(1, sp('ext', '[1, ["", "ac"]]'), sp('ext', '[1, ["", "ac"]]')) msgpack_eq(1, sp('ext', '[1, ["", "ac"]]'), sp('ext', '[1, ["", "ac"]]'))
@ -92,20 +80,16 @@ describe('autoload/msgpack.vim', function()
end) end)
it('compares map specials correctly', function() it('compares map specials correctly', function()
msgpack_eq(1, mapsp(), mapsp()) msgpack_eq(1, mapsp(), mapsp())
msgpack_eq(1, mapsp(sp('binary', '[""]'), '""'), mapsp(sp('binary', '[""]'), '""'))
msgpack_eq( msgpack_eq(
1, 1,
mapsp(mapsp('1', '1'), mapsp('1', '1')), mapsp(mapsp('1', '1'), mapsp('1', '1')),
mapsp(mapsp('1', '1'), mapsp('1', '1')) mapsp(mapsp('1', '1'), mapsp('1', '1'))
) )
msgpack_eq(0, mapsp(), mapsp('1', '1')) msgpack_eq(0, mapsp(), mapsp('1', '1'))
msgpack_eq(0, mapsp(sp('binary', '["a"]'), '""'), mapsp(sp('binary', '[""]'), '""'))
msgpack_eq(0, mapsp(sp('binary', '[""]'), '"a"'), mapsp(sp('binary', '[""]'), '""'))
msgpack_eq(0, mapsp(sp('binary', '["a"]'), '"a"'), mapsp(sp('binary', '[""]'), '""'))
msgpack_eq( msgpack_eq(
0, 0,
mapsp(mapsp('1', '1'), mapsp('1', '1')), mapsp(mapsp('1', '1'), mapsp('1', '1')),
mapsp(sp('binary', '[""]'), mapsp('1', '1')) mapsp(sp('string', '[""]'), mapsp('1', '1'))
) )
msgpack_eq( msgpack_eq(
0, 0,
@ -138,7 +122,7 @@ describe('autoload/msgpack.vim', function()
msgpack_eq(1, mapsp(sp('string', '["1"]'), '1'), '{"1": 1}') msgpack_eq(1, mapsp(sp('string', '["1"]'), '1'), '{"1": 1}')
msgpack_eq(1, mapsp(sp('string', '["1"]'), sp('integer', '[1, 0, 0, 1]')), '{"1": 1}') msgpack_eq(1, mapsp(sp('string', '["1"]'), sp('integer', '[1, 0, 0, 1]')), '{"1": 1}')
msgpack_eq(0, mapsp(sp('integer', '[1, 0, 0, 1]'), sp('string', '["1"]')), '{1: "1"}') msgpack_eq(0, mapsp(sp('integer', '[1, 0, 0, 1]'), sp('string', '["1"]')), '{1: "1"}')
msgpack_eq(0, mapsp('"1"', sp('integer', '[1, 0, 0, 1]')), '{"1": 1}') msgpack_eq(1, mapsp('"1"', sp('integer', '[1, 0, 0, 1]')), '{"1": 1}')
msgpack_eq(0, mapsp(sp('string', '["1"]'), '1', sp('string', '["2"]'), '2'), '{"1": 1}') msgpack_eq(0, mapsp(sp('string', '["1"]'), '1', sp('string', '["2"]'), '2'), '{"1": 1}')
msgpack_eq(0, mapsp(sp('string', '["1"]'), '1'), '{"1": 1, "2": 2}') msgpack_eq(0, mapsp(sp('string', '["1"]'), '1'), '{"1": 1, "2": 2}')
end) end)
@ -290,7 +274,6 @@ describe('autoload/msgpack.vim', function()
it('works for special dictionaries', function() it('works for special dictionaries', function()
type_eq('string', sp('string', '[""]')) type_eq('string', sp('string', '[""]'))
type_eq('binary', sp('binary', '[""]'))
type_eq('ext', sp('ext', '[1, [""]]')) type_eq('ext', sp('ext', '[1, [""]]'))
type_eq('array', sp('array', '[]')) type_eq('array', sp('array', '[]'))
type_eq('map', sp('map', '[]')) type_eq('map', sp('map', '[]'))
@ -301,7 +284,7 @@ describe('autoload/msgpack.vim', function()
end) end)
it('works for regular values', function() it('works for regular values', function()
type_eq('binary', '""') type_eq('string', '""')
type_eq('array', '[]') type_eq('array', '[]')
type_eq('map', '{}') type_eq('map', '{}')
type_eq('integer', '1') type_eq('integer', '1')
@ -319,7 +302,6 @@ describe('autoload/msgpack.vim', function()
it('works for special dictionaries', function() it('works for special dictionaries', function()
sp_type_eq('string', sp('string', '[""]')) sp_type_eq('string', sp('string', '[""]'))
sp_type_eq('binary', sp('binary', '[""]'))
sp_type_eq('ext', sp('ext', '[1, [""]]')) sp_type_eq('ext', sp('ext', '[1, [""]]'))
sp_type_eq('array', sp('array', '[]')) sp_type_eq('array', sp('array', '[]'))
sp_type_eq('map', sp('map', '[]')) sp_type_eq('map', sp('map', '[]'))
@ -347,12 +329,9 @@ describe('autoload/msgpack.vim', function()
end end
it('works for special dictionaries', function() it('works for special dictionaries', function()
string_eq('=""', sp('string', '[""]')) string_eq('""', sp('string', '[""]'))
string_eq('="\\n"', sp('string', '["", ""]')) string_eq('"\\n"', sp('string', '["", ""]'))
string_eq('="ab\\0c\\nde"', sp('string', '["ab\\nc", "de"]')) string_eq('"ab\\0c\\nde"', sp('string', '["ab\\nc", "de"]'))
string_eq('""', sp('binary', '[""]'))
string_eq('"\\n"', sp('binary', '["", ""]'))
string_eq('"ab\\0c\\nde"', sp('binary', '["ab\\nc", "de"]'))
string_eq('+(2)""', sp('ext', '[2, [""]]')) string_eq('+(2)""', sp('ext', '[2, [""]]'))
string_eq('+(2)"\\n"', sp('ext', '[2, ["", ""]]')) string_eq('+(2)"\\n"', sp('ext', '[2, ["", ""]]'))
string_eq('+(2)"ab\\0c\\nde"', sp('ext', '[2, ["ab\\nc", "de"]]')) string_eq('+(2)"ab\\0c\\nde"', sp('ext', '[2, ["ab\\nc", "de"]]'))
@ -397,8 +376,8 @@ describe('autoload/msgpack.vim', function()
string_eq('[]', '[]') string_eq('[]', '[]')
string_eq('[[[{}]]]', '[[[{}]]]') string_eq('[[[{}]]]', '[[[{}]]]')
string_eq('{}', '{}') string_eq('{}', '{}')
string_eq('{="2": 10}', '{2: 10}') string_eq('{"2": 10}', '{2: 10}')
string_eq('{="2": [{}]}', '{2: [{}]}') string_eq('{"2": [{}]}', '{2: [{}]}')
string_eq('1', '1') string_eq('1', '1')
string_eq('0.0', '0.0') string_eq('0.0', '0.0')
string_eq('inf', '(1.0/0.0)') string_eq('inf', '(1.0/0.0)')
@ -422,7 +401,6 @@ describe('autoload/msgpack.vim', function()
nvim_command('let spflt = ' .. sp('float', '1.0')) nvim_command('let spflt = ' .. sp('float', '1.0'))
nvim_command('let spext = ' .. sp('ext', '[2, ["abc", "def"]]')) nvim_command('let spext = ' .. sp('ext', '[2, ["abc", "def"]]'))
nvim_command('let spstr = ' .. sp('string', '["abc", "def"]')) nvim_command('let spstr = ' .. sp('string', '["abc", "def"]'))
nvim_command('let spbin = ' .. sp('binary', '["abc", "def"]'))
nvim_command('let spbln = ' .. sp('boolean', '0')) nvim_command('let spbln = ' .. sp('boolean', '0'))
nvim_command('let spnil = ' .. sp('nil', '0')) nvim_command('let spnil = ' .. sp('nil', '0'))
@ -432,7 +410,6 @@ describe('autoload/msgpack.vim', function()
nvim_command('let spflt2 = msgpack#deepcopy(spflt)') nvim_command('let spflt2 = msgpack#deepcopy(spflt)')
nvim_command('let spext2 = msgpack#deepcopy(spext)') nvim_command('let spext2 = msgpack#deepcopy(spext)')
nvim_command('let spstr2 = msgpack#deepcopy(spstr)') nvim_command('let spstr2 = msgpack#deepcopy(spstr)')
nvim_command('let spbin2 = msgpack#deepcopy(spbin)')
nvim_command('let spbln2 = msgpack#deepcopy(spbln)') nvim_command('let spbln2 = msgpack#deepcopy(spbln)')
nvim_command('let spnil2 = msgpack#deepcopy(spnil)') nvim_command('let spnil2 = msgpack#deepcopy(spnil)')
@ -442,7 +419,6 @@ describe('autoload/msgpack.vim', function()
eq('float', nvim_eval('msgpack#type(spflt2)')) eq('float', nvim_eval('msgpack#type(spflt2)'))
eq('ext', nvim_eval('msgpack#type(spext2)')) eq('ext', nvim_eval('msgpack#type(spext2)'))
eq('string', nvim_eval('msgpack#type(spstr2)')) eq('string', nvim_eval('msgpack#type(spstr2)'))
eq('binary', nvim_eval('msgpack#type(spbin2)'))
eq('boolean', nvim_eval('msgpack#type(spbln2)')) eq('boolean', nvim_eval('msgpack#type(spbln2)'))
eq('nil', nvim_eval('msgpack#type(spnil2)')) eq('nil', nvim_eval('msgpack#type(spnil2)'))
@ -457,7 +433,6 @@ describe('autoload/msgpack.vim', function()
nvim_command('let spext._VAL[0] = 3') nvim_command('let spext._VAL[0] = 3')
nvim_command('let spext._VAL[1][0] = "gh"') nvim_command('let spext._VAL[1][0] = "gh"')
nvim_command('let spstr._VAL[0] = "gh"') nvim_command('let spstr._VAL[0] = "gh"')
nvim_command('let spbin._VAL[0] = "gh"')
nvim_command('let spbln._VAL = 1') nvim_command('let spbln._VAL = 1')
nvim_command('let spnil._VAL = 1') nvim_command('let spnil._VAL = 1')
@ -467,7 +442,6 @@ describe('autoload/msgpack.vim', function()
eq({ _TYPE = {}, _VAL = 1.0 }, nvim_eval('spflt2')) eq({ _TYPE = {}, _VAL = 1.0 }, nvim_eval('spflt2'))
eq({ _TYPE = {}, _VAL = { 2, { 'abc', 'def' } } }, nvim_eval('spext2')) eq({ _TYPE = {}, _VAL = { 2, { 'abc', 'def' } } }, nvim_eval('spext2'))
eq({ _TYPE = {}, _VAL = { 'abc', 'def' } }, nvim_eval('spstr2')) eq({ _TYPE = {}, _VAL = { 'abc', 'def' } }, nvim_eval('spstr2'))
eq({ _TYPE = {}, _VAL = { 'abc', 'def' } }, nvim_eval('spbin2'))
eq({ _TYPE = {}, _VAL = 0 }, nvim_eval('spbln2')) eq({ _TYPE = {}, _VAL = 0 }, nvim_eval('spbln2'))
eq({ _TYPE = {}, _VAL = 0 }, nvim_eval('spnil2')) eq({ _TYPE = {}, _VAL = 0 }, nvim_eval('spnil2'))
@ -477,7 +451,6 @@ describe('autoload/msgpack.vim', function()
nvim_command('let spflt._TYPE = []') nvim_command('let spflt._TYPE = []')
nvim_command('let spext._TYPE = []') nvim_command('let spext._TYPE = []')
nvim_command('let spstr._TYPE = []') nvim_command('let spstr._TYPE = []')
nvim_command('let spbin._TYPE = []')
nvim_command('let spbln._TYPE = []') nvim_command('let spbln._TYPE = []')
nvim_command('let spnil._TYPE = []') nvim_command('let spnil._TYPE = []')
@ -487,7 +460,6 @@ describe('autoload/msgpack.vim', function()
eq('float', nvim_eval('msgpack#special_type(spflt2)')) eq('float', nvim_eval('msgpack#special_type(spflt2)'))
eq('ext', nvim_eval('msgpack#special_type(spext2)')) eq('ext', nvim_eval('msgpack#special_type(spext2)'))
eq('string', nvim_eval('msgpack#special_type(spstr2)')) eq('string', nvim_eval('msgpack#special_type(spstr2)'))
eq('binary', nvim_eval('msgpack#special_type(spbin2)'))
eq('boolean', nvim_eval('msgpack#special_type(spbln2)')) eq('boolean', nvim_eval('msgpack#special_type(spbln2)'))
eq('nil', nvim_eval('msgpack#special_type(spnil2)')) eq('nil', nvim_eval('msgpack#special_type(spnil2)'))
end) end)
@ -509,7 +481,7 @@ describe('autoload/msgpack.vim', function()
eq('map', nvim_eval('msgpack#type(map2)')) eq('map', nvim_eval('msgpack#type(map2)'))
eq('integer', nvim_eval('msgpack#type(int2)')) eq('integer', nvim_eval('msgpack#type(int2)'))
eq('float', nvim_eval('msgpack#type(flt2)')) eq('float', nvim_eval('msgpack#type(flt2)'))
eq('binary', nvim_eval('msgpack#type(bin2)')) eq('string', nvim_eval('msgpack#type(bin2)'))
nvim_command('call add(arr, 0)') nvim_command('call add(arr, 0)')
nvim_command('call add(arr[0], 0)') nvim_command('call add(arr[0], 0)')
@ -566,21 +538,6 @@ describe('autoload/msgpack.vim', function()
nvim_command('unlet g:__val') nvim_command('unlet g:__val')
end end
it('correctly loads binary strings', function()
eval_eq('binary', { 'abcdef' }, '"abcdef"')
eval_eq('binary', { 'abc', 'def' }, '"abc\\ndef"')
eval_eq('binary', { 'abc\ndef' }, '"abc\\0def"')
eval_eq('binary', { '\nabc\ndef\n' }, '"\\0abc\\0def\\0"')
eval_eq('binary', { 'abc\n\n\ndef' }, '"abc\\0\\0\\0def"')
eval_eq('binary', { 'abc\n', '\ndef' }, '"abc\\0\\n\\0def"')
eval_eq('binary', { 'abc', '', '', 'def' }, '"abc\\n\\n\\ndef"')
eval_eq('binary', { 'abc', '', '', 'def', '' }, '"abc\\n\\n\\ndef\\n"')
eval_eq('binary', { '', 'abc', '', '', 'def' }, '"\\nabc\\n\\n\\ndef"')
eval_eq('binary', { '' }, '""')
eval_eq('binary', { '"' }, '"\\""')
eval_eq('binary', { 'py3 print(sys.version_info)' }, '"py3 print(sys.version_info)"')
end)
it('correctly loads strings', function() it('correctly loads strings', function()
eval_eq('string', { 'abcdef' }, '="abcdef"') eval_eq('string', { 'abcdef' }, '="abcdef"')
eval_eq('string', { 'abc', 'def' }, '="abc\\ndef"') eval_eq('string', { 'abc', 'def' }, '="abc\\ndef"')

View File

@ -68,7 +68,7 @@ describe('autoload/shada.vim', function()
endfor endfor
return ret return ret
elseif type(a:val) == type('') elseif type(a:val) == type('')
return {'_TYPE': v:msgpack_types.binary, '_VAL': split(a:val, "\n", 1)} return {'_TYPE': v:msgpack_types.string, '_VAL': split(a:val, "\n", 1)}
else else
return a:val return a:val
endif endif
@ -253,8 +253,7 @@ describe('autoload/shada.vim', function()
' + sm magic value "TRUE"', ' + sm magic value "TRUE"',
' # Expected integer', ' # Expected integer',
' + so offset value "TRUE"', ' + so offset value "TRUE"',
' # Expected binary string', ' + sp pattern "abc"',
' + sp pattern ="abc"',
}, },
([[ [{'type': 1, 'timestamp': 0, 'data': { ([[ [{'type': 1, 'timestamp': 0, 'data': {
'sm': 'TRUE', 'sm': 'TRUE',
@ -267,7 +266,7 @@ describe('autoload/shada.vim', function()
'n': -0x40, 'n': -0x40,
'l': -10, 'l': -10,
'c': 'abc', 'c': 'abc',
'f': {'_TYPE': v:msgpack_types.binary, '_VAL': ["abc\ndef"]}, 'f': {'_TYPE': v:msgpack_types.string, '_VAL': ["abc\ndef"]},
}}] ]]):gsub('\n', '') }}] ]]):gsub('\n', '')
) )
sd2strings_eq( sd2strings_eq(
@ -276,15 +275,14 @@ describe('autoload/shada.vim', function()
' % Key Description Value', ' % Key Description Value',
' # Expected no NUL bytes', ' # Expected no NUL bytes',
' + f file name "abc\\0def"', ' + f file name "abc\\0def"',
' # Expected array of binary strings', ' + rc contents ["abc", "abc"]',
' + rc contents ["abc", ="abc"]',
' # Expected integer', ' # Expected integer',
' + rt type "ABC"', ' + rt type "ABC"',
}, },
([[ [{'type': 1, 'timestamp': 0, 'data': { ([[ [{'type': 1, 'timestamp': 0, 'data': {
'rt': 'ABC', 'rt': 'ABC',
'rc': ["abc", {'_TYPE': v:msgpack_types.string, '_VAL': ["abc"]}], 'rc': ["abc", {'_TYPE': v:msgpack_types.string, '_VAL': ["abc"]}],
'f': {'_TYPE': v:msgpack_types.binary, '_VAL': ["abc\ndef"]}, 'f': {'_TYPE': v:msgpack_types.string, '_VAL': ["abc\ndef"]},
}}] ]]):gsub('\n', '') }}] ]]):gsub('\n', '')
) )
sd2strings_eq( sd2strings_eq(
@ -295,7 +293,7 @@ describe('autoload/shada.vim', function()
' + rc contents ["abc", "a\\nd\\0"]', ' + rc contents ["abc", "a\\nd\\0"]',
}, },
([[ [{'type': 1, 'timestamp': 0, 'data': { ([[ [{'type': 1, 'timestamp': 0, 'data': {
'rc': ["abc", {'_TYPE': v:msgpack_types.binary, '_VAL': ["a", "d\n"]}], 'rc': ["abc", {'_TYPE': v:msgpack_types.string, '_VAL': ["a", "d\n"]}],
}}] ]]):gsub('\n', '') }}] ]]):gsub('\n', '')
) )
end) end)
@ -468,7 +466,7 @@ describe('autoload/shada.vim', function()
sd2strings_eq({ sd2strings_eq({
'Replacement string with timestamp ' .. epoch .. ':', 'Replacement string with timestamp ' .. epoch .. ':',
' # Unexpected type: map instead of array', ' # Unexpected type: map instead of array',
' = {="a": [10]}', ' = {"a": [10]}',
}, { { type = 3, timestamp = 0, data = { a = { 10 } } } }) }, { { type = 3, timestamp = 0, data = { a = { 10 } } } })
sd2strings_eq( sd2strings_eq(
{ {
@ -498,7 +496,7 @@ describe('autoload/shada.vim', function()
' - :s replacement string "abc\\0def"', ' - :s replacement string "abc\\0def"',
}, },
([[ [{'type': 3, 'timestamp': 0, 'data': [ ([[ [{'type': 3, 'timestamp': 0, 'data': [
{'_TYPE': v:msgpack_types.binary, '_VAL': ["abc\ndef"]}, {'_TYPE': v:msgpack_types.string, '_VAL': ["abc\ndef"]},
]}] ]]):gsub('\n', '') ]}] ]]):gsub('\n', '')
) )
sd2strings_eq( sd2strings_eq(
@ -508,7 +506,7 @@ describe('autoload/shada.vim', function()
' - :s replacement string "abc\\ndef"', ' - :s replacement string "abc\\ndef"',
}, },
([[ [{'type': 3, 'timestamp': 0, 'data': [ ([[ [{'type': 3, 'timestamp': 0, 'data': [
{'_TYPE': v:msgpack_types.binary, '_VAL': ["abc", "def"]}, {'_TYPE': v:msgpack_types.string, '_VAL': ["abc", "def"]},
]}] ]]):gsub('\n', '') ]}] ]]):gsub('\n', '')
) )
sd2strings_eq( sd2strings_eq(
@ -519,7 +517,7 @@ describe('autoload/shada.vim', function()
' - 0', ' - 0',
}, },
([[ [{'type': 3, 'timestamp': 0, 'data': [ ([[ [{'type': 3, 'timestamp': 0, 'data': [
{'_TYPE': v:msgpack_types.binary, '_VAL': ["abc", "def"]}, {'_TYPE': v:msgpack_types.string, '_VAL': ["abc", "def"]},
0, 0,
]}] ]]):gsub('\n', '') ]}] ]]):gsub('\n', '')
) )
@ -529,7 +527,7 @@ describe('autoload/shada.vim', function()
sd2strings_eq({ sd2strings_eq({
'History entry with timestamp ' .. epoch .. ':', 'History entry with timestamp ' .. epoch .. ':',
' # Unexpected type: map instead of array', ' # Unexpected type: map instead of array',
' = {="a": [10]}', ' = {"a": [10]}',
}, { { type = 4, timestamp = 0, data = { a = { 10 } } } }) }, { { type = 4, timestamp = 0, data = { a = { 10 } } } })
sd2strings_eq( sd2strings_eq(
{ {
@ -682,7 +680,7 @@ describe('autoload/shada.vim', function()
}, },
([[ [{'type': 4, 'timestamp': 0, 'data': [ ([[ [{'type': 4, 'timestamp': 0, 'data': [
4, 4,
{'_TYPE': v:msgpack_types.binary, '_VAL': ["abc\ndef"]}, {'_TYPE': v:msgpack_types.string, '_VAL': ["abc\ndef"]},
]}] ]]):gsub('\n', '') ]}] ]]):gsub('\n', '')
) )
sd2strings_eq( sd2strings_eq(
@ -909,7 +907,7 @@ describe('autoload/shada.vim', function()
sd2strings_eq({ sd2strings_eq({
'Variable with timestamp ' .. epoch .. ':', 'Variable with timestamp ' .. epoch .. ':',
' # Unexpected type: map instead of array', ' # Unexpected type: map instead of array',
' = {="a": [10]}', ' = {"a": [10]}',
}, { { type = 6, timestamp = 0, data = { a = { 10 } } } }) }, { { type = 6, timestamp = 0, data = { a = { 10 } } } })
sd2strings_eq( sd2strings_eq(
{ {
@ -941,7 +939,7 @@ describe('autoload/shada.vim', function()
' # Expected more elements in list', ' # Expected more elements in list',
}, },
([[ [{'type': 6, 'timestamp': 0, 'data': [ ([[ [{'type': 6, 'timestamp': 0, 'data': [
{'_TYPE': v:msgpack_types.binary, '_VAL': ["\n"]}, {'_TYPE': v:msgpack_types.string, '_VAL': ["\n"]},
]}] ]]):gsub('\n', '') ]}] ]]):gsub('\n', '')
) )
sd2strings_eq( sd2strings_eq(
@ -952,7 +950,7 @@ describe('autoload/shada.vim', function()
' # Expected more elements in list', ' # Expected more elements in list',
}, },
([[ [{'type': 6, 'timestamp': 0, 'data': [ ([[ [{'type': 6, 'timestamp': 0, 'data': [
{'_TYPE': v:msgpack_types.binary, '_VAL': ["foo"]}, {'_TYPE': v:msgpack_types.string, '_VAL': ["foo"]},
]}] ]]):gsub('\n', '') ]}] ]]):gsub('\n', '')
) )
sd2strings_eq( sd2strings_eq(
@ -963,7 +961,7 @@ describe('autoload/shada.vim', function()
' - value NIL', ' - value NIL',
}, },
([[ [{'type': 6, 'timestamp': 0, 'data': [ ([[ [{'type': 6, 'timestamp': 0, 'data': [
{'_TYPE': v:msgpack_types.binary, '_VAL': ["foo"]}, {'_TYPE': v:msgpack_types.string, '_VAL': ["foo"]},
{'_TYPE': v:msgpack_types.nil, '_VAL': ["foo"]}, {'_TYPE': v:msgpack_types.nil, '_VAL': ["foo"]},
]}] ]]):gsub('\n', '') ]}] ]]):gsub('\n', '')
) )
@ -976,7 +974,7 @@ describe('autoload/shada.vim', function()
' - NIL', ' - NIL',
}, },
([[ [{'type': 6, 'timestamp': 0, 'data': [ ([[ [{'type': 6, 'timestamp': 0, 'data': [
{'_TYPE': v:msgpack_types.binary, '_VAL': ["foo"]}, {'_TYPE': v:msgpack_types.string, '_VAL': ["foo"]},
{'_TYPE': v:msgpack_types.nil, '_VAL': ["foo"]}, {'_TYPE': v:msgpack_types.nil, '_VAL': ["foo"]},
{'_TYPE': v:msgpack_types.nil, '_VAL': ["foo"]}, {'_TYPE': v:msgpack_types.nil, '_VAL': ["foo"]},
]}] ]]):gsub('\n', '') ]}] ]]):gsub('\n', '')
@ -1041,7 +1039,7 @@ describe('autoload/shada.vim', function()
}, },
([[ [{'type': 7, 'timestamp': 0, 'data': { ([[ [{'type': 7, 'timestamp': 0, 'data': {
'n': -10, 'n': -10,
'f': {'_TYPE': v:msgpack_types.binary, '_VAL': ["\n"]}, 'f': {'_TYPE': v:msgpack_types.string, '_VAL': ["\n"]},
}}] ]]):gsub('\n', '') }}] ]]):gsub('\n', '')
) )
sd2strings_eq( sd2strings_eq(
@ -1174,7 +1172,7 @@ describe('autoload/shada.vim', function()
}, },
([[ [{'type': 8, 'timestamp': 0, 'data': { ([[ [{'type': 8, 'timestamp': 0, 'data': {
'n': -10, 'n': -10,
'f': {'_TYPE': v:msgpack_types.binary, '_VAL': ["\n"]}, 'f': {'_TYPE': v:msgpack_types.string, '_VAL': ["\n"]},
}}] ]]):gsub('\n', '') }}] ]]):gsub('\n', '')
) )
sd2strings_eq( sd2strings_eq(
@ -1237,7 +1235,7 @@ describe('autoload/shada.vim', function()
sd2strings_eq({ sd2strings_eq({
'Buffer list with timestamp ' .. epoch .. ':', 'Buffer list with timestamp ' .. epoch .. ':',
' # Unexpected type: map instead of array', ' # Unexpected type: map instead of array',
' = {="a": [10]}', ' = {"a": [10]}',
}, { { type = 9, timestamp = 0, data = { a = { 10 } } } }) }, { { type = 9, timestamp = 0, data = { a = { 10 } } } })
sd2strings_eq({ sd2strings_eq({
'Buffer list with timestamp ' .. epoch .. ':', 'Buffer list with timestamp ' .. epoch .. ':',
@ -1247,7 +1245,7 @@ describe('autoload/shada.vim', function()
sd2strings_eq({ sd2strings_eq({
'Buffer list with timestamp ' .. epoch .. ':', 'Buffer list with timestamp ' .. epoch .. ':',
' # Expected array of maps', ' # Expected array of maps',
' = [{="a": 10}, []]', ' = [{"a": 10}, []]',
}, { { type = 9, timestamp = 0, data = { { a = 10 }, {} } } }) }, { { type = 9, timestamp = 0, data = { { a = 10 }, {} } } })
sd2strings_eq({ sd2strings_eq({
'Buffer list with timestamp ' .. epoch .. ':', 'Buffer list with timestamp ' .. epoch .. ':',
@ -1322,7 +1320,7 @@ describe('autoload/shada.vim', function()
}, },
([[ [{'type': 9, 'timestamp': 0, 'data': [ ([[ [{'type': 9, 'timestamp': 0, 'data': [
{'f': 10}, {'f': 10},
{'f': {'_TYPE': v:msgpack_types.binary, '_VAL': ["\n"]}}, {'f': {'_TYPE': v:msgpack_types.string, '_VAL': ["\n"]}},
]}] ]]):gsub('\n', '') ]}] ]]):gsub('\n', '')
) )
end) end)
@ -1385,7 +1383,7 @@ describe('autoload/shada.vim', function()
}, },
([[ [{'type': 10, 'timestamp': 0, 'data': { ([[ [{'type': 10, 'timestamp': 0, 'data': {
'n': -10, 'n': -10,
'f': {'_TYPE': v:msgpack_types.binary, '_VAL': ["\n"]}, 'f': {'_TYPE': v:msgpack_types.string, '_VAL': ["\n"]},
}}] ]]):gsub('\n', '') }}] ]]):gsub('\n', '')
) )
sd2strings_eq( sd2strings_eq(
@ -1504,7 +1502,7 @@ describe('autoload/shada.vim', function()
}, },
([[ [{'type': 11, 'timestamp': 0, 'data': { ([[ [{'type': 11, 'timestamp': 0, 'data': {
'n': -10, 'n': -10,
'f': {'_TYPE': v:msgpack_types.binary, '_VAL': ["\n"]}, 'f': {'_TYPE': v:msgpack_types.string, '_VAL': ["\n"]},
}}] ]]):gsub('\n', '') }}] ]]):gsub('\n', '')
) )
sd2strings_eq( sd2strings_eq(
@ -1616,7 +1614,7 @@ describe('autoload/shada.vim', function()
timestamp = 0, timestamp = 0,
data = { data = {
c = 'abc', c = 'abc',
f = { '!binary', { 'abc\ndef' } }, f = { '!string', { 'abc\ndef' } },
l = -10, l = -10,
n = -64, n = -64,
rc = '10', rc = '10',
@ -1711,7 +1709,7 @@ describe('autoload/shada.vim', function()
timestamp = 0, timestamp = 0,
data = { data = {
c = 'abc', c = 'abc',
f = { '!binary', { 'abc\ndef' } }, f = { '!string', { 'abc\ndef' } },
l = -10, l = -10,
n = -64, n = -64,
rc = '10', rc = '10',
@ -1892,7 +1890,7 @@ describe('autoload/shada.vim', function()
} } }, { } } }, {
'Replacement string with timestamp ' .. epoch .. ':', 'Replacement string with timestamp ' .. epoch .. ':',
' # Unexpected type: map instead of array', ' # Unexpected type: map instead of array',
' = {="a": [10]}', ' = {"a": [10]}',
}) })
strings2sd_eq({ { type = 3, timestamp = 0, data = {} } }, { strings2sd_eq({ { type = 3, timestamp = 0, data = {} } }, {
'Replacement string with timestamp ' .. epoch .. ':', 'Replacement string with timestamp ' .. epoch .. ':',
@ -1934,7 +1932,7 @@ describe('autoload/shada.vim', function()
} } }, { } } }, {
'History entry with timestamp ' .. epoch .. ':', 'History entry with timestamp ' .. epoch .. ':',
' # Unexpected type: map instead of array', ' # Unexpected type: map instead of array',
' = {="a": [10]}', ' = {"a": [10]}',
}) })
strings2sd_eq({ { type = 4, timestamp = 0, data = {} } }, { strings2sd_eq({ { type = 4, timestamp = 0, data = {} } }, {
'History entry with timestamp ' .. epoch .. ':', 'History entry with timestamp ' .. epoch .. ':',
@ -2184,7 +2182,7 @@ describe('autoload/shada.vim', function()
} } }, { } } }, {
'Variable with timestamp ' .. epoch .. ':', 'Variable with timestamp ' .. epoch .. ':',
' # Unexpected type: map instead of array', ' # Unexpected type: map instead of array',
' = {="a": [10]}', ' = {"a": [10]}',
}) })
strings2sd_eq({ { type = 6, timestamp = 0, data = {} } }, { strings2sd_eq({ { type = 6, timestamp = 0, data = {} } }, {
'Variable with timestamp ' .. epoch .. ':', 'Variable with timestamp ' .. epoch .. ':',
@ -2315,7 +2313,7 @@ describe('autoload/shada.vim', function()
} } }, { } } }, {
'Buffer list with timestamp ' .. epoch .. ':', 'Buffer list with timestamp ' .. epoch .. ':',
' # Unexpected type: map instead of array', ' # Unexpected type: map instead of array',
' = {="a": [10]}', ' = {"a": [10]}',
}) })
strings2sd_eq( strings2sd_eq(
{ { type = 9, timestamp = 0, data = { { { type = 9, timestamp = 0, data = {
@ -2325,7 +2323,7 @@ describe('autoload/shada.vim', function()
{ {
'Buffer list with timestamp ' .. epoch .. ':', 'Buffer list with timestamp ' .. epoch .. ':',
' # Expected array of maps', ' # Expected array of maps',
' = [{="a": 10}, []]', ' = [{"a": 10}, []]',
} }
) )
strings2sd_eq({ { type = 9, timestamp = 0, data = { strings2sd_eq({ { type = 9, timestamp = 0, data = {
@ -2421,7 +2419,7 @@ describe('autoload/shada.vim', function()
timestamp = 0, timestamp = 0,
data = { data = {
{ f = 10 }, { f = 10 },
{ f = { '!binary', { '\n' } } }, { f = { '!string', { '\n' } } },
}, },
}, },
}, { }, {
@ -2955,7 +2953,7 @@ describe('ftplugin/shada.vim', function()
' - :s replacement string "abc\\ndef"', ' - :s replacement string "abc\\ndef"',
' Buffer list with timestamp ' .. epoch .. ':', ' Buffer list with timestamp ' .. epoch .. ':',
' # Expected array of maps', ' # Expected array of maps',
'= [{="a": 10}, []]', '= [{"a": 10}, []]',
' Buffer list with timestamp ' .. epoch .. ':', ' Buffer list with timestamp ' .. epoch .. ':',
' % Key Description Value', ' % Key Description Value',
' # Expected binary string', ' # Expected binary string',
@ -2992,7 +2990,7 @@ describe('ftplugin/shada.vim', function()
' - :s replacement string "abc\\ndef"', ' - :s replacement string "abc\\ndef"',
'Buffer list with timestamp ' .. epoch .. ':', 'Buffer list with timestamp ' .. epoch .. ':',
' # Expected array of maps', ' # Expected array of maps',
' = [{="a": 10}, []]', ' = [{"a": 10}, []]',
'Buffer list with timestamp ' .. epoch .. ':', 'Buffer list with timestamp ' .. epoch .. ':',
' % Key Description Value', ' % Key Description Value',
' # Expected binary string', ' # Expected binary string',
@ -3083,7 +3081,7 @@ describe('syntax/shada.vim', function()
' - :s replacement string DEBUG', ' - :s replacement string DEBUG',
'Buffer list with timestamp ' .. epoch .. ':', 'Buffer list with timestamp ' .. epoch .. ':',
' # Expected array of maps', ' # Expected array of maps',
' = [{="a": +(10)"ac\\0df\\ngi\\"tt\\.", TRUE: FALSE}, [NIL, +(-10)""]]', ' = [{"a": +(10)"ac\\0df\\ngi\\"tt\\.", TRUE: FALSE}, [NIL, +(-10)""]]',
'Buffer list with timestamp ' .. epoch .. ':', 'Buffer list with timestamp ' .. epoch .. ':',
' % Key Description Value', ' % Key Description Value',
'', '',
@ -3119,8 +3117,8 @@ describe('syntax/shada.vim', function()
{1: -} {4::s replacement string} {1:DEBUG} | {1: -} {4::s replacement string} {1:DEBUG} |
{1:Buffer list} with timestamp 1970{1:-}01{1:-}01{1:T}00{1::}00{1::}00: | {1:Buffer list} with timestamp 1970{1:-}01{1:-}01{1:T}00{1::}00{1::}00: |
{4: # Expected array of maps} | {4: # Expected array of maps} |
= {1:[{="}{3:a}{1:":} {1:+(}{5:10}{1:)"}{3:ac}{6:\0}{3:df}{6:\n}{3:gi}{6:\"}{3:tt\.}{1:",} {1:TRUE:} {1:FALSE},} {1:[NIL,} {1:+(}{5:-}| = {1:[{"}{3:a}{1:":} {1:+(}{5:10}{1:)"}{3:ac}{6:\0}{3:df}{6:\n}{3:gi}{6:\"}{3:tt\.}{1:",} {1:TRUE:} {1:FALSE},} {1:[NIL,} {1:+(}{5:-1}|
{5:10}{1:)""]]} | {5:0}{1:)""]]} |
{1:Buffer list} with timestamp 1970{1:-}01{1:-}01{1:T}00{1::}00{1::}00: | {1:Buffer list} with timestamp 1970{1:-}01{1:-}01{1:T}00{1::}00{1::}00: |
{2: % Key Description Value} | {2: % Key Description Value} |
| |
@ -3464,7 +3462,6 @@ describe('syntax/shada.vim', function()
{ { 'ShaDaEntryRawMsgpack' }, ' = ' }, { { 'ShaDaEntryRawMsgpack' }, ' = ' },
{ { 'ShaDaMsgpackArray', 'ShaDaMsgpackArrayBraces' }, '[' }, { { 'ShaDaMsgpackArray', 'ShaDaMsgpackArrayBraces' }, '[' },
{ { 'ShaDaMsgpackArray', 'ShaDaMsgpackMap', 'ShaDaMsgpackMapBraces' }, '{' }, { { 'ShaDaMsgpackArray', 'ShaDaMsgpackMap', 'ShaDaMsgpackMapBraces' }, '{' },
{ { 'ShaDaMsgpackArray', 'ShaDaMsgpackMap', 'ShaDaMsgpackString' }, '=' },
{ {
{ {
'ShaDaMsgpackArray', 'ShaDaMsgpackArray',

View File

@ -502,9 +502,9 @@ describe('json_decode() function', function()
end end
it('parses strings with NUL properly', function() it('parses strings with NUL properly', function()
sp_decode_eq({ _TYPE = 'string', _VAL = { '\n' } }, '"\\u0000"') sp_decode_eq('\000', '"\\u0000"')
sp_decode_eq({ _TYPE = 'string', _VAL = { '\n', '\n' } }, '"\\u0000\\n\\u0000"') sp_decode_eq('\000\n\000', '"\\u0000\\n\\u0000"')
sp_decode_eq({ _TYPE = 'string', _VAL = { '\n«\n' } }, '"\\u0000\\u00AB\\u0000"') sp_decode_eq('\000«\000', '"\\u0000\\u00AB\\u0000"')
end) end)
it('parses dictionaries with duplicate keys to special maps', function() it('parses dictionaries with duplicate keys to special maps', function()
@ -580,14 +580,8 @@ describe('json_decode() function', function()
end) end)
it('parses dictionaries with keys with NUL bytes to special maps', function() it('parses dictionaries with keys with NUL bytes to special maps', function()
sp_decode_eq( sp_decode_eq({ _TYPE = 'map', _VAL = { { 'a\000\nb', 4 } } }, '{"a\\u0000\\nb": 4}')
{ _TYPE = 'map', _VAL = { { { _TYPE = 'string', _VAL = { 'a\n', 'b' } }, 4 } } }, sp_decode_eq({ _TYPE = 'map', _VAL = { { 'a\000\nb\n', 4 } } }, '{"a\\u0000\\nb\\n": 4}')
'{"a\\u0000\\nb": 4}'
)
sp_decode_eq(
{ _TYPE = 'map', _VAL = { { { _TYPE = 'string', _VAL = { 'a\n', 'b', '' } }, 4 } } },
'{"a\\u0000\\nb\\n": 4}'
)
sp_decode_eq({ sp_decode_eq({
_TYPE = 'map', _TYPE = 'map',
_VAL = { _VAL = {
@ -595,10 +589,7 @@ describe('json_decode() function', function()
{ 'a', 1 }, { 'a', 1 },
{ 'c', 4 }, { 'c', 4 },
{ 'd', 2 }, { 'd', 2 },
{ { '\000', 4 },
{ _TYPE = 'string', _VAL = { '\n' } },
4,
},
}, },
}, '{"b": 3, "a": 1, "c": 4, "d": 2, "\\u0000": 4}') }, '{"b": 3, "a": 1, "c": 4, "d": 2, "\\u0000": 4}')
end) end)
@ -738,22 +729,11 @@ describe('json_encode() function', function()
eq('{"\\u0000": 1}', eval('json_encode(todump)')) eq('{"\\u0000": 1}', eval('json_encode(todump)'))
end) end)
it('can dump generic mapping with BIN special key and NUL', function()
command('let todump = {"_TYPE": v:msgpack_types.binary, "_VAL": ["\\n"]}')
command('let todump = {"_TYPE": v:msgpack_types.map, "_VAL": [[todump, 1]]}')
eq('{"\\u0000": 1}', eval('json_encode(todump)'))
end)
it('can dump STR special mapping with NUL and NL', function() it('can dump STR special mapping with NUL and NL', function()
command('let todump = {"_TYPE": v:msgpack_types.string, "_VAL": ["\\n", ""]}') command('let todump = {"_TYPE": v:msgpack_types.string, "_VAL": ["\\n", ""]}')
eq('"\\u0000\\n"', eval('json_encode(todump)')) eq('"\\u0000\\n"', eval('json_encode(todump)'))
end) end)
it('can dump BIN special mapping with NUL and NL', function()
command('let todump = {"_TYPE": v:msgpack_types.binary, "_VAL": ["\\n", ""]}')
eq('"\\u0000\\n"', eval('json_encode(todump)'))
end)
it('cannot dump special ext mapping', function() it('cannot dump special ext mapping', function()
command('let todump = {"_TYPE": v:msgpack_types.ext, "_VAL": [5, ["",""]]}') command('let todump = {"_TYPE": v:msgpack_types.ext, "_VAL": [5, ["",""]]}')
eq('Vim(call):E474: Unable to convert EXT string to JSON', exc_exec('call json_encode(todump)')) eq('Vim(call):E474: Unable to convert EXT string to JSON', exc_exec('call json_encode(todump)'))

View File

@ -371,13 +371,14 @@ describe('msgpack*() functions', function()
eq(1, eval('dumped ==# dumped2')) eq(1, eval('dumped ==# dumped2'))
end) end)
it('can restore and dump STR string with zero byte', function() it('can restore and dump STR string contents with zero byte', function()
command('let dumped = ["\\xA1\\n"]') command('let dumped = ["\\xA1\\n"]')
command('let parsed = msgpackparse(dumped)') command('let parsed = msgpackparse(dumped)')
command('let dumped2 = msgpackdump(parsed)') command('let dumped2 = msgpackdump(parsed)')
eq({ { _TYPE = {}, _VAL = { '\n' } } }, eval('parsed')) eq({ '\000' }, eval('parsed'))
eq(1, eval('parsed[0]._TYPE is v:msgpack_types.string')) eq(eval('v:t_blob'), eval('type(parsed[0])'))
eq(1, eval('dumped ==# dumped2')) -- type is not preserved: prefer BIN for binary contents
eq(0, eval('dumped ==# dumped2'))
end) end)
it('can restore and dump BIN string with NL', function() it('can restore and dump BIN string with NL', function()
@ -428,9 +429,8 @@ describe('msgpackparse() function', function()
parse_eq({ true }, { '\195' }) parse_eq({ true }, { '\195' })
end) end)
it('restores FIXSTR as special dict', function() it('restores FIXSTR as string', function()
parse_eq({ { _TYPE = {}, _VAL = { 'ab' } } }, { '\162ab' }) parse_eq({ 'ab' }, { '\162ab' })
eq(1, eval('g:parsed[0]._TYPE is v:msgpack_types.string'))
end) end)
it('restores BIN 8 as string', function() it('restores BIN 8 as string', function()
@ -442,9 +442,8 @@ describe('msgpackparse() function', function()
eq(1, eval('g:parsed[0]._TYPE is v:msgpack_types.ext')) eq(1, eval('g:parsed[0]._TYPE is v:msgpack_types.ext'))
end) end)
it('restores MAP with BIN key as special dictionary', function() it('restores MAP with BIN key as ordinary dictionary', function()
parse_eq({ { _TYPE = {}, _VAL = { { 'a', '' } } } }, { '\129\196\001a\196\n' }) parse_eq({ { a = '' } }, { '\129\196\001a\196\n' })
eq(1, eval('g:parsed[0]._TYPE is v:msgpack_types.map'))
end) end)
it('restores MAP with duplicate STR keys as special dictionary', function() it('restores MAP with duplicate STR keys as special dictionary', function()
@ -455,14 +454,14 @@ describe('msgpackparse() function', function()
{ {
_TYPE = {}, _TYPE = {},
_VAL = { _VAL = {
{ { _TYPE = {}, _VAL = { 'a' } }, '' }, { 'a', '' },
{ { _TYPE = {}, _VAL = { 'a' } }, '' }, { 'a', '' },
}, },
}, },
}, eval('parsed')) }, eval('parsed'))
eq(1, eval('g:parsed[0]._TYPE is v:msgpack_types.map')) eq(1, eval('g:parsed[0]._TYPE is v:msgpack_types.map'))
eq(1, eval('g:parsed[0]._VAL[0][0]._TYPE is v:msgpack_types.string')) eq(eval('v:t_string'), eval('type(g:parsed[0]._VAL[0][0])'))
eq(1, eval('g:parsed[0]._VAL[1][0]._TYPE is v:msgpack_types.string')) eq(eval('v:t_string'), eval('type(g:parsed[0]._VAL[1][0])'))
end) end)
it('restores MAP with MAP key as special dictionary', function() it('restores MAP with MAP key as special dictionary', function()
@ -802,7 +801,7 @@ describe('msgpackdump() function', function()
it('can dump NULL string', function() it('can dump NULL string', function()
dump_eq({ '\196\n' }, '[$XXX_UNEXISTENT_VAR_XXX]') dump_eq({ '\196\n' }, '[$XXX_UNEXISTENT_VAR_XXX]')
dump_eq({ '\196\n' }, '[{"_TYPE": v:msgpack_types.binary, "_VAL": [$XXX_UNEXISTENT_VAR_XXX]}]') dump_eq({ '\196\n' }, '[v:_null_blob]')
dump_eq({ '\160' }, '[{"_TYPE": v:msgpack_types.string, "_VAL": [$XXX_UNEXISTENT_VAR_XXX]}]') dump_eq({ '\160' }, '[{"_TYPE": v:msgpack_types.string, "_VAL": [$XXX_UNEXISTENT_VAR_XXX]}]')
end) end)