Commit 69dd62df authored by Kevin Wolf's avatar Kevin Wolf
Browse files

qapi: Anonymous unions



The discriminator for anonymous unions is the data type. This allows to
have a union type that allows both of these:

    { 'file': 'my_existing_block_device_id' }
    { 'file': { 'filename': '/tmp/mydisk.qcow2', 'read-only': true } }

Unions like this are specified in the schema with an empty dict as
discriminator. For this example you could take:

    { 'union': 'BlockRef',
      'discriminator': {},
      'data': { 'definition': 'BlockOptions',
                'reference': 'str' } }
    { 'type': 'ExampleObject',
      'data: { 'file': 'BlockRef' } }

Signed-off-by: default avatarKevin Wolf <kwolf@redhat.com>
Reviewed-by: default avatarEric Blake <eblake@redhat.com>
parent ea66c6d8
Loading
Loading
Loading
Loading
+25 −0
Original line number Diff line number Diff line
@@ -125,6 +125,31 @@ Resulting in this JSON object:
   "lazy-refcounts": true }


A special type of unions are anonymous unions. They don't form a dictionary in
the wire format but allow the direct use of different types in their place. As
they aren't structured, they don't have any explicit discriminator but use
the (QObject) data type of their value as an implicit discriminator. This means
that they are restricted to using only one discriminator value per QObject
type. For example, you cannot have two different complex types in an anonymous
union, or two different integer types.

Anonymous unions are declared using an empty dictionary as their discriminator.
The discriminator values never appear on the wire, they are only used in the
generated C code. Anonymous unions cannot have a base type.

 { 'union': 'BlockRef',
   'discriminator': {},
   'data': { 'definition': 'BlockdevOptions',
             'reference': 'str' } }

This example allows using both of the following example objects:

 { "file": "my_existing_block_device_id" }
 { "file": { "driver": "file",
             "readonly": false,
             'filename': "/tmp/mydisk.qcow2" } }


=== Commands ===

Commands are defined by using a list containing three members.  The first
+1 −0
Original line number Diff line number Diff line
@@ -44,6 +44,7 @@ typedef enum {
    QTYPE_QFLOAT,
    QTYPE_QBOOL,
    QTYPE_QERROR,
    QTYPE_MAX,
} qtype_code;

struct QObject;
+2 −0
Original line number Diff line number Diff line
@@ -32,6 +32,8 @@ struct Visitor

    void (*type_enum)(Visitor *v, int *obj, const char *strings[],
                      const char *kind, const char *name, Error **errp);
    void (*get_next_type)(Visitor *v, int *kind, const int *qobjects,
                          const char *name, Error **errp);

    void (*type_int)(Visitor *v, int64_t *obj, const char *name, Error **errp);
    void (*type_bool)(Visitor *v, bool *obj, const char *name, Error **errp);
+3 −0
Original line number Diff line number Diff line
@@ -13,6 +13,7 @@
#ifndef QAPI_VISITOR_CORE_H
#define QAPI_VISITOR_CORE_H

#include "qapi/qmp/qobject.h"
#include "qapi/error.h"
#include <stdlib.h>

@@ -42,6 +43,8 @@ void visit_end_list(Visitor *v, Error **errp);
void visit_start_optional(Visitor *v, bool *present, const char *name,
                          Error **errp);
void visit_end_optional(Visitor *v, Error **errp);
void visit_get_next_type(Visitor *v, int *obj, const int *qtypes,
                         const char *name, Error **errp);
void visit_type_enum(Visitor *v, int *obj, const char *strings[],
                     const char *kind, const char *name, Error **errp);
void visit_type_int(Visitor *v, int64_t *obj, const char *name, Error **errp);
+9 −0
Original line number Diff line number Diff line
@@ -12,6 +12,7 @@
 */

#include "qemu-common.h"
#include "qapi/qmp/qobject.h"
#include "qapi/qmp/qerror.h"
#include "qapi/visitor.h"
#include "qapi/visitor-impl.h"
@@ -98,6 +99,14 @@ void visit_end_optional(Visitor *v, Error **errp)
    }
}

void visit_get_next_type(Visitor *v, int *obj, const int *qtypes,
                         const char *name, Error **errp)
{
    if (!error_is_set(errp) && v->get_next_type) {
        v->get_next_type(v, obj, qtypes, name, errp);
    }
}

void visit_type_enum(Visitor *v, int *obj, const char *strings[],
                     const char *kind, const char *name, Error **errp)
{
Loading