From patchwork Sun Apr 5 04:07:46 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Eric Blake X-Patchwork-Id: 458201 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 8AC39140134 for ; Sun, 5 Apr 2015 14:15:35 +1000 (AEST) Received: from localhost ([::1]:35035 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Yeby9-0003ci-9k for incoming@patchwork.ozlabs.org; Sun, 05 Apr 2015 00:15:33 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:42800) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1YebrE-00008P-Ax for qemu-devel@nongnu.org; Sun, 05 Apr 2015 00:08:27 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1YebrC-0002qL-K5 for qemu-devel@nongnu.org; Sun, 05 Apr 2015 00:08:24 -0400 Received: from mx1.redhat.com ([209.132.183.28]:34941) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1YebrC-0002qD-8o for qemu-devel@nongnu.org; Sun, 05 Apr 2015 00:08:22 -0400 Received: from int-mx11.intmail.prod.int.phx2.redhat.com (int-mx11.intmail.prod.int.phx2.redhat.com [10.5.11.24]) by mx1.redhat.com (Postfix) with ESMTPS id 08F25319B5C for ; Sun, 5 Apr 2015 04:08:22 +0000 (UTC) Received: from red.redhat.com (ovpn-113-46.phx2.redhat.com [10.3.113.46]) by int-mx11.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id t35489wB008523; Sun, 5 Apr 2015 00:08:21 -0400 From: Eric Blake To: qemu-devel@nongnu.org Date: Sat, 4 Apr 2015 22:07:46 -0600 Message-Id: <1428206887-7921-16-git-send-email-eblake@redhat.com> In-Reply-To: <1428206887-7921-1-git-send-email-eblake@redhat.com> References: <1428206887-7921-1-git-send-email-eblake@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.24 X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x X-Received-From: 209.132.183.28 Cc: kwolf@redhat.com, berto@igalia.co, armbru@redhat.com Subject: [Qemu-devel] [PATCH v6 15/36] qapi: Document new 'alternate' meta-type X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org The next patch will quit special-casing "'union':'Foo', 'discriminator':{}" and instead use "'alternate':'Foo'". Separating docs from implementation makes it easier to focus on wording without holding up code. In particular, making alternate a separate type makes for a nice type hierarchy: /-------- meta-type ------\ / | \ simple types alternate complex types | | | | built-in enum type(struct) union | \ / / \ numeric string simple flat A later patch will then clean up 'type' vs. 'struct' confusion. Signed-off-by: Eric Blake Reviewed-by: Markus Armbruster --- v6: split from v5:12/28, merge in 2/5 of doc followup series, as well as Markus' wording improvements --- docs/qapi-code-gen.txt | 57 +++++++++++++++++++++++++++++++------------------- 1 file changed, 36 insertions(+), 21 deletions(-) diff --git a/docs/qapi-code-gen.txt b/docs/qapi-code-gen.txt index 585cb24..8a76cc1 100644 --- a/docs/qapi-code-gen.txt +++ b/docs/qapi-code-gen.txt @@ -84,11 +84,12 @@ the definition of complex structs that can have mutually recursive types, and allows for indefinite nesting of QMP that satisfies the schema. A type name should not be defined more than once. -There are six top-level expressions recognized by the parser: -'include', 'command', 'type', 'enum', 'union', and 'event'. There are -several built-in types, such as 'int' and 'str'; additionally, the -top-level expressions can define complex types, enumeration types, and -several flavors of union types. The 'command' and 'event' expressions +There are seven top-level expressions recognized by the parser: +'include', 'command', 'type', 'enum', 'union', 'alternate', and +'event'. There are several groups of types: simple types (a number of +built-in types, such as 'int' and 'str'; as well as enumerations), +complex types (structs and two flavors of unions), and alternate types +(a choice between other types). The 'command' and 'event' expressions can refer to existing types by name, or list an anonymous type as a dictionary. Listing a type name inside an array refers to a single-dimension array of that type; multi-dimension arrays are not @@ -260,14 +261,12 @@ open-coding the field to be type 'str'. Usage: { 'union': STRING, 'data': DICT } or: { 'union': STRING, 'data': DICT, 'base': COMPLEX-TYPE-NAME, 'discriminator': ENUM-MEMBER-OF-BASE } -or: { 'union': STRING, 'data': DICT, 'discriminator': {} } Union types are used to let the user choose between several different -variants for an object. There are three flavors: simple (no -discriminator or base), flat (both base and discriminator are -strings), and anonymous (discriminator is an empty dictionary). A -union type is defined using a data dictionary as explained in the -following paragraphs. +variants for an object. There are two flavors: simple (no +discriminator or base), flat (both discriminator and base). A union +type is defined using a data dictionary as explained in the following +paragraphs. A simple union type defines a mapping from automatic discriminator values to data types like in this example: @@ -349,20 +348,36 @@ is identical on the wire to: 'data': { 'one': 'Branch1', 'two': 'Branch2' } } -The final flavor of unions is an anonymous union. While the other two -union types are always passed as a JSON object in the wire format, an -anonymous union instead allows the direct use of different types in -its place. 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. +=== Alternate types === - { 'union': 'BlockRef', - 'discriminator': {}, +Usage: { 'alternate': STRING, 'data': DICT } + +An alternate type is one that allows a choice between two or more JSON +data types (string, integer, number, or object, but currently not +array) on the wire. The definition is similar to a simple union type, +where each branch of the union names a QAPI type. For example: + + { 'alternate': 'BlockRef', 'data': { 'definition': 'BlockdevOptions', 'reference': 'str' } } -This example allows using both of the following example objects: +Just like for a simple union, an implicit C enum 'NameKind' is created +to enumerate the branches for the alternate 'Name'. + +Unlike a union, the discriminator string is never passed on the wire +for QMP. Instead, the value's JSON type serves as an implicit +discriminator, which in turn means that an alternate can only express +a choice between types represented differently in JSON. If a branch +is typed as the 'bool' built-in, the alternate accepts true and false; +if it is typed as any of the various numeric built-ins, it accepts a +JSON number; if it is typed as a 'str' built-in or named enum type, it +accepts a JSON string; and if it is typed as a complex type (struct or +union), it accepts a JSON object. Two different complex types, for +instance, aren't permitted, because both are represented as a JSON +object. + +The example alternate declaration above allows using both of the +following example objects: { "file": "my_existing_block_device_id" } { "file": { "driver": "file",