9191}
9292
9393
94+ #: Extra wire spellings the C++ client accepts for an enum (C++ enum name -> {spelling: member
95+ #: NAME}). Only spellings peers really send, which the hand-written client always accepted:
96+ #: vgi-go sends ``function_type`` in lower case, and ``table_in_out`` is the legacy name of
97+ #: TABLE. Encoding always writes the canonical member name.
98+ ENUM_WIRE_ALIASES : dict [str , dict [str , str ]] = {
99+ "FunctionType" : {
100+ "scalar" : "SCALAR" ,
101+ "table" : "TABLE" ,
102+ "table_in_out" : "TABLE" ,
103+ "table_buffering" : "TABLE_BUFFERING" ,
104+ "aggregate" : "AGGREGATE" ,
105+ },
106+ }
107+
108+
94109def cpp_name (py_name : str ) -> str :
95110 """The C++ type name for a protocol type's Python name."""
96111 return CPP_NAMES .get (py_name ) or cs .csharp_name (py_name )
@@ -411,6 +426,20 @@ def _render_header(model: _Model, namespace: list[str]) -> str:
411426 f" const std::string &worker_path);\n \n "
412427 )
413428
429+ out .write ("// " + "-" * 76 + "\n // Methods.\n // " + "-" * 76 + "\n \n " )
430+ out .write ("//! One VgiProtocol method's wire schemas (vgi_protocol_schemas.hpp factories).\n " )
431+ out .write ("struct MethodSchemas {\n " )
432+ out .write ("\t const char *method;\n " )
433+ out .write ("\t //! The outer request batch (`<Method>ParamsSchema`).\n " )
434+ out .write ("\t std::shared_ptr<arrow::Schema> params;\n " )
435+ out .write ("\t //! The record a unary result carries (`<Method>ResultSchema`); null when the method\n " )
436+ out .write ("\t //! returns nothing, raw bytes, or is a stream.\n " )
437+ out .write ("\t std::shared_ptr<arrow::Schema> result;\n " )
438+ out .write ("\t //! False for a unary method that returns None.\n " )
439+ out .write ("\t bool returns_value;\n " )
440+ out .write ("};\n " )
441+ out .write ("//! Every VgiProtocol method, by name order.\n " )
442+ out .write ("const std::vector<MethodSchemas> &AllMethodSchemas();\n \n " )
414443 out .write ("// Test hooks (test/cpp/test_protocol_records.cpp).\n " )
415444 out .write ("//! Every record's name with a one-row batch of a default-constructed instance.\n " )
416445 out .write (
@@ -473,6 +502,16 @@ def _render_source(model: _Model, namespace: list[str]) -> str:
473502 out .write (f"std::optional<{ e .name } > { e .name } FromWire(const std::string &wire) {{\n " )
474503 out .write (f"\t for (int16_t i = 0; i < k{ e .name } Count; i++) {{\n " )
475504 out .write (f"\t \t if (wire == k{ e .name } Wire[i]) {{\n \t \t \t return static_cast<{ e .name } >(i);\n \t \t }}\n \t }}\n " )
505+ aliases = ENUM_WIRE_ALIASES .get (e .name , {})
506+ if aliases :
507+ member_ident = {m .wire_name : m .ident for m in e .members }
508+ out .write (
509+ "\t // Accepted spellings beyond the canonical names (vgi.codegen.cpp_records.ENUM_WIRE_ALIASES).\n "
510+ )
511+ for alias , member in sorted (aliases .items ()):
512+ if member not in member_ident :
513+ raise GeneratorError (f"{ e .name } : alias { alias !r} names unknown member { member !r} " )
514+ out .write (f'\t if (wire == "{ alias } ") {{\n \t \t return { e .name } ::{ member_ident [member ]} ;\n \t }}\n ' )
476515 out .write ("\t return std::nullopt;\n }\n \n " )
477516 out .write (f"void ReadValue(const arrow::Array &array, int64_t i, { e .name } &out, const wire::Ctx &ctx) {{\n " )
478517 out .write ("\t std::string s;\n \t wire::ReadValue(array, i, s, ctx);\n " )
@@ -539,6 +578,13 @@ def _render_source(model: _Model, namespace: list[str]) -> str:
539578 )
540579 out .write (f'\t wire::RowReader r(batch, row, "{ r .name } ", worker_path);\n \t Read{ r .name } (r, out);\n }}\n \n ' )
541580
581+ out .write ("const std::vector<MethodSchemas> &AllMethodSchemas() {\n " )
582+ out .write ("\t static const std::vector<MethodSchemas> methods = {\n " )
583+ for method , params , result , returns in _method_rows ():
584+ result_expr = f"{ result } ()" if result else "nullptr"
585+ out .write (f'\t {{"{ method } ", { params } (), { result_expr } , { "true" if returns else "false" } }},\n ' )
586+ out .write ("\t };\n \t return methods;\n }\n \n " )
587+
542588 factories = _factory_names ()
543589 out .write (
544590 "std::vector<std::pair<std::string, std::shared_ptr<arrow::RecordBatch>>> DefaultRecordBatchesForTesting() {\n "
@@ -556,6 +602,29 @@ def _render_source(model: _Model, namespace: list[str]) -> str:
556602 return out .getvalue ()
557603
558604
605+ def _method_rows () -> list [tuple [str , str , str | None , bool ]]:
606+ """(method, params factory, result factory or None, returns a value) for every VgiProtocol method."""
607+ from vgi_rpc .rpc ._types import MethodType , rpc_methods # type: ignore[attr-defined]
608+
609+ from vgi .codegen ._common import _resolve_inner_schema , sanitize_name
610+ from vgi .protocol import VgiProtocol
611+
612+ rows : list [tuple [str , str , str | None , bool ]] = []
613+ methods = rpc_methods (VgiProtocol )
614+ for name in sorted (methods ):
615+ info = methods [name ]
616+ stem = sanitize_name (name )
617+ result = None
618+ if (
619+ info .method_type == MethodType .UNARY
620+ and info .has_return
621+ and _resolve_inner_schema (info .result_type , name ) is not None
622+ ):
623+ result = f"{ stem } ResultSchema"
624+ rows .append ((name , f"{ stem } ParamsSchema" , result , bool (info .has_return )))
625+ return rows
626+
627+
559628def _factory_names () -> set [str ]:
560629 """Stems of the schema factories vgi_protocol_schemas.hpp emits (see cpp_schemas.emit)."""
561630 from vgi .codegen ._common import EXTRA_RESPONSE_TYPES , REQUEST_TYPES , collect_schemas
0 commit comments