qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: Victor Toso <victortoso@redhat.com>
To: qemu-devel@nongnu.org
Cc: "Markus Armbruster" <armbru@redhat.com>,
	"John Snow" <jsnow@redhat.com>,
	"Daniel P . Berrangé" <berrange@redhat.com>,
	"Andrea Bolognani" <abologna@redhat.com>
Subject: [PATCH v4 09/11] qapi: golang: Generate command type
Date: Fri, 14 Feb 2025 21:29:42 +0100	[thread overview]
Message-ID: <20250214202944.69897-10-victortoso@redhat.com> (raw)
In-Reply-To: <20250214202944.69897-1-victortoso@redhat.com>

This patch handles QAPI command types and generates data structures in
Go that handles it.

Note that command's id is part of the first layer of unmarshal, so it
is a member of protocol.go's Message type.

qapi:
 | ##
 | # @add-fd:
 | #
 | # Add a file descriptor, that was passed via SCM rights, to an fd set.
 | #
 | # @fdset-id: The ID of the fd set to add the file descriptor to.
 | #
 | # @opaque: A free-form string that can be used to describe the fd.
 | #
 | # Returns:
 | #     @AddfdInfo
 | #
 | # Errors:
 | #     - If file descriptor was not received, GenericError
 | #     - If @fdset-id is a negative value, GenericError
 | #
 | # .. note:: The list of fd sets is shared by all monitor connections.
 | #
 | # .. note:: If @fdset-id is not specified, a new fd set will be
 | #    created.
 | #
 | # Since: 1.2
 | #
 | # .. qmp-example::
 | #
 | #     -> { "execute": "add-fd", "arguments": { "fdset-id": 1 } }
 | #     <- { "return": { "fdset-id": 1, "fd": 3 } }
 | ##
 | { 'command': 'add-fd',
 |   'data': { '*fdset-id': 'int',
 |             '*opaque': 'str' },
 |   'returns': 'AddfdInfo' }

go:
 | // Add a file descriptor, that was passed via SCM rights, to an fd
 | // set.
 | //
 | // Returns:   @AddfdInfo
 | //
 | // Errors:   - If file descriptor was not received, GenericError   -
 | // If @fdset-id is a negative value, GenericError
 | //
 | // .. note:: The list of fd sets is shared by all monitor connections.
 | // .. note:: If @fdset-id is not specified, a new fd set will be
 | // created.
 | //
 | // Since: 1.2
 | //
 | // .. qmp-example::    -> { "execute": "add-fd", "arguments": {
 | // "fdset-id": 1 } }   <- { "return": { "fdset-id": 1, "fd": 3 } }
 | type AddFdCommand struct {
 | 	// The ID of the fd set to add the file descriptor to.
 | 	FdsetId *int64 `json:"fdset-id,omitempty"`
 | 	// A free-form string that can be used to describe the fd.
 | 	Opaque *string `json:"opaque,omitempty"`
 | }

Signed-off-by: Victor Toso <victortoso@redhat.com>
---
 scripts/qapi/golang/golang.py | 52 +++++++++++++++++++++++++++++++++--
 1 file changed, 50 insertions(+), 2 deletions(-)

diff --git a/scripts/qapi/golang/golang.py b/scripts/qapi/golang/golang.py
index b9a2c47137..a14970fb1f 100644
--- a/scripts/qapi/golang/golang.py
+++ b/scripts/qapi/golang/golang.py
@@ -316,7 +316,7 @@ def qapi_to_go_type_name(name: str, meta: Optional[str] = None) -> str:
     name += "".join(word.title() for word in words[1:])
 
     # Handle specific meta suffix
-    types = ["event"]
+    types = ["event", "command"]
     if meta in types:
         name = name[:-3] if name.endswith("Arg") else name
         name += meta.title().replace(" ", "")
@@ -1009,6 +1009,15 @@ def generate_template_alternate(
     return "\n" + content
 
 
+def generate_template_command(commands: dict[str, Tuple[str, str]]) -> str:
+    content = ""
+    for name in sorted(commands):
+        type_name, gocode = commands[name]
+        content += gocode
+
+    return content
+
+
 def generate_template_event(events: dict[str, Tuple[str, str]]) -> (str, str):
     content = ""
     methods = ""
@@ -1069,6 +1078,7 @@ def __init__(self, _: str):
         # Map each qapi type to the necessary Go imports
         types = {
             "alternate": ["encoding/json", "errors", "fmt"],
+            "command": [],
             "enum": [],
             "event": [],
             "struct": ["encoding/json"],
@@ -1080,6 +1090,7 @@ def __init__(self, _: str):
 
         self.schema: QAPISchema
         self.events: dict[str, Tuple[str, str]] = {}
+        self.commands: dict[str, Tuple[str, str]] = {}
         self.golang_package_name = "qapi"
         self.duplicate = list(gofiles)
         self.enums: dict[str, str] = {}
@@ -1140,6 +1151,8 @@ def visit_end(self) -> None:
         self.types["event"] += evtype
         self.interfaces["event"] += eviface
 
+        self.types["command"] += generate_template_command(self.commands)
+
     def visit_object_type(
         self,
         name: str,
@@ -1286,7 +1299,42 @@ def visit_command(
         allow_preconfig: bool,
         coroutine: bool,
     ) -> None:
-        pass
+        assert name == info.defn_name
+        assert name not in self.commands
+
+        type_name = qapi_to_go_type_name(name, info.defn_meta)
+
+        doc = self.docmap.get(name, None)
+        type_doc, _ = qapi_to_golang_struct_docs(doc)
+
+        content = ""
+        if boxed or not arg_type or not qapi_name_is_object(arg_type.name):
+            args: List[dict[str:str]] = []
+            if arg_type:
+                args.append(
+                    {
+                        "name": f"{arg_type.name}",
+                    }
+                )
+            content += string_to_code(
+                generate_struct_type(type_name, type_doc=type_doc, args=args)
+            )
+        else:
+            assert isinstance(arg_type, QAPISchemaObjectType)
+            content += string_to_code(
+                qapi_to_golang_struct(
+                    self,
+                    name,
+                    arg_type.info,
+                    arg_type.ifcond,
+                    arg_type.features,
+                    arg_type.base,
+                    arg_type.members,
+                    arg_type.branches,
+                )
+            )
+
+        self.commands[name] = (type_name, content)
 
     def visit_event(
         self,
-- 
2.48.1



  parent reply	other threads:[~2025-02-14 20:37 UTC|newest]

Thread overview: 18+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-02-14 20:29 [PATCH v4 00/11] Victor Toso
2025-02-14 20:29 ` [PATCH v4 01/11] qapi: golang: first level unmarshalling type Victor Toso
2025-02-14 20:29 ` [PATCH v4 02/11] qapi: golang: Generate enum type Victor Toso
2025-02-14 20:29 ` [PATCH v4 03/11] qapi: golang: Generate alternate types Victor Toso
2025-02-14 20:29 ` [PATCH v4 04/11] qapi: golang: Generate struct types Victor Toso
2025-02-14 20:29 ` [PATCH v4 05/11] qapi: golang: structs: Address nullable members Victor Toso
2025-02-14 20:29 ` [PATCH v4 06/11] qapi: golang: Generate union type Victor Toso
2025-02-14 20:29 ` [PATCH v4 07/11] qapi: golang: Generate event type Victor Toso
2025-02-14 20:29 ` [PATCH v4 08/11] qapi: golang: Generate Event interface Victor Toso
2025-02-14 20:29 ` Victor Toso [this message]
2025-02-14 20:29 ` [PATCH v4 10/11] qapi: golang: Generate Command sync/async interfaces Victor Toso
2025-02-14 20:29 ` [PATCH v4 11/11] docs: add notes on Golang code generator Victor Toso
2025-02-17 13:13 ` [PATCH v4 00/11] Daniel P. Berrangé
2025-02-20  8:06   ` Markus Armbruster
2025-02-17 14:58 ` Daniel P. Berrangé
2025-02-17 16:52   ` Victor Toso
2025-03-07 11:25     ` Victor Toso
2025-03-07 11:33       ` Daniel P. Berrangé

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20250214202944.69897-10-victortoso@redhat.com \
    --to=victortoso@redhat.com \
    --cc=abologna@redhat.com \
    --cc=armbru@redhat.com \
    --cc=berrange@redhat.com \
    --cc=jsnow@redhat.com \
    --cc=qemu-devel@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).