[jsonrpc-glib] message: support NULL in JSONRPC_MESSAGE_PUT_VARIANT()
- From: Christian Hergert <chergert src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [jsonrpc-glib] message: support NULL in JSONRPC_MESSAGE_PUT_VARIANT()
- Date: Tue, 21 Dec 2021 21:08:13 +0000 (UTC)
commit 99898fd95210257f220e0e78446a402bdc6f443d
Author: Christian Hergert <chergert redhat com>
Date: Tue Dec 21 13:08:00 2021 -0800
message: support NULL in JSONRPC_MESSAGE_PUT_VARIANT()
This instead places a <mav nothing> if we get a NULL variant so that the
serialized form looks closer to what is expected (ie: key is there, but no
value to unwrap).
This unblocks https://gitlab.gnome.org/GNOME/gnome-builder/-/merge_requests/433
src/jsonrpc-message.c | 61 ++++++++++++++++++++++++++++++++++++++-------------
tests/test-message.c | 51 ++++++++++++++++++++++++++++++++++++++++++
2 files changed, 97 insertions(+), 15 deletions(-)
---
diff --git a/src/jsonrpc-message.c b/src/jsonrpc-message.c
index 9c236a3..3c58856 100644
--- a/src/jsonrpc-message.c
+++ b/src/jsonrpc-message.c
@@ -90,13 +90,7 @@ jsonrpc_message_build_object (GVariantBuilder *builder,
if (!keyptr || keyptr->magic.bytes[0] == '}')
EXIT;
- if (IS_PUT_VARIANT (keyptr))
- {
- g_variant_builder_add (builder, "v", ((JsonrpcMessagePutVariant *)keyptr)->val);
- EXIT;
- }
-
- g_variant_builder_open (builder, G_VARIANT_TYPE ("{sv}"));
+ g_assert (!IS_PUT_VARIANT (keyptr));
/*
* Either this is a string wrapped in JSONRPC_MESSAGE_PUT_STRING() or
@@ -107,13 +101,13 @@ jsonrpc_message_build_object (GVariantBuilder *builder,
else
key = (const char *)keyptr;
- g_variant_builder_add (builder, "s", key);
-
/*
* Now try to read the value for the key/val pair.
*/
valptr = va_arg (*args, gpointer);
+ g_variant_builder_open (builder, G_VARIANT_TYPE ("{sv}"));
+ g_variant_builder_add (builder, "s", key);
g_variant_builder_open (builder, G_VARIANT_TYPE ("v"));
switch (valptr->magic.bytes[0])
@@ -123,12 +117,32 @@ jsonrpc_message_build_object (GVariantBuilder *builder,
/*
* Peek ahead if a possible GVariant will be injected
*/
- if (IS_PUT_VARIANT ((JsonrpcMessageAny *)param))
- g_variant_builder_open (builder, G_VARIANT_TYPE ("v"));
+ if (IS_PUT_VARIANT ((JsonrpcMessageAny *)param) &&
+ ((JsonrpcMessagePutVariant *)param)->val != NULL)
+ {
+ if (g_variant_is_of_type (((JsonrpcMessagePutVariant *)param)->val, G_VARIANT_TYPE_VARDICT))
+ {
+ g_variant_builder_add (builder, "v", ((JsonrpcMessagePutVariant *)param)->val);
+ }
+ else
+ {
+ g_warning ("Attempt to add variant of type %s but expected a{sv}",
+ g_variant_get_type_string (((JsonrpcMessagePutVariant *)param)->val));
+ g_variant_builder_open (builder, G_VARIANT_TYPE ("mav"));
+ }
+ }
+ else if (IS_PUT_VARIANT ((JsonrpcMessageAny *)param))
+ {
+ g_variant_builder_open (builder, G_VARIANT_TYPE ("mav"));
+ g_variant_builder_close (builder);
+ }
else
- g_variant_builder_open (builder, G_VARIANT_TYPE ("a{sv}"));
- jsonrpc_message_build_object (builder, param, args);
- g_variant_builder_close (builder);
+ {
+ g_variant_builder_open (builder, G_VARIANT_TYPE ("a{sv}"));
+ jsonrpc_message_build_object (builder, param, args);
+ g_variant_builder_close (builder);
+ }
+
break;
case '[':
@@ -379,7 +393,24 @@ jsonrpc_message_parse_object (GVariantDict *dict,
}
}
else if (IS_GET_VARIANT (valptr))
- ret = !!(*((JsonrpcMessageGetVariant *)valptr)->variantptr = g_variant_dict_lookup_value (dict, key,
NULL));
+ {
+ GVariant *lookup = g_variant_dict_lookup_value (dict, key, NULL);
+ GVariant *child = NULL;
+
+ if (lookup != NULL &&
+ g_variant_is_of_type (lookup, G_VARIANT_TYPE_VARIANT) &&
+ g_variant_n_children (lookup) == 1 &&
+ (child = g_variant_get_child_value (lookup, 0)) &&
+ g_variant_is_of_type (child, G_VARIANT_TYPE ("a{sv}")))
+ *((JsonrpcMessageGetVariant *)valptr)->variantptr = g_steal_pointer (&child);
+ else
+ *((JsonrpcMessageGetVariant *)valptr)->variantptr = g_steal_pointer (&lookup);
+
+ ret = !!(*((JsonrpcMessageGetVariant *)valptr)->variantptr);
+
+ g_clear_pointer (&lookup, g_variant_unref);
+ g_clear_pointer (&child, g_variant_unref);
+ }
else if (IS_GET_STRING (valptr))
{
g_autoptr(GVariant) v = g_variant_dict_lookup_value (dict, key, NULL);
diff --git a/tests/test-message.c b/tests/test-message.c
index 7497ee2..0c4fbf4 100644
--- a/tests/test-message.c
+++ b/tests/test-message.c
@@ -299,6 +299,55 @@ test_null_strv (void)
g_assert_null (get_ar_from_v);
}
+static void
+test_putv_null (void)
+{
+ g_autoptr(GVariant) src = NULL;
+ g_autoptr(GVariant) dst = NULL;
+ GVariantDict dict;
+
+ src = JSONRPC_MESSAGE_NEW ("key", "{", JSONRPC_MESSAGE_PUT_VARIANT (NULL), "}");
+ g_assert_nonnull (src);
+
+ g_variant_dict_init (&dict, NULL);
+ g_variant_dict_insert (&dict, "key", "mav", NULL);
+ dst = g_variant_dict_end (&dict);
+
+ g_assert_nonnull (dst);
+ g_assert_true (g_variant_equal (dst, src));
+}
+
+static void
+test_putv_nonnull (void)
+{
+ g_autoptr(GVariant) src = NULL;
+ g_autoptr(GVariant) dst = NULL;
+ g_autoptr(GVariant) child = NULL;
+ g_autoptr(GVariant) child2 = NULL;
+ GVariantDict cdict;
+ GVariantDict dict;
+
+ g_variant_dict_init (&cdict, NULL);
+ g_variant_dict_insert (&cdict, "hello", "s", "world");
+ child = g_variant_take_ref (g_variant_dict_end (&cdict));
+
+ src = JSONRPC_MESSAGE_NEW ("key", "{", JSONRPC_MESSAGE_PUT_VARIANT (child), "}");
+ g_assert_nonnull (src);
+
+ g_variant_dict_init (&dict, NULL);
+ g_variant_dict_insert (&dict, "key", "v", child);
+ dst = g_variant_take_ref (g_variant_dict_end (&dict));
+ g_assert_nonnull (dst);
+
+ g_assert_false (g_variant_is_floating (src));
+ g_assert_false (g_variant_is_floating (dst));
+ g_assert_false (g_variant_is_floating (child));
+ g_assert_true (g_variant_equal (dst, src));
+
+ JSONRPC_MESSAGE_PARSE (src, "key", JSONRPC_MESSAGE_GET_VARIANT (&child2));
+ g_assert_true (g_variant_equal (child, child2));
+}
+
gint
main (gint argc,
gchar *argv[])
@@ -316,5 +365,7 @@ main (gint argc,
g_test_add_func ("/Jsonrpc/Message/null_string", test_null_string);
g_test_add_func ("/Jsonrpc/Message/strv", test_strv);
g_test_add_func ("/Jsonrpc/Message/null_strv", test_null_strv);
+ g_test_add_func ("/Jsonrpc/Message/putv_null", test_putv_null);
+ g_test_add_func ("/Jsonrpc/Message/putv_nonnull", test_putv_nonnull);
return g_test_run ();
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]