From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([2001:4830:134:3::10]:50544) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1YdKZu-0002Up-V9 for qemu-devel@nongnu.org; Wed, 01 Apr 2015 11:29:16 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1YdKZr-0003LZ-Ny for qemu-devel@nongnu.org; Wed, 01 Apr 2015 11:29:14 -0400 Received: from mx1.redhat.com ([209.132.183.28]:36420) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1YdKZr-0003LL-H1 for qemu-devel@nongnu.org; Wed, 01 Apr 2015 11:29:11 -0400 From: Markus Armbruster References: <1427227433-5030-1-git-send-email-eblake@redhat.com> <1427227433-5030-2-git-send-email-eblake@redhat.com> Date: Wed, 01 Apr 2015 17:29:07 +0200 In-Reply-To: <1427227433-5030-2-git-send-email-eblake@redhat.com> (Eric Blake's message of "Tue, 24 Mar 2015 14:03:26 -0600") Message-ID: <874mozq33w.fsf@blackfin.pond.sub.org> MIME-Version: 1.0 Content-Type: text/plain Subject: Re: [Qemu-devel] [PATCH v5 01/28] qapi: Document type-safety considerations List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: Eric Blake Cc: kwolf@redhat.com, lcapitulino@redhat.com, famz@redhat.com, qemu-devel@nongnu.org, wenchaoqemu@gmail.com Eric Blake writes: [...] > === Union types === > > -Union types are used to let the user choose between several different data > -types. A union type is defined using a dictionary as explained in the > -following paragraphs. > +Usage: { 'union': 'str', 'data': 'dict' } > +or: { 'union': 'str', 'data': 'dict', 'base': 'complex-type-name', > + 'discriminator': 'enum-member-of-base' } > +or: { 'union': 'str', 'data': 'dict', 'discriminator': {} } > > +Union types are used to let the user choose between several different > +data types. There are three flavors: simple (no discriminator), flat > +(a base type is mandatory, and discriminator is the name of an enum > +field within that base type), and anonymous (discriminator is an > +empty dictionary). A union type is defined using a data dictionary as > +explained in the following paragraphs. > > -A simple union type defines a mapping from discriminator values to data types > -like in this example: > +A simple union type defines a mapping from automatic discriminator > +values to data types like in this example: > > { 'type': 'FileOptions', 'data': { 'filename': 'str' } } > { 'type': 'Qcow2Options', > @@ -132,10 +273,17 @@ specified data type corresponding to the discriminator value: > { "type": "qcow2", "data" : { "backing-file": "/some/place/my-image", > "lazy-refcounts": true } } > > +Additionally, an implicit C enum NameKind is created, corresponding to > +the union Name, for accessing the various branches of the union. No > +branch of the union can be named 'max', as this would collide with the > +implicit enum. > > -A union definition can specify a complex type as its base. In this case, the > -fields of the complex type are included as top-level fields of the union > -dictionary in the QMP wire format. An example definition is: > + > +A flat union definition specifies a complex type as its base, and > +avoids nesting on the wire. In this case, the fields of the complex > +type are included as top-level fields of the union dictionary in the > +QMP wire format, and the 'discriminator' field must be the name of an > +enum-typed member of the base type. An example definition is: > > { 'type': 'BlockdevCommonOptions', 'data': { 'readonly': 'bool' } } > { 'union': 'BlockdevOptions', 'base': 'BlockdevCommonOptions', 'data': { 'raw': 'RawOptions', 'qcow2': 'Qcow2Options' } } Where's 'discriminator'? And it looks like this on the wire: { "type": "qcow2", "readonly": false, > "data" : { "backing-file": "/some/place/my-image", > "lazy-refcounts": true } } Is the variant part really wrapped in "data"? Here's the real schema's flat union BlockdevOptions: { 'union': 'BlockdevOptions', 'base': 'BlockdevOptionsBase', 'discriminator': 'driver', 'data': { 'qcow2': 'BlockdevOptionsQcow2', 'raw': 'BlockdevOptionsGenericFormat', [many more omitted...] } } Same thing, just different names. One the wire, it looks like { "driver": "qcow2", "id": "disk1", "file": { "driver": "file", "filename": "tmp.qcow2" } } > > - > -Flat union types avoid the nesting on the wire. They are used whenever a > -specific field of the base type is declared as the discriminator ('type' is > -then no longer generated). The discriminator must be of enumeration type. > -The above example can then be modified as follows: > +Notice that in a flat union, a 'type' field is no longer generated, > +and the keys of the 'data' dictionary must match the valid values for > +the discriminator (although not necessarily in the same order). The > +above example for simple unions can be modified to a flat union as > +follows: > > { 'enum': 'BlockdevDriver', 'data': [ 'raw', 'qcow2' ] } > { 'type': 'BlockdevCommonOptions', 'data': { 'driver': 'BlockdevDriver', 'readonly': 'bool' } } { 'union': 'BlockdevOptions', 'base': 'BlockdevCommonOptions', 'discriminator': 'driver', 'data': { 'raw': 'RawOptions', 'qcow2': 'Qcow2Options' } } Resulting in this JSON object: { "driver": "qcow2", "readonly": false, "backing-file": "/some/place/my-image", "lazy-refcounts": true } This actually matches the above example with the "data" wrapper peeled off the variant part. [...]