diff --git a/CHANGELOG.md b/CHANGELOG.md index a883165e..eac6de58 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ -# v1.7.6-alpha0 +# v1.7.6-alpha1 * Fixed maximum enumerators per collection, issue #412. +* Added `!` prefix flag to exclude values which evaluate to `false`, pr #413. # v1.7.5 diff --git a/inc/ti/field.t.h b/inc/ti/field.t.h index 7e312bbb..de2db2c0 100644 --- a/inc/ti/field.t.h +++ b/inc/ti/field.t.h @@ -30,6 +30,7 @@ enum TI_FIELD_FLAG_NO_IDS=TI_FLAGS_NO_IDS, /* 32 */ TI_FIELD_FLAG_SKIP_NIL=64, /* skip when prop is nil */ + TI_FIELD_FLAG_SKIP_FALSE=128, /* skip when prop evaluates to false */ }; #define TI_FIELD_MIN_MAX (TI_FIELD_FLAG_MIN_DEEP|TI_FIELD_FLAG_MAX_DEEP) diff --git a/inc/ti/val.h b/inc/ti/val.h index ddf510bd..af6d02fd 100644 --- a/inc/ti/val.h +++ b/inc/ti/val.h @@ -65,7 +65,6 @@ int ti_val_convert_to_int(ti_val_t ** val, ex_t * e); int ti_val_convert_to_float(ti_val_t ** val, ex_t * e); int ti_val_convert_to_array(ti_val_t ** val, ex_t * e); int ti_val_convert_to_set(ti_val_t ** val, ex_t * e); -_Bool ti_val_as_bool(ti_val_t * val); size_t ti_val_get_len(ti_val_t * val); int ti_val_gen_ids(ti_val_t * val); _Bool ti_val_has_ids(ti_val_t * val); diff --git a/inc/ti/val.inline.h b/inc/ti/val.inline.h index 18ee4b3a..48b1f8ec 100644 --- a/inc/ti/val.inline.h +++ b/inc/ti/val.inline.h @@ -36,6 +36,57 @@ static inline int val__str_to_str(ti_val_t ** UNUSED(v), ex_t * UNUSED(e)); static inline int val__no_to_str(ti_val_t ** val, ex_t * e); +static inline _Bool val__as_bool_false(ti_val_t * UNUSED(val)) +{ + return false; +} +static inline _Bool val__as_bool_true(ti_val_t * UNUSED(val)) +{ + return true; +} +static inline _Bool val__as_bool_int(ti_val_t * val) +{ + return !!VINT(val);; +} +static inline _Bool val__as_bool_float(ti_val_t * val) +{ + return !!VFLOAT(val); +} +static inline _Bool val__as_bool_bool(ti_val_t * val) +{ + return VBOOL(val); +} +static inline _Bool val__as_bool_raw(ti_val_t * val) +{ + return !!((ti_raw_t *) val)->n; +} +static inline _Bool val__as_bool_arr(ti_val_t * val) +{ + return !!VARR(val)->n; +} +static inline _Bool val__as_bool_set(ti_val_t * val) +{ + return !!VSET(val)->n; +} +static inline _Bool val__as_bool_thing(ti_val_t * val) +{ + return !!ti_thing_n((ti_thing_t *) val); +} +static inline _Bool val__as_bool_wrap(ti_val_t * val) +{ + return !!ti_thing_n(((ti_wrap_t *) val)->thing); +} +static inline _Bool val__as_bool_room(ti_val_t * val) +{ + return !!((ti_room_t *) val)->id; +} +static inline _Bool val__as_bool_task(ti_val_t * val) +{ + return !!((ti_vtask_t *) val)->run_at; +} +static inline _Bool val__as_bool_member(ti_val_t * val); /* defined later */ + + static inline const char * val__nil_type_str(ti_val_t * UNUSED(val)) { return TI_VAL_NIL_S; @@ -247,6 +298,7 @@ typedef int (*ti_val_to_arr_cb) (ti_val_t ** v, ti_varr_t * varr, ex_t * e); typedef int (*ti_val_to_client_pk_cb) (ti_val_t *, ti_vp_t *, int, int); typedef int (*ti_val_to_store_pk_cb) (ti_val_t *, msgpack_packer * pk); typedef const char * (*ti_val_type_str_cb) (ti_val_t *); +typedef _Bool (*ti_val_as_bool_cb) (ti_val_t *); typedef struct { @@ -256,6 +308,7 @@ typedef struct ti_val_to_client_pk_cb to_client_pk; ti_val_to_store_pk_cb to_store_pk; ti_val_type_str_cb get_type_str; + ti_val_as_bool_cb as_bool; _Bool allowed_as_vtask_arg; /* allowed in the @thingsdb scope */ } ti_val_type_t; @@ -269,6 +322,7 @@ static ti_val_type_t ti_val_type_props[22] = { .to_client_pk = val__nil_to_client_pk, .to_store_pk = val__nil_to_store_pk, .get_type_str = val__nil_type_str, + .as_bool = val__as_bool_false, .allowed_as_vtask_arg = true, }, /* TI_VAL_INT */ @@ -279,6 +333,7 @@ static ti_val_type_t ti_val_type_props[22] = { .to_client_pk = val__int_to_client_pk, .to_store_pk = val__int_to_store_pk, .get_type_str = val__int_type_str, + .as_bool = val__as_bool_int, .allowed_as_vtask_arg = true, }, /* TI_VAL_FLOAT */ @@ -289,6 +344,7 @@ static ti_val_type_t ti_val_type_props[22] = { .to_client_pk = val__float_to_client_pk, .to_store_pk = val__float_to_store_pk, .get_type_str = val__float_type_str, + .as_bool = val__as_bool_float, .allowed_as_vtask_arg = true, }, /* TI_VAL_BOOL */ @@ -299,6 +355,7 @@ static ti_val_type_t ti_val_type_props[22] = { .to_client_pk = val__bool_to_client_pk, .to_store_pk = (ti_val_to_store_pk_cb) ti_vbool_to_pk, .get_type_str = val__bool_type_str, + .as_bool = val__as_bool_bool, .allowed_as_vtask_arg = true, }, /* TI_VAL_DATETIME */ @@ -309,6 +366,7 @@ static ti_val_type_t ti_val_type_props[22] = { .to_client_pk = val__datetime_to_client_pk, .to_store_pk = (ti_val_to_store_pk_cb) ti_datetime_to_store_pk, .get_type_str = val__datetime_type_str, + .as_bool = val__as_bool_true, .allowed_as_vtask_arg = true, }, /* TI_VAL_NAME */ @@ -319,6 +377,7 @@ static ti_val_type_t ti_val_type_props[22] = { .to_client_pk = val__str_to_client_pk, .to_store_pk = (ti_val_to_store_pk_cb) ti_name_to_pk, .get_type_str = val__str_type_str, + .as_bool = val__as_bool_raw, .allowed_as_vtask_arg = true, }, /* TI_VAL_STR */ @@ -329,6 +388,7 @@ static ti_val_type_t ti_val_type_props[22] = { .to_client_pk = val__str_to_client_pk, .to_store_pk = (ti_val_to_store_pk_cb) ti_raw_str_to_pk, .get_type_str = val__str_type_str, + .as_bool = val__as_bool_raw, .allowed_as_vtask_arg = true, }, /* TI_VAL_BYTES */ @@ -339,6 +399,7 @@ static ti_val_type_t ti_val_type_props[22] = { .to_client_pk = val__bytes_to_client_pk, .to_store_pk = (ti_val_to_store_pk_cb) ti_raw_bytes_to_pk, .get_type_str = val__bytes_type_str, + .as_bool = val__as_bool_raw, .allowed_as_vtask_arg = true, }, /* TI_VAL_REGEX */ @@ -349,6 +410,7 @@ static ti_val_type_t ti_val_type_props[22] = { .to_client_pk = val__regex_to_client_pk, .to_store_pk = (ti_val_to_store_pk_cb) ti_regex_to_store_pk, .get_type_str = val__regex_type_str, + .as_bool = val__as_bool_true, .allowed_as_vtask_arg = true, }, /* TI_VAL_THING */ @@ -359,6 +421,7 @@ static ti_val_type_t ti_val_type_props[22] = { .to_client_pk = (ti_val_to_client_pk_cb) ti_thing_to_client_pk, .to_store_pk = (ti_val_to_store_pk_cb) ti_thing_to_store_pk, .get_type_str = val__thing_type_str, + .as_bool = val__as_bool_thing, .allowed_as_vtask_arg = false, }, /* TI_VAL_WRAP */ @@ -369,6 +432,7 @@ static ti_val_type_t ti_val_type_props[22] = { .to_client_pk = (ti_val_to_client_pk_cb) ti_wrap_to_client_pk, .to_store_pk = (ti_val_to_store_pk_cb) ti_wrap_to_store_pk, .get_type_str = val__wrap_type_str, + .as_bool = val__as_bool_wrap, .allowed_as_vtask_arg = false, }, /* TI_VAL_ROOM */ @@ -379,6 +443,7 @@ static ti_val_type_t ti_val_type_props[22] = { .to_client_pk = val__room_to_client_pk, .to_store_pk = (ti_val_to_store_pk_cb) ti_room_to_store_pk, .get_type_str = val__room_type_str, + .as_bool = val__as_bool_room, .allowed_as_vtask_arg = false, }, /* TI_VAL_TASK */ @@ -389,6 +454,7 @@ static ti_val_type_t ti_val_type_props[22] = { .to_client_pk = val__task_to_client_pk, .to_store_pk = (ti_val_to_store_pk_cb) ti_vtask_to_store_pk, .get_type_str = val__task_type_str, + .as_bool = val__as_bool_task, .allowed_as_vtask_arg = false, }, /* TI_VAL_ARR */ @@ -399,6 +465,7 @@ static ti_val_type_t ti_val_type_props[22] = { .to_client_pk = (ti_val_to_client_pk_cb) val__varr_to_client_pk, .to_store_pk = (ti_val_to_store_pk_cb) val__varr_to_store_pk, .get_type_str = val__arr_type_str, + .as_bool = val__as_bool_arr, .allowed_as_vtask_arg = false, }, /* TI_VAL_SET */ @@ -409,6 +476,7 @@ static ti_val_type_t ti_val_type_props[22] = { .to_client_pk = (ti_val_to_client_pk_cb) ti_vset_to_client_pk, .to_store_pk = (ti_val_to_store_pk_cb) ti_vset_to_store_pk, .get_type_str = val__set_type_str, + .as_bool = val__as_bool_set, .allowed_as_vtask_arg = false, }, /* TI_VAL_ERROR */ @@ -419,6 +487,7 @@ static ti_val_type_t ti_val_type_props[22] = { .to_client_pk = val__error_to_client_pk, .to_store_pk = (ti_val_to_store_pk_cb) ti_verror_to_store_pk, .get_type_str = val__error_type_str, + .as_bool = val__as_bool_false, .allowed_as_vtask_arg = false, }, /* TI_VAL_MEMBER */ @@ -429,6 +498,7 @@ static ti_val_type_t ti_val_type_props[22] = { .to_client_pk = (ti_val_to_client_pk_cb) val__member_to_client_pk, .to_store_pk = (ti_val_to_store_pk_cb) val__member_to_store_pk, .get_type_str = val__member_type_str, + .as_bool = val__as_bool_member, .allowed_as_vtask_arg = false, }, /* TI_VAL_MPDATA */ @@ -439,6 +509,7 @@ static ti_val_type_t ti_val_type_props[22] = { .to_client_pk = val__mpdata_to_client_pk, .to_store_pk = (ti_val_to_store_pk_cb) ti_raw_mpdata_to_store_pk, .get_type_str = val__mpdata_type_str, + .as_bool = val__as_bool_raw, .allowed_as_vtask_arg = false, }, /* TI_VAL_CLOSURE */ @@ -449,6 +520,7 @@ static ti_val_type_t ti_val_type_props[22] = { .to_client_pk = val__closure_to_client_pk, .to_store_pk = (ti_val_to_store_pk_cb) ti_closure_to_store_pk, .get_type_str = val__closure_type_str, + .as_bool = val__as_bool_true, .allowed_as_vtask_arg = false, }, /* TI_VAL_FUTURE */ @@ -458,6 +530,7 @@ static ti_val_type_t ti_val_type_props[22] = { .to_arr_cb = val__future_to_arr, .to_client_pk = (ti_val_to_client_pk_cb) val__future_to_client_pk, .get_type_str = val__future_type_str, + .as_bool = val__as_bool_true, .allowed_as_vtask_arg = false, }, /* TI_VAL_MODULE */ @@ -467,6 +540,7 @@ static ti_val_type_t ti_val_type_props[22] = { .to_arr_cb = val__module_to_arr, .to_client_pk = (ti_val_to_client_pk_cb) val__module_to_client_pk, .get_type_str = val__module_type_str, + .as_bool = val__as_bool_true, .allowed_as_vtask_arg = false, }, /* TI_VAL_TEMPLATE */ @@ -478,6 +552,16 @@ static ti_val_type_t ti_val_type_props[22] = { #define ti_val(__val) (&ti_val_type_props[(__val)->tp]) +static inline _Bool val__as_bool_member(ti_val_t * val) +{ + return ti_val(VMEMBER(val))->as_bool(VMEMBER(val)); +} + +static inline _Bool ti_val_as_bool(ti_val_t * val) +{ + return ti_val(val)->as_bool(val); +} + static inline const char * ti_val_str(ti_val_t * val) { return ti_val(val)->get_type_str(val); diff --git a/inc/ti/version.h b/inc/ti/version.h index 42897274..39d5fdef 100644 --- a/inc/ti/version.h +++ b/inc/ti/version.h @@ -25,7 +25,7 @@ * "-rc0" * "" */ -#define TI_VERSION_PRE_RELEASE "-alpha0" +#define TI_VERSION_PRE_RELEASE "-alpha1" #define TI_MAINTAINER \ "Jeroen van der Heijden " diff --git a/itest/Dockerfile b/itest/Dockerfile index e1ee37a4..64e59f5b 100644 --- a/itest/Dockerfile +++ b/itest/Dockerfile @@ -30,4 +30,5 @@ COPY ./memleak.supp /memleak.supp WORKDIR /itest RUN pip install -r requirements.txt ENV THINGSDB_BIN=/thingsdb +ENV THINGSDB_MEMCHECK=1 CMD [ "python", "run_all_tests.py" ] diff --git a/itest/lib/__init__.py b/itest/lib/__init__.py index f715d90c..aa339520 100644 --- a/itest/lib/__init__.py +++ b/itest/lib/__init__.py @@ -1,11 +1,13 @@ import asyncio import logging import random +import subprocess from .testbase import TestBase from .task import Task from .cleanup import cleanup as clean from .cleanup import killall from .node import Node +from .color import Color from .vars import THINGSDB_BIN from .vars import THINGSDB_KEEP_ON_ERROR from .vars import THINGSDB_LOGLEVEL @@ -39,11 +41,27 @@ async def wrapped(self): return wrapper -async def _run_test(test): +async def _run_test(test, hide_version: bool = False): logger = logging.getLogger() logger.setLevel(THINGSDB_LOGLEVEL) task = Task(test.title) + if not hide_version: + try: + result = subprocess.run( + [THINGSDB_BIN, '--version'], + capture_output=True, + text=True, + check=True + ) + out = result.stdout.strip() + lines = out.splitlines() + lines[0] = f' {lines[0]}' + out = '\n'.join(lines[:5]) + print(Color.info(out)) + except Exception: + pass + logging.info(f""" Test Settings: THINGSDB_BIN: {THINGSDB_BIN} @@ -70,10 +88,10 @@ async def _run_test(test): await task.task -def run_test(test: TestBase): - loop = asyncio.get_event_loop() +def run_test(test: TestBase, hide_version: bool = False): + loop = asyncio.new_event_loop() clean() - loop.run_until_complete(_run_test(test)) + loop.run_until_complete(_run_test(test, hide_version)) INT_MIN = -9223372036854775808 diff --git a/itest/run_all_tests.py b/itest/run_all_tests.py index 0ffb18ec..cd7153ef 100755 --- a/itest/run_all_tests.py +++ b/itest/run_all_tests.py @@ -43,10 +43,20 @@ from test_wss import TestWSS +_hide_version = False + + +def hide_version() -> bool: + global _hide_version + current = _hide_version + _hide_version = True + return current + + def no_mem_test(test_class): tmp = vars.THINGSDB_MEMCHECK.copy() vars.THINGSDB_MEMCHECK.clear() - run_test(test_class()) + run_test(test_class(), hide_version=hide_version()) vars.THINGSDB_MEMCHECK[:] = tmp @@ -62,44 +72,44 @@ def no_mem_test(test_class): help='include modules testing') args = parser.parse_args() - run_test(TestAdvanced()) - run_test(TestArguments()) - run_test(TestBackup()) - run_test(TestChanges()) - run_test(TestCollectionFunctions()) - run_test(TestDatetime()) - run_test(TestDict()) + run_test(TestAdvanced(), hide_version=hide_version()) + run_test(TestArguments(), hide_version=hide_version()) + run_test(TestBackup(), hide_version=hide_version()) + run_test(TestChanges(), hide_version=hide_version()) + run_test(TestCollectionFunctions(), hide_version=hide_version()) + run_test(TestDatetime(), hide_version=hide_version()) + run_test(TestDict(), hide_version=hide_version()) if args.doc_test is True: - run_test(TestDocUrl()) - run_test(TestEnum()) - run_test(TestFuture()) - run_test(TestGC()) - run_test(TestHTTPAPI()) - run_test(TestImport()) - run_test(TestIndexSlice()) - run_test(TestMath()) + run_test(TestDocUrl(), hide_version=hide_version()) + run_test(TestEnum(), hide_version=hide_version()) + run_test(TestFuture(), hide_version=hide_version()) + run_test(TestGC(), hide_version=hide_version()) + run_test(TestHTTPAPI(), hide_version=hide_version()) + run_test(TestImport(), hide_version=hide_version()) + run_test(TestIndexSlice(), hide_version=hide_version()) + run_test(TestMath(), hide_version=hide_version()) if args.doc_modules is True: - run_test(TestModules()) - run_test(TestMultiNode()) - run_test(TestNested()) - run_test(TestNodeFunctions()) - run_test(TestNodes()) - run_test(TestOperators()) - run_test(TestProcedures()) - run_test(TestRelations()) - run_test(TestRestriction()) - run_test(TestRoom()) - run_test(TestRoomWSS()) - run_test(TestScopes()) - run_test(TestStatements()) - run_test(TestSyntax()) - run_test(TestTasks()) - run_test(TestThingsDBFunctions()) - run_test(TestType()) - run_test(TestTypes()) - run_test(TestUserAccess()) - run_test(TestVariable()) - run_test(TestWhitelist()) - run_test(TestWS()) - run_test(TestWSS()) - run_test(TestWrap()) + run_test(TestModules(), hide_version=hide_version()) + run_test(TestMultiNode(), hide_version=hide_version()) + run_test(TestNested(), hide_version=hide_version()) + run_test(TestNodeFunctions(), hide_version=hide_version()) + run_test(TestNodes(), hide_version=hide_version()) + run_test(TestOperators(), hide_version=hide_version()) + run_test(TestProcedures(), hide_version=hide_version()) + run_test(TestRelations(), hide_version=hide_version()) + run_test(TestRestriction(), hide_version=hide_version()) + run_test(TestRoom(), hide_version=hide_version()) + run_test(TestRoomWSS(), hide_version=hide_version()) + run_test(TestScopes(), hide_version=hide_version()) + run_test(TestStatements(), hide_version=hide_version()) + run_test(TestSyntax(), hide_version=hide_version()) + run_test(TestTasks(), hide_version=hide_version()) + run_test(TestThingsDBFunctions(), hide_version=hide_version()) + run_test(TestType(), hide_version=hide_version()) + run_test(TestTypes(), hide_version=hide_version()) + run_test(TestUserAccess(), hide_version=hide_version()) + run_test(TestVariable(), hide_version=hide_version()) + run_test(TestWhitelist(), hide_version=hide_version()) + run_test(TestWS(), hide_version=hide_version()) + run_test(TestWSS(), hide_version=hide_version()) + run_test(TestWrap(), hide_version=hide_version()) diff --git a/itest/test_wrap.py b/itest/test_wrap.py index 3a7006dc..645f96fb 100755 --- a/itest/test_wrap.py +++ b/itest/test_wrap.py @@ -362,6 +362,50 @@ async def test_skip_nil(self, client): {'name': 'c'} ]) + async def test_skip_false(self, client): + with self.assertRaisesRegex( + ValueError, + r'invalid declaration for `x` on type `T`; duplicate flags;'): + await client.query("""//ti + set_type('T', {x: '!!int'}) + """) + + await client.query("""//ti + set_type('T', { + name: 'str', + age: 'int?', + other: '[str]?', + }); + set_type('_T', { + name: 'str', + age: '!int?', + other: '!any', + }, true, true); + """) + res = await client.query("""//ti + .orig = [ + T{name: 'a'}, + T{name: 'b', age: 123, other: ['other']}, + {name: 'c', age: nil, other: []}, + {name: 'd', age: 0, other: nil} + ].map_wrap('_T'); + """) + self.assertEqual(res, [ + {'name': 'a'}, + {'name': 'b', 'age': 123, 'other': ['other']}, + {'name': 'c'}, + {'name': 'd'} + ]) + res = await client.query("""//ti + .orig.copy(); + """) + self.assertEqual(res, [ + {'name': 'a'}, + {'name': 'b', 'age': 123, 'other': ['other']}, + {'name': 'c'}, + {'name': 'd'} + ]) + if __name__ == '__main__': run_test(TestWrap()) diff --git a/src/ti/field.c b/src/ti/field.c index 626ced4d..33634108 100644 --- a/src/ti/field.c +++ b/src/ti/field.c @@ -493,6 +493,11 @@ static int field__init(ti_field_t * field, ex_t * e) goto duplicate_flag; field->flags |= TI_FIELD_FLAG_SKIP_NIL; break; + case '!': + if (field->flags & TI_FIELD_FLAG_SKIP_FALSE) + goto duplicate_flag; + field->flags |= TI_FIELD_FLAG_SKIP_FALSE; + break; default: goto done_flags; } @@ -2153,6 +2158,9 @@ _Bool ti_field_maps_to_val(ti_field_t * field, ti_val_t * val) { uint16_t spec = field->spec; + if ((field->flags & TI_FIELD_FLAG_SKIP_FALSE) && !ti_val_as_bool(val)) + return false; + if (ti_val_is_nil(val)) { if (field->flags & TI_FIELD_FLAG_SKIP_NIL) diff --git a/src/ti/map.c b/src/ti/map.c index 869be1f7..a8f82e71 100644 --- a/src/ti/map.c +++ b/src/ti/map.c @@ -17,7 +17,8 @@ ti_map_t * ti_map_new(vec_t * mappings) map->can_skip = false; for (vec_each(mappings, ti_mapping_t, mapping)) { - if (mapping->t_field->flags & TI_FIELD_FLAG_SKIP_NIL) + if (mapping->t_field->flags & ( + TI_FIELD_FLAG_SKIP_NIL|TI_FIELD_FLAG_SKIP_FALSE)) { map->can_skip = true; break; diff --git a/src/ti/val.c b/src/ti/val.c index 8280a89f..832375da 100644 --- a/src/ti/val.c +++ b/src/ti/val.c @@ -1338,57 +1338,6 @@ int ti_val_convert_to_set(ti_val_t ** val, ex_t * e) return e->nr; } -/* - * Can be called on any value type and returns `true` or `false`. - */ -_Bool ti_val_as_bool(ti_val_t * val) -{ - switch ((ti_val_enum) val->tp) - { - case TI_VAL_NIL: - return false; - case TI_VAL_INT: - return !!VINT(val); - case TI_VAL_FLOAT: - return !!VFLOAT(val); - case TI_VAL_BOOL: - return VBOOL(val); - case TI_VAL_DATETIME: - return true; - case TI_VAL_MPDATA: - case TI_VAL_NAME: - case TI_VAL_STR: - case TI_VAL_BYTES: - return !!((ti_raw_t *) val)->n; - case TI_VAL_REGEX: - return true; - case TI_VAL_ARR: - return !!VARR(val)->n; - case TI_VAL_SET: - return !!VSET(val)->n; - case TI_VAL_THING: - return !!ti_thing_n((ti_thing_t *) val); - case TI_VAL_WRAP: - return !!ti_thing_n(((ti_wrap_t *) val)->thing); - case TI_VAL_ROOM: - return ((ti_room_t *) val)->id; - case TI_VAL_TASK: - return ((ti_vtask_t *) val)->run_at; - case TI_VAL_CLOSURE: - case TI_VAL_FUTURE: - case TI_VAL_MODULE: - return true; - case TI_VAL_ERROR: - return false; - case TI_VAL_MEMBER: - return ti_val_as_bool(VMEMBER(val)); - case TI_VAL_TEMPLATE: - assert(0); - } - assert(0); - return false; -} - /* * Can only be called on values which have a length. * Enum types should have been checked on the value they contain. diff --git a/src/ti/wrap.c b/src/ti/wrap.c index d598c2df..eba69e5c 100644 --- a/src/ti/wrap.c +++ b/src/ti/wrap.c @@ -473,6 +473,11 @@ int ti__wrap_field_thing( for (vec_each(map->mappings, ti_mapping_t, mapping)) skip += ( + (mapping->t_field->flags & TI_FIELD_FLAG_SKIP_FALSE) && + !ti_val_as_bool( + VEC_get(thing->items.vec, mapping->f_field->idx) + ) + ) || ( (mapping->t_field->flags & TI_FIELD_FLAG_SKIP_NIL) && ti_val_is_nil( VEC_get(thing->items.vec, mapping->f_field->idx) @@ -491,8 +496,11 @@ int ti__wrap_field_thing( { val = VEC_get(thing->items.vec, mapping->f_field->idx); - if ((mapping->t_field->flags & TI_FIELD_FLAG_SKIP_NIL) && - ti_val_is_nil(val)) + if (( + (mapping->t_field->flags & TI_FIELD_FLAG_SKIP_FALSE) && + !ti_val_as_bool(val)) || ( + (mapping->t_field->flags & TI_FIELD_FLAG_SKIP_NIL) && + ti_val_is_nil(val))) continue; if (mp_pack_strn( @@ -620,8 +628,11 @@ int ti_wrap_copy(ti_wrap_t ** wrap, uint8_t deep) ti_prop_t * p; ti_val_t * val = VEC_get(thing->items.vec, mapping->f_field->idx); - if (ti_val_is_nil(val) && - (mapping->t_field->flags & TI_FIELD_FLAG_SKIP_NIL)) + if (( + (mapping->t_field->flags & TI_FIELD_FLAG_SKIP_FALSE) && + !ti_val_is_bool(val)) || ( + (mapping->t_field->flags & TI_FIELD_FLAG_SKIP_NIL) && + ti_val_is_nil(val))) continue; p = ti_prop_create(mapping->f_field->name, val);