예제 #1
0
static gboolean
type_allows_choices (const GVariantType *type)
{
  if (g_variant_type_is_array (type) ||
      g_variant_type_is_maybe (type))
    return type_allows_choices (g_variant_type_element (type));

  return g_variant_type_equal (type, G_VARIANT_TYPE_STRING);
}
예제 #2
0
GVariant* js_to_dbus(JSContextRef ctx, const JSValueRef jsvalue, const GVariantType* sig, JSValueRef *exception)
{
    if (g_variant_type_is_array(sig)) {
        GVariantBuilder builder;
        g_variant_builder_init(&builder, sig);
        JSPropertyNameArrayRef array = JSObjectCopyPropertyNames(ctx, (JSObjectRef)jsvalue);

        const GVariantType* child_sig = g_variant_type_element(sig);

        if (g_variant_type_is_dict_entry(child_sig)) {

            const GVariantType* key_sig = g_variant_type_first(child_sig);
            const GVariantType* value_sig = g_variant_type_next(key_sig);
            for (size_t i=0; i < JSPropertyNameArrayGetCount(array); i++) {
                if (filter_function_child(ctx, jsvalue, i)) continue;

                g_variant_builder_open(&builder, child_sig);
                JSValueRef key = JSValueMakeString(ctx, JSPropertyNameArrayGetNameAtIndex(array, i));
                JSValueRef value = JSObjectGetPropertyAtIndex(ctx, (JSObjectRef)jsvalue, i, NULL);
                g_variant_builder_add_value(&builder, js_to_dbus(ctx, key, key_sig, exception));
                g_variant_builder_add_value(&builder, js_to_dbus(ctx, value, value_sig, exception));
                g_variant_builder_close(&builder);
            }
            return g_variant_builder_end(&builder);

	} else {
	    GVariantBuilder builder;
	    g_variant_builder_init(&builder, sig);
	    JSPropertyNameArrayRef array = JSObjectCopyPropertyNames(ctx, (JSObjectRef)jsvalue);
	    const GVariantType* child_sig = g_variant_type_element(sig);
	    for (size_t i=0; i < JSPropertyNameArrayGetCount(array); i++) {
		if (filter_array_child(ctx, array, i)) continue;
		g_variant_builder_add_value(&builder, js_to_dbus(ctx, JSObjectGetPropertyAtIndex(ctx, (JSObjectRef)jsvalue, i, NULL), child_sig, exception));
	    }
	    JSPropertyNameArrayRelease(array);
	    return g_variant_builder_end(&builder);
	}
    } else if (g_variant_type_is_tuple(sig)) {
	    GVariantBuilder builder;
	    g_variant_builder_init(&builder, sig);
	    JSPropertyNameArrayRef array = JSObjectCopyPropertyNames(ctx, (JSObjectRef)jsvalue);
	    const GVariantType* current_sig = g_variant_type_first(sig);
            for (size_t i=0; i < JSPropertyNameArrayGetCount(array); i++) {
                if (filter_array_child(ctx, array, i)) continue;
                g_variant_builder_add_value(&builder, js_to_dbus(ctx, JSObjectGetPropertyAtIndex(ctx, (JSObjectRef)jsvalue, i, NULL), current_sig, exception));
		current_sig = g_variant_type_next(current_sig);
            }
            JSPropertyNameArrayRelease(array);
            return g_variant_builder_end(&builder);
    } else {
        switch (g_variant_type_peek_string(sig)[0]) {
            case 'y':
                return g_variant_new_byte(JSValueToNumber(ctx, jsvalue, exception));
            case 'n':
                return g_variant_new_int16(JSValueToNumber(ctx, jsvalue, exception));
            case 'q':
                return g_variant_new_uint16(JSValueToNumber(ctx, jsvalue, exception));
            case 'i':
                return g_variant_new_int32(JSValueToNumber(ctx, jsvalue, exception));
            case 'u':
                return g_variant_new_uint32(JSValueToNumber(ctx, jsvalue, exception));
            case 'x':
                return g_variant_new_int64(JSValueToNumber(ctx, jsvalue, exception));
            case 't':
                return g_variant_new_uint64(JSValueToNumber(ctx, jsvalue, exception));
            case 'd':
                return g_variant_new_double(JSValueToNumber(ctx, jsvalue, exception));
            case 'h':
                return g_variant_new_handle(JSValueToNumber(ctx, jsvalue, exception));
            case 'b':
                return g_variant_new_boolean(JSValueToBoolean(ctx, jsvalue));
            case 's':
                {
                    char* v = jsvalue_to_cstr(ctx, jsvalue);
                    GVariant* r = g_variant_new_string(v);
                    g_free(v);
                    return r;
                }
            case 'v':
                {
                    //TODO:
                    /*g_variant_new_variant()*/
                    g_assert_not_reached();
                }
        }
    }
    g_assert_not_reached();
}
예제 #3
0
JSValueRef dbus_to_js(JSContextRef ctx, GVariant *dbus)
{
    JSValueRef jsvalue = NULL;
    GVariantClass type = g_variant_classify(dbus);
    switch (type) {
        case G_VARIANT_CLASS_STRING:
        case G_VARIANT_CLASS_OBJECT_PATH:
        case G_VARIANT_CLASS_SIGNATURE:
            {
                JSStringRef js_string = JSStringCreateWithUTF8CString(g_variant_get_string(dbus, NULL));
                jsvalue = JSValueMakeString(ctx, js_string);
                JSStringRelease(js_string);
                return jsvalue;
            }
        case G_VARIANT_CLASS_BYTE:
            return JSValueMakeNumber(ctx, g_variant_get_byte(dbus));
        case G_VARIANT_CLASS_DOUBLE:
            return JSValueMakeNumber(ctx, g_variant_get_double(dbus));
        case G_VARIANT_CLASS_INT16:
            return JSValueMakeNumber(ctx, g_variant_get_int16(dbus));
        case G_VARIANT_CLASS_UINT16:
            return JSValueMakeNumber(ctx, g_variant_get_uint16(dbus));
        case G_VARIANT_CLASS_INT32:
            return JSValueMakeNumber(ctx, g_variant_get_int32(dbus));
        case G_VARIANT_CLASS_UINT32:
            return JSValueMakeNumber(ctx, g_variant_get_uint32(dbus));
        case G_VARIANT_CLASS_INT64:
            return JSValueMakeNumber(ctx, g_variant_get_int64(dbus));
        case G_VARIANT_CLASS_UINT64:
            return JSValueMakeNumber(ctx, g_variant_get_uint64(dbus));
        case G_VARIANT_CLASS_BOOLEAN:
            return JSValueMakeBoolean(ctx, g_variant_get_boolean(dbus));
        case G_VARIANT_CLASS_HANDLE:
            g_warning("didn't support FD type");
            return JSValueMakeNumber(ctx, g_variant_get_uint32(dbus));
        case G_VARIANT_CLASS_VARIANT:
            {
                GVariant* v = g_variant_get_variant(dbus);
                jsvalue = dbus_to_js(ctx, v);
                g_variant_unref(v);
                return jsvalue;
            }

        case G_VARIANT_CLASS_DICT_ENTRY:
            /*g_assert_not_reached();*/
            break;

        case G_VARIANT_CLASS_ARRAY:
            {
                if (g_variant_type_is_dict_entry(g_variant_type_element(g_variant_get_type(dbus)))) {
                    jsvalue = JSObjectMake(ctx, NULL, NULL);
                    for (size_t i=0; i<g_variant_n_children(dbus); i++) {
                        GVariant *dic = g_variant_get_child_value(dbus, i);
                        GVariant *key= g_variant_get_child_value (dic, 0);
                        GVariant *value = g_variant_get_child_value (dic, 1);

                        JSValueRef js_key = dbus_to_js(ctx, key);
                        JSValueRef js_value = dbus_to_js(ctx, value);

                        JSStringRef key_str = JSValueToStringCopy(ctx, js_key, NULL);
                        JSObjectSetProperty(ctx, (JSObjectRef)jsvalue, key_str, js_value, 0, NULL);
                        JSStringRelease(key_str);

                        g_variant_unref(key);
                        g_variant_unref(value);
                        g_variant_unref(dic);
                    }
                    return jsvalue;
                } else {
                    int n = g_variant_n_children(dbus);
                    JSValueRef *args = g_new(JSValueRef, n);
                    for (int i=0; i < n; i++) {
                        GVariant* v = g_variant_get_child_value(dbus, i);
                        args[i] = dbus_to_js(ctx, v);
                        g_variant_unref(v);
                    }
                    jsvalue = JSObjectMakeArray(ctx, n, args, NULL);
                    g_free(args);
                    return jsvalue;
                }
            }
        case G_VARIANT_CLASS_TUPLE:
            {
                int n = g_variant_n_children(dbus);
                jsvalue = JSObjectMakeArray(ctx, 0, NULL, NULL);
                for (int i=0; i < n; i++) {
                    GVariant* v = g_variant_get_child_value(dbus, i);
                    JSObjectSetPropertyAtIndex(ctx, (JSObjectRef)jsvalue, i, dbus_to_js(ctx, v), NULL);
                    g_variant_unref(v);
                }
                return jsvalue;
            }
        case G_VARIANT_CLASS_MAYBE:
            g_assert_not_reached();
    }
    g_warning("didn't support signature type:%c", type);
    return JSValueMakeUndefined(ctx);
}
예제 #4
0
static JsonBuilder *
_json_builder_add_gvariant (JsonBuilder *builder,
                            GVariant *value)
{
  g_return_val_if_fail (JSON_IS_BUILDER (builder), builder);

  g_variant_ref_sink (value);

  switch (g_variant_classify (value))
    {
    case G_VARIANT_CLASS_BOOLEAN:
      json_builder_add_boolean_value (builder, g_variant_get_boolean (value));
      break;

    case G_VARIANT_CLASS_BYTE:
      json_builder_add_int_value (builder, g_variant_get_byte (value));
      break;

    case G_VARIANT_CLASS_INT16:
      json_builder_add_int_value (builder, g_variant_get_int16 (value));
      break;

    case G_VARIANT_CLASS_UINT16:
      json_builder_add_int_value (builder, g_variant_get_uint16 (value));
      break;

    case G_VARIANT_CLASS_INT32:
      json_builder_add_int_value (builder, g_variant_get_int32 (value));
      break;

    case G_VARIANT_CLASS_UINT32:
      json_builder_add_int_value (builder, g_variant_get_uint32 (value));
      break;

    case G_VARIANT_CLASS_INT64:
      json_builder_add_int_value (builder, g_variant_get_int64 (value));
      break;

    case G_VARIANT_CLASS_UINT64:
      json_builder_add_int_value (builder, g_variant_get_uint64 (value));
      break;

    case G_VARIANT_CLASS_HANDLE:
      json_builder_add_int_value (builder, g_variant_get_handle (value));
      break;

    case G_VARIANT_CLASS_DOUBLE:
      json_builder_add_double_value (builder, g_variant_get_double (value));
      break;

    case G_VARIANT_CLASS_STRING:      /* explicit fall-through */
    case G_VARIANT_CLASS_OBJECT_PATH: /* explicit fall-through */
    case G_VARIANT_CLASS_SIGNATURE:
      json_builder_add_string_value (builder, g_variant_get_string (value, NULL));
      break;

     /* TODO: */
    case G_VARIANT_CLASS_VARIANT:
      {
        GVariant *child;
        child = g_variant_get_variant (value);
        _json_builder_add_gvariant (builder, child);
        g_variant_unref (child);
      }
      break;

    case G_VARIANT_CLASS_MAYBE:
      g_assert_not_reached ();
      break;

    case G_VARIANT_CLASS_ARRAY:
      {
        const GVariantType *type;
        const GVariantType *element_type;

        type = g_variant_get_type (value);
        element_type = g_variant_type_element (type);
        if (g_variant_type_is_dict_entry (element_type))
          {
            GVariantIter iter;
            GVariant *child;

            json_builder_begin_object (builder);

            g_variant_iter_init (&iter, value);
            while ((child = g_variant_iter_next_value (&iter)) != NULL)
              {
                _json_builder_add_gvariant (builder, child);
                g_variant_unref (child);
              }

            json_builder_end_object (builder);
          }
        else
          {
            GVariantIter iter;
            GVariant *child;

            json_builder_begin_array (builder);

            g_variant_iter_init (&iter, value);
            while ((child = g_variant_iter_next_value (&iter)) != NULL)
              {
                _json_builder_add_gvariant (builder, child);
                g_variant_unref (child);
              }

            json_builder_end_array (builder);
          }
      }
      break;

    case G_VARIANT_CLASS_TUPLE:
      {
        GVariantIter iter;
        GVariant *child;

        json_builder_begin_array (builder);

        g_variant_iter_init (&iter, value);
        while ((child = g_variant_iter_next_value (&iter)) != NULL)
          {
            _json_builder_add_gvariant (builder, child);
            g_variant_unref (child);
          }

        json_builder_end_array (builder);
      }
      break;

    case G_VARIANT_CLASS_DICT_ENTRY:
      {
        GVariant *dict_key;
        GVariant *dict_value;
        gchar *dict_key_string;

        dict_key = g_variant_get_child_value (value, 0);
        dict_value = g_variant_get_child_value (value, 1);

        if (g_variant_is_of_type (dict_key, G_VARIANT_TYPE("s")))
          dict_key_string = g_variant_dup_string (dict_key, NULL);
        else
          dict_key_string = g_variant_print (dict_key, FALSE);

        json_builder_set_member_name (builder, dict_key_string);
        _json_builder_add_gvariant (builder, dict_value);
        g_free (dict_key_string);

        g_variant_unref (dict_key);
        g_variant_unref (dict_value);
      }
      break;
    }

  g_variant_unref (value);

  return builder;
}
예제 #5
0
static GConfValue *
gconf_settings_backend_gvariant_to_gconf_value (GVariant *value)
{
  const GVariantType *type;
  GConfValue         *gconf_value = NULL;

  type = g_variant_get_type (value);
  if (g_variant_type_is_basic (type) &&
      !g_variant_type_equal (type, G_VARIANT_TYPE_BASIC))
    gconf_value = gconf_settings_backend_simple_gvariant_to_gconf_value (value, type);
  else if (g_variant_type_is_array (type))
    {
      const GVariantType *array_type;
      array_type = g_variant_type_element (type);

      if (g_variant_type_is_basic (array_type) &&
          !g_variant_type_equal (array_type, G_VARIANT_TYPE_BASIC))
        {
          GConfValueType  value_type;
          int             i;
          GSList        *list = NULL;

          for (i = 0; i < g_variant_n_children (value); i++)
            {
              GConfValue *l;

              l = gconf_settings_backend_simple_gvariant_to_gconf_value (g_variant_get_child_value (value, i),
                                                                         array_type);
              list = g_slist_prepend (list, l);
            }

          list = g_slist_reverse (list);

          value_type = gconf_settings_backend_simple_gvariant_type_to_gconf_value_type (array_type);
          gconf_value = gconf_value_new (GCONF_VALUE_LIST);
          gconf_value_set_list_type (gconf_value, value_type);
          gconf_value_set_list (gconf_value, list);

          g_slist_foreach (list, (GFunc) gconf_value_free, NULL);
          g_slist_free (list);
        }
    }
  else if (g_variant_type_is_tuple (type) &&
            g_variant_type_n_items (type) == 2)
    {
      const GVariantType *first_type;
      const GVariantType *second_type;

      first_type = g_variant_type_first (type);
      second_type = g_variant_type_next (first_type);

      if (g_variant_type_is_basic (first_type) &&
          !g_variant_type_equal (first_type, G_VARIANT_TYPE_BASIC) &&
          g_variant_type_is_basic (second_type) &&
          !g_variant_type_equal (second_type, G_VARIANT_TYPE_BASIC))
        {
          GConfValue *car;
          GConfValue *cdr;

          gconf_value = gconf_value_new (GCONF_VALUE_PAIR);

          car = gconf_settings_backend_simple_gvariant_to_gconf_value (g_variant_get_child_value (value, 0), first_type);
          cdr = gconf_settings_backend_simple_gvariant_to_gconf_value (g_variant_get_child_value (value, 1), second_type);

          if (car)
            gconf_value_set_car_nocopy (gconf_value, car);
          if (cdr)
            gconf_value_set_cdr_nocopy (gconf_value, cdr);

          if (car == NULL || cdr == NULL)
            {
              gconf_value_free (gconf_value);
              gconf_value = NULL;
            }
        }
    }

  return gconf_value;
}
예제 #6
0
static GVariant *
gconf_settings_backend_gconf_value_to_gvariant (GConfValue         *gconf_value,
                                                const GVariantType *expected_type)
{
  switch (gconf_value->type)
    {
    case GCONF_VALUE_STRING:
    case GCONF_VALUE_INT:
    case GCONF_VALUE_FLOAT:
    case GCONF_VALUE_BOOL:
      if (!gconf_settings_backend_simple_gconf_value_type_is_compatible (gconf_value->type, expected_type))
        return NULL;
      return gconf_settings_backend_simple_gconf_value_type_to_gvariant (gconf_value, expected_type);
    case GCONF_VALUE_LIST:
      {
        GConfValueType      list_type;
        const GVariantType *array_type;
        GSList             *list;
        GPtrArray          *array;
        GVariant           *result;

        if (!g_variant_type_is_array (expected_type))
          return NULL;

        list_type = gconf_value_get_list_type (gconf_value);
        array_type = g_variant_type_element (expected_type);
        if (!gconf_settings_backend_simple_gconf_value_type_is_compatible (list_type, array_type))
          return NULL;

        array = g_ptr_array_new ();
        for (list = gconf_value_get_list (gconf_value); list != NULL; list = list->next)
          {
            GVariant *variant;
            variant = gconf_settings_backend_simple_gconf_value_type_to_gvariant (list->data, array_type);
            g_ptr_array_add (array, variant);
          }

        result = g_variant_new_array (array_type, (GVariant **) array->pdata, array->len);
        g_ptr_array_free (array, TRUE);

        return result;
      }
      break;
    case GCONF_VALUE_PAIR:
      {
        GConfValue         *car;
        GConfValue         *cdr;
        const GVariantType *first_type;
        const GVariantType *second_type;
        GVariant           *tuple[2];
        GVariant           *result;

        if (!g_variant_type_is_tuple (expected_type) ||
            g_variant_type_n_items (expected_type) != 2)
          return NULL;

        car = gconf_value_get_car (gconf_value);
        cdr = gconf_value_get_cdr (gconf_value);
        first_type = g_variant_type_first (expected_type);
        second_type = g_variant_type_next (first_type);

        if (!gconf_settings_backend_simple_gconf_value_type_is_compatible (car->type, first_type) ||
            !gconf_settings_backend_simple_gconf_value_type_is_compatible (cdr->type, second_type))
          return NULL;

        tuple[0] = gconf_settings_backend_simple_gconf_value_type_to_gvariant (car, first_type);
        tuple[1] = gconf_settings_backend_simple_gconf_value_type_to_gvariant (cdr, second_type);

        result = g_variant_new_tuple (tuple, 2);
        return result;
      }
      break;
    default:
      return NULL;
    }

  g_assert_not_reached ();

  return NULL;
}
예제 #7
0
static void
build_json (JsonBuilder *builder,
            GVariant *value)
{
  const GVariantType *type;
  const GVariantType *element_type;

  g_variant_ref_sink (value);

  switch (g_variant_classify (value))
    {
    case G_VARIANT_CLASS_BOOLEAN:
      json_builder_add_boolean_value (builder, g_variant_get_boolean (value));
      break;

    case G_VARIANT_CLASS_BYTE:
      json_builder_add_int_value (builder, g_variant_get_byte (value));
      break;

    case G_VARIANT_CLASS_INT16:
      json_builder_add_int_value (builder, g_variant_get_int16 (value));
      break;

    case G_VARIANT_CLASS_UINT16:
      json_builder_add_int_value (builder, g_variant_get_uint16 (value));
      break;

    case G_VARIANT_CLASS_INT32:
      json_builder_add_int_value (builder, g_variant_get_int32 (value));
      break;

    case G_VARIANT_CLASS_UINT32:
      json_builder_add_int_value (builder, g_variant_get_uint32 (value));
      break;

    case G_VARIANT_CLASS_INT64:
      json_builder_add_int_value (builder, g_variant_get_int64 (value));
      break;

    case G_VARIANT_CLASS_UINT64:
      json_builder_add_int_value (builder, g_variant_get_uint64 (value));
      break;

    case G_VARIANT_CLASS_HANDLE:
      json_builder_add_int_value (builder, g_variant_get_handle (value));
      break;

    case G_VARIANT_CLASS_DOUBLE:
      json_builder_add_double_value (builder, g_variant_get_double (value));
      break;

    case G_VARIANT_CLASS_STRING:      /* explicit fall-through */
    case G_VARIANT_CLASS_OBJECT_PATH: /* explicit fall-through */
    case G_VARIANT_CLASS_SIGNATURE:
      {
        /* HACK: We can't use json_builder_add_string_value here since
           it turns empty strings into 'null' values inside arrays.

           https://bugzilla.gnome.org/show_bug.cgi?id=730803
        */
        JsonNode *string_element = json_node_alloc ();
        json_node_init_string (string_element, g_variant_get_string (value, NULL));
        json_builder_add_value (builder, string_element);
      }
      break;

    case G_VARIANT_CLASS_VARIANT:
      build_json_variant (builder, value);
      break;

    case G_VARIANT_CLASS_ARRAY:
      type = g_variant_get_type (value);
      element_type = g_variant_type_element (type);
      if (g_variant_type_is_dict_entry (element_type))
        build_json_dictionary (builder, element_type, value);
      else
        build_json_array_or_tuple (builder, value);
      break;

    case G_VARIANT_CLASS_TUPLE:
      build_json_array_or_tuple (builder, value);
      break;

    case G_VARIANT_CLASS_DICT_ENTRY:
    case G_VARIANT_CLASS_MAYBE:
    default:
      g_return_if_reached ();
      break;
    }

  g_variant_unref (value);
}
예제 #8
0
static GVariant *
parse_json (JsonNode *node,
            const GVariantType *type,
            GError **error)
{
  const GVariantType *element_type;
  const gchar *str;

  if (!g_variant_type_is_definite (type))
    {
      g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_DATA,
                   "Indefinite type '%.*s' is not supported",
                   (int)g_variant_type_get_string_length (type),
                   g_variant_type_peek_string (type));
      return NULL;
    }

  if (g_variant_type_is_basic (type))
    {
      if (g_variant_type_equal (type, G_VARIANT_TYPE_BOOLEAN))
        {
          if (check_type (node, JSON_NODE_VALUE, G_TYPE_BOOLEAN, error))
            return g_variant_new_boolean (json_node_get_boolean (node));
        }
      else if (g_variant_type_equal (type, G_VARIANT_TYPE_BYTE))
        {
          if (check_type (node, JSON_NODE_VALUE, G_TYPE_INT64, error))
            return g_variant_new_byte (json_node_get_int (node));
        }
      else if (g_variant_type_equal (type, G_VARIANT_TYPE_INT16))
        {
          if (check_type (node, JSON_NODE_VALUE, G_TYPE_INT64, error))
            return g_variant_new_int16 (json_node_get_int (node));
        }
      else if (g_variant_type_equal (type, G_VARIANT_TYPE_UINT16))
        {
          if (check_type (node, JSON_NODE_VALUE, G_TYPE_INT64, error))
            return g_variant_new_uint16 (json_node_get_int (node));
        }
      else if (g_variant_type_equal (type, G_VARIANT_TYPE_INT32))
        {
          if (check_type (node, JSON_NODE_VALUE, G_TYPE_INT64, error))
            return g_variant_new_int32 (json_node_get_int (node));
        }
      else if (g_variant_type_equal (type, G_VARIANT_TYPE_UINT32))
        {
          if (check_type (node, JSON_NODE_VALUE, G_TYPE_INT64, error))
            return g_variant_new_uint32 (json_node_get_int (node));
        }
      else if (g_variant_type_equal (type, G_VARIANT_TYPE_INT64))
        {
          if (check_type (node, JSON_NODE_VALUE, G_TYPE_INT64, error))
            return g_variant_new_int64 (json_node_get_int (node));
        }
      else if (g_variant_type_equal (type, G_VARIANT_TYPE_UINT64))
        {
          if (check_type (node, JSON_NODE_VALUE, G_TYPE_INT64, error))
            return g_variant_new_uint64 (json_node_get_int (node));
        }
      else if (g_variant_type_equal (type, G_VARIANT_TYPE_DOUBLE))
        {
          if (check_type (node, JSON_NODE_VALUE, G_TYPE_INT64, NULL))
            return g_variant_new_double (json_node_get_int (node));
          else if (check_type (node, JSON_NODE_VALUE, G_TYPE_DOUBLE, error))
            return g_variant_new_double (json_node_get_double (node));
        }
      else if (g_variant_type_equal (type, G_VARIANT_TYPE_STRING))
        {
          if (check_type (node, JSON_NODE_VALUE, G_TYPE_STRING, error))
            return g_variant_new_string (json_node_get_string (node));
        }
      else if (g_variant_type_equal (type, G_VARIANT_TYPE_OBJECT_PATH))
        {
          if (check_type (node, JSON_NODE_VALUE, G_TYPE_STRING, error))
            {
              str = json_node_get_string (node);
              if (g_variant_is_object_path (str))
                return g_variant_new_object_path (str);
              else
                {
                  g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_DATA,
                               "Invalid object path '%s'", str);
                  return NULL;
                }
            }
        }
      else if (g_variant_type_equal (type, G_VARIANT_TYPE_SIGNATURE))
        {
          if (check_type (node, JSON_NODE_VALUE, G_TYPE_STRING, error))
            {
              str = json_node_get_string (node);
              if (g_variant_is_signature (str))
                return g_variant_new_signature (str);
              else
                {
                  g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_DATA,
                               "Invalid signature '%s'", str);
                  return NULL;
                }
            }
        }
      else
        {
          parse_not_supported (type, error);
        }
    }
  else if (g_variant_type_is_variant (type))
    {
      return parse_json_variant (node, error);
    }
  else if (g_variant_type_is_array (type))
    {
      element_type = g_variant_type_element (type);
      if (g_variant_type_is_dict_entry (element_type))
        return parse_json_dictionary (node, element_type, error);
      else
        return parse_json_array (node, element_type, error);
    }
  else if (g_variant_type_is_tuple (type))
    {
      return parse_json_tuple (node, g_variant_type_first (type), error);
    }
  else
    {
      parse_not_supported (type, error);
    }

  return NULL;
}