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 07/11] qapi: golang: Generate event type
Date: Fri, 14 Feb 2025 21:29:40 +0100	[thread overview]
Message-ID: <20250214202944.69897-8-victortoso@redhat.com> (raw)
In-Reply-To: <20250214202944.69897-1-victortoso@redhat.com>

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

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

Example:
qapi:
 | ##
 | # @MEMORY_DEVICE_SIZE_CHANGE:
 | #
 | # Emitted when the size of a memory device changes.  Only emitted for
 | # memory devices that can actually change the size (e.g., virtio-mem
 | # due to guest action).
 | #
 | # @id: device's ID
 | #
 | # @size: the new size of memory that the device provides
 | #
 | # @qom-path: path to the device object in the QOM tree (since 6.2)
 | #
 | # .. note:: This event is rate-limited.
 | #
 | # Since: 5.1
 | #
 | # .. qmp-example::
 | #
 | #     <- { "event": "MEMORY_DEVICE_SIZE_CHANGE",
 | #          "data": { "id": "vm0", "size": 1073741824,
 | #                    "qom-path": "/machine/unattached/device[2]" },
 | #          "timestamp": { "seconds": 1588168529, "microseconds": 201316 } }
 | ##
 | { 'event': 'MEMORY_DEVICE_SIZE_CHANGE',
 |   'data': { '*id': 'str', 'size': 'size', 'qom-path' : 'str'} }

go:
 | // Emitted when the size of a memory device changes.  Only emitted for
 | // memory devices that can actually change the size (e.g., virtio-mem
 | // due to guest action).
 | //
 | // .. note:: This event is rate-limited.
 | //
 | // Since: 5.1
 | //
 | // .. qmp-example::    <- { "event": "MEMORY_DEVICE_SIZE_CHANGE",
 | // "data": { "id": "vm0", "size": 1073741824,           "qom-path":
 | // "/machine/unattached/device[2]" },      "timestamp": { "seconds":
 | // 1588168529, "microseconds": 201316 } }
 | type MemoryDeviceSizeChangeEvent struct {
 | 	// device's ID
 | 	Id *string `json:"id,omitempty"`
 | 	// the new size of memory that the device provides
 | 	Size uint64 `json:"size"`
 | 	// path to the device object in the QOM tree (since 6.2)
 | 	QomPath string `json:"qom-path"`
 | }

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

diff --git a/scripts/qapi/golang/golang.py b/scripts/qapi/golang/golang.py
index 59e9b1f644..63d55ca950 100644
--- a/scripts/qapi/golang/golang.py
+++ b/scripts/qapi/golang/golang.py
@@ -291,7 +291,7 @@ def qapi_to_field_name_enum(name: str) -> str:
     return name.title().replace("-", "")
 
 
-def qapi_to_go_type_name(name: str) -> str:
+def qapi_to_go_type_name(name: str, meta: Optional[str] = None) -> str:
     # We want to keep CamelCase for Golang types. We want to avoid removing
     # already set CameCase names while fixing uppercase ones, eg:
     # 1) q_obj_SocketAddress_base -> SocketAddressBase
@@ -309,6 +309,12 @@ def qapi_to_go_type_name(name: str) -> str:
 
     name += "".join(word.title() for word in words[1:])
 
+    # Handle specific meta suffix
+    types = ["event"]
+    if meta in types:
+        name = name[:-3] if name.endswith("Arg") else name
+        name += meta.title().replace(" ", "")
+
     return name
 
 
@@ -818,7 +824,8 @@ def qapi_to_golang_struct(
                 fields.append(field)
                 with_nullable = True if nullable else with_nullable
 
-    type_name = qapi_to_go_type_name(name)
+    type_name = qapi_to_go_type_name(name, info.defn_meta)
+
     content = string_to_code(
         generate_struct_type(
             type_name, type_doc=type_doc, args=fields, indent=indent
@@ -996,6 +1003,15 @@ def generate_template_alternate(
     return "\n" + content
 
 
+def generate_template_event(events: dict[str, Tuple[str, str]]) -> str:
+    content = ""
+    for name in sorted(events):
+        type_name, gocode = events[name]
+        content += gocode
+
+    return content
+
+
 def generate_content_from_dict(data: dict[str, str]) -> str:
     content = ""
 
@@ -1045,11 +1061,13 @@ def __init__(self, _: str):
         types = {
             "alternate": ["encoding/json", "errors", "fmt"],
             "enum": [],
+            "event": [],
             "struct": ["encoding/json"],
             "union": ["encoding/json", "errors", "fmt"],
         }
 
         self.schema: QAPISchema
+        self.events: dict[str, Tuple[str, str]] = {}
         self.golang_package_name = "qapi"
         self.duplicate = list(gofiles)
         self.enums: dict[str, str] = {}
@@ -1096,6 +1114,7 @@ def visit_end(self) -> None:
         self.types["alternate"] += generate_content_from_dict(self.alternates)
         self.types["struct"] += generate_content_from_dict(self.structs)
         self.types["union"] += generate_content_from_dict(self.unions)
+        self.types["event"] += generate_template_event(self.events)
 
     def visit_object_type(
         self,
@@ -1254,7 +1273,31 @@ def visit_event(
         arg_type: Optional[QAPISchemaObjectType],
         boxed: bool,
     ) -> None:
-        pass
+        assert name == info.defn_name
+        assert name not in self.events
+        type_name = qapi_to_go_type_name(name, info.defn_meta)
+
+        if isinstance(arg_type, QAPISchemaObjectType):
+            content = string_to_code(
+                qapi_to_golang_struct(
+                    self,
+                    name,
+                    info,
+                    arg_type.ifcond,
+                    arg_type.features,
+                    arg_type.base,
+                    arg_type.members,
+                    arg_type.branches,
+                )
+            )
+        else:
+            doc = self.docmap.get(name, None)
+            type_doc, _ = qapi_to_golang_struct_docs(doc)
+            content = string_to_code(
+                generate_struct_type(type_name, type_doc=type_doc)
+            )
+
+        self.events[name] = (type_name, content)
 
     def write(self, outdir: str) -> None:
         godir = "go"
-- 
2.48.1



  parent reply	other threads:[~2025-02-14 20:31 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 ` Victor Toso [this message]
2025-02-14 20:29 ` [PATCH v4 08/11] qapi: golang: Generate Event interface Victor Toso
2025-02-14 20:29 ` [PATCH v4 09/11] qapi: golang: Generate command type Victor Toso
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-8-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).