json-util: add json_dispatch_job_id() dispatcher for job IDs

Job IDs are uint32_t values that are always >= 1 (the manager's ID counter starts at 1 and wraps from UINT32_MAX back to 1, never assigning 0). Add a dedicated dispatch function that validates this constraint, rejecting 0 and treating null as "unset" (0).

Co-developed-by: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Ivan Kruglov
2026-05-18 00:33:47 -07:00
parent f33fa0910d
commit 2d4f2441f5
3 changed files with 85 additions and 0 deletions
+21
View File
@@ -796,6 +796,27 @@ int json_dispatch_access_mode(const char *name, sd_json_variant *variant, sd_jso
return 0;
}
int json_dispatch_job_id(const char *name, sd_json_variant *variant, sd_json_dispatch_flags_t flags, void *userdata) {
uint32_t *id = ASSERT_PTR(userdata);
uint32_t k;
int r;
if (sd_json_variant_is_null(variant)) {
*id = 0;
return 0;
}
r = sd_json_dispatch_uint32(name, variant, flags, &k);
if (r < 0)
return r;
if (k == 0)
return json_log(variant, flags, SYNTHETIC_ERRNO(EINVAL), "JSON field '%s' is not a valid job ID.", strna(name));
*id = k;
return 0;
}
int json_variant_compare(sd_json_variant *a, sd_json_variant *b) {
int r;
+1
View File
@@ -132,6 +132,7 @@ int json_dispatch_ifindex(const char *name, sd_json_variant *variant, sd_json_di
int json_dispatch_log_level(const char *name, sd_json_variant *variant, sd_json_dispatch_flags_t flags, void *userdata);
int json_dispatch_strv_environment(const char *name, sd_json_variant *variant, sd_json_dispatch_flags_t flags, void *userdata);
int json_dispatch_access_mode(const char *name, sd_json_variant *variant, sd_json_dispatch_flags_t flags, void *userdata);
int json_dispatch_job_id(const char *name, sd_json_variant *variant, sd_json_dispatch_flags_t flags, void *userdata);
static inline int json_variant_unbase64_iovec(sd_json_variant *v, struct iovec *ret) {
return sd_json_variant_unbase64(v, ret ? &ret->iov_base : NULL, ret ? &ret->iov_len : NULL);
+63
View File
@@ -1569,6 +1569,69 @@ TEST(access_mode) {
&mm), ERANGE);
}
TEST(job_id) {
_cleanup_(sd_json_variant_unrefp) sd_json_variant *v = NULL;
ASSERT_OK(sd_json_parse("{\"a\": 1, \"b\": 4294967295, \"c\": null}",
/* flags= */ 0,
&v,
/* reterr_line= */ NULL,
/* reterr_column= */ NULL));
struct {
uint32_t a, b, c;
} data = { 99, 99, 99 };
ASSERT_OK(sd_json_dispatch(
v,
(const sd_json_dispatch_field[]) {
{ "a", _SD_JSON_VARIANT_TYPE_INVALID, json_dispatch_job_id, voffsetof(data, a), 0 },
{ "b", _SD_JSON_VARIANT_TYPE_INVALID, json_dispatch_job_id, voffsetof(data, b), 0 },
{ "c", _SD_JSON_VARIANT_TYPE_INVALID, json_dispatch_job_id, voffsetof(data, c), 0 },
{},
},
/* flags= */ 0,
&data));
ASSERT_EQ(data.a, UINT32_C(1));
ASSERT_EQ(data.b, UINT32_MAX);
ASSERT_EQ(data.c, UINT32_C(0));
/* Zero is not a valid job ID */
sd_json_variant_unrefp(&v);
ASSERT_OK(sd_json_parse("{\"a\": 0}",
/* flags= */ 0,
&v,
/* reterr_line= */ NULL,
/* reterr_column= */ NULL));
ASSERT_ERROR(sd_json_dispatch(
v,
(const sd_json_dispatch_field[]) {
{ "a", _SD_JSON_VARIANT_TYPE_INVALID, json_dispatch_job_id, voffsetof(data, a), 0 },
{},
},
/* flags= */ 0,
&data), EINVAL);
/* Negative values are not valid */
sd_json_variant_unrefp(&v);
ASSERT_OK(sd_json_parse("{\"a\": -1}",
/* flags= */ 0,
&v,
/* reterr_line= */ NULL,
/* reterr_column= */ NULL));
ASSERT_ERROR(sd_json_dispatch(
v,
(const sd_json_dispatch_field[]) {
{ "a", _SD_JSON_VARIANT_TYPE_INVALID, json_dispatch_job_id, voffsetof(data, a), 0 },
{},
},
/* flags= */ 0,
&data), EINVAL);
}
static void test_json_variant_compare_one(const char *a, const char *b, int expected) {
int r;