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