1
0
mirror of https://github.com/systemd/systemd.git synced 2025-01-09 01:18:19 +03:00

Merge pull request #33425 from poettering/json-enum-easier

json: make serializing/deserializing systemd-style enums easier in Varlink
This commit is contained in:
Lennart Poettering 2024-06-20 23:05:08 +02:00 committed by GitHub
commit 5b272499dc
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 49 additions and 17 deletions

View File

@ -60,8 +60,16 @@ struct json_variant_foreach_state {
return json_log(variant, flags, SYNTHETIC_ERRNO(EINVAL), "JSON field '%s' is not a string.", strna(n)); \
\
type cc = func(sd_json_variant_string(variant)); \
if (cc < 0) \
return json_log(variant, flags, SYNTHETIC_ERRNO(EINVAL), "Value of JSON field '%s' not recognized.", strna(n)); \
if (cc < 0) { \
/* Maybe this enum is recognizable if we replace "_" (i.e. Varlink syntax) with "-" (how we usually prefer it). */ \
_cleanup_free_ char *z = strreplace(sd_json_variant_string(variant), "_", "-"); \
if (!z) \
return json_log_oom(variant, flags); \
\
cc = func(z); \
if (cc < 0) \
return json_log(variant, flags, SYNTHETIC_ERRNO(EINVAL), "Value of JSON field '%s' not recognized: %s", strna(n), sd_json_variant_string(variant)); \
} \
\
*c = cc; \
return 0; \
@ -130,6 +138,7 @@ enum {
_JSON_BUILD_IOVEC_HEX,
_JSON_BUILD_HW_ADDR,
_JSON_BUILD_STRING_SET,
_JSON_BUILD_STRING_UNDERSCORIFY,
_JSON_BUILD_PAIR_UNSIGNED_NON_ZERO,
_JSON_BUILD_PAIR_FINITE_USEC,
@ -156,6 +165,7 @@ enum {
#define JSON_BUILD_ETHER_ADDR(v) SD_JSON_BUILD_BYTE_ARRAY(((const struct ether_addr*) { v })->ether_addr_octet, sizeof(struct ether_addr))
#define JSON_BUILD_HW_ADDR(v) _JSON_BUILD_HW_ADDR, (const struct hw_addr_data*) { v }
#define JSON_BUILD_STRING_SET(s) _JSON_BUILD_STRING_SET, (Set *) { s }
#define JSON_BUILD_STRING_UNDERSCORIFY(s) _JSON_BUILD_STRING_UNDERSCORIFY, (const char *) { s }
#define JSON_BUILD_PAIR_UNSIGNED_NON_ZERO(name, u) _JSON_BUILD_PAIR_UNSIGNED_NON_ZERO, (const char*) { name }, (uint64_t) { u }
#define JSON_BUILD_PAIR_FINITE_USEC(name, u) _JSON_BUILD_PAIR_FINITE_USEC, (const char*) { name }, (usec_t) { u }

View File

@ -3500,7 +3500,8 @@ _public_ int sd_json_buildv(sd_json_variant **ret, va_list ap) {
switch (command) {
case _SD_JSON_BUILD_STRING: {
case _SD_JSON_BUILD_STRING:
case _JSON_BUILD_STRING_UNDERSCORIFY: {
const char *p;
if (!IN_SET(current->expect, EXPECT_TOPLEVEL, EXPECT_OBJECT_VALUE, EXPECT_ARRAY_ELEMENT)) {
@ -3511,6 +3512,18 @@ _public_ int sd_json_buildv(sd_json_variant **ret, va_list ap) {
p = va_arg(ap, const char *);
if (current->n_suppress == 0) {
_cleanup_free_ char *c = NULL;
if (command == _JSON_BUILD_STRING_UNDERSCORIFY) {
c = strreplace(p, "-", "_");
if (!c) {
r = -ENOMEM;
goto finish;
}
p = c;
}
r = sd_json_variant_new_string(&add, p);
if (r < 0)
goto finish;

View File

@ -306,13 +306,17 @@ TEST(build) {
a = sd_json_variant_unref(a);
b = sd_json_variant_unref(b);
assert_se(sd_json_build(&a, SD_JSON_BUILD_OBJECT(SD_JSON_BUILD_PAIR("one", SD_JSON_BUILD_INTEGER(7)),
SD_JSON_BUILD_PAIR("two", SD_JSON_BUILD_REAL(2.0)),
SD_JSON_BUILD_PAIR("three", SD_JSON_BUILD_INTEGER(0)))) >= 0);
assert_se(sd_json_buildo(&a,
SD_JSON_BUILD_PAIR("one", SD_JSON_BUILD_INTEGER(7)),
SD_JSON_BUILD_PAIR("two", SD_JSON_BUILD_REAL(2.0)),
SD_JSON_BUILD_PAIR("four", JSON_BUILD_STRING_UNDERSCORIFY("foo-bar-baz")),
SD_JSON_BUILD_PAIR("three", SD_JSON_BUILD_INTEGER(0))) >= 0);
assert_se(sd_json_build(&b, SD_JSON_BUILD_OBJECT(SD_JSON_BUILD_PAIR("two", SD_JSON_BUILD_INTEGER(2)),
SD_JSON_BUILD_PAIR("three", SD_JSON_BUILD_REAL(0)),
SD_JSON_BUILD_PAIR("one", SD_JSON_BUILD_REAL(7)))) >= 0);
assert_se(sd_json_buildo(&b,
SD_JSON_BUILD_PAIR("two", SD_JSON_BUILD_INTEGER(2)),
SD_JSON_BUILD_PAIR("four", SD_JSON_BUILD_STRING("foo_bar_baz")),
SD_JSON_BUILD_PAIR("three", SD_JSON_BUILD_REAL(0)),
SD_JSON_BUILD_PAIR("one", SD_JSON_BUILD_REAL(7))) >= 0);
assert_se(sd_json_variant_equal(a, b));
@ -913,37 +917,40 @@ TEST(json_dispatch) {
}
typedef enum mytestenum {
myfoo, mybar, mybaz, _mymax, _myinvalid = -EINVAL,
myfoo, mybar, mybaz, with_some_dashes, _mymax, _myinvalid = -EINVAL,
} mytestenum;
static const char *mytestenum_table[_mymax] = {
[myfoo] = "myfoo",
[mybar] = "mybar",
[mybaz] = "mybaz",
[with_some_dashes] = "with-some-dashes",
};
DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING(mytestenum, mytestenum);
DEFINE_PRIVATE_STRING_TABLE_LOOKUP(mytestenum, mytestenum);
static JSON_DISPATCH_ENUM_DEFINE(dispatch_mytestenum, mytestenum, mytestenum_from_string);
TEST(json_dispatch_enum_define) {
struct data {
mytestenum a, b, c, d;
mytestenum a, b, c, d, e;
} data = {
.a = _myinvalid,
.b = _myinvalid,
.c = _myinvalid,
.d = mybar,
.e = _myinvalid,
};
_cleanup_(sd_json_variant_unrefp) sd_json_variant *j = NULL;
assert_se(sd_json_build(&j, SD_JSON_BUILD_OBJECT(
SD_JSON_BUILD_PAIR("a", SD_JSON_BUILD_STRING("mybaz")),
SD_JSON_BUILD_PAIR("b", SD_JSON_BUILD_STRING("mybar")),
SD_JSON_BUILD_PAIR("c", SD_JSON_BUILD_STRING("myfoo")),
SD_JSON_BUILD_PAIR("d", SD_JSON_BUILD_NULL))) >= 0);
assert_se(sd_json_buildo(&j,
SD_JSON_BUILD_PAIR("a", SD_JSON_BUILD_STRING("mybaz")),
SD_JSON_BUILD_PAIR("b", SD_JSON_BUILD_STRING("mybar")),
SD_JSON_BUILD_PAIR("c", SD_JSON_BUILD_STRING("myfoo")),
SD_JSON_BUILD_PAIR("d", SD_JSON_BUILD_NULL),
SD_JSON_BUILD_PAIR("e", JSON_BUILD_STRING_UNDERSCORIFY(mytestenum_to_string(with_some_dashes)))) >= 0);
assert_se(sd_json_dispatch(j,
(const sd_json_dispatch_field[]) {
@ -951,6 +958,7 @@ TEST(json_dispatch_enum_define) {
{ "b", _SD_JSON_VARIANT_TYPE_INVALID, dispatch_mytestenum, offsetof(struct data, b), 0 },
{ "c", _SD_JSON_VARIANT_TYPE_INVALID, dispatch_mytestenum, offsetof(struct data, c), 0 },
{ "d", _SD_JSON_VARIANT_TYPE_INVALID, dispatch_mytestenum, offsetof(struct data, d), 0 },
{ "e", _SD_JSON_VARIANT_TYPE_INVALID, dispatch_mytestenum, offsetof(struct data, e), 0 },
{},
},
/* flags= */ 0,
@ -960,6 +968,7 @@ TEST(json_dispatch_enum_define) {
assert(data.b == mybar);
assert(data.c == myfoo);
assert(data.d < 0);
assert(data.e == with_some_dashes);
}
TEST(json_dispatch_double) {