cln-grpc: Add generation of request conversion

This is taking protobuf requests on one side and converting them into
the JSON-RPC requests.
This commit is contained in:
Christian Decker 2022-01-16 16:12:54 +01:00
parent 8d3871d791
commit 5d6e9d6dae
3 changed files with 59 additions and 1 deletions

Binary file not shown.

View File

@ -1,5 +1,5 @@
from msggen.model import Method, CompositeField, Service
from msggen.grpc import GrpcGenerator, GrpcConverterGenerator
from msggen.grpc import GrpcGenerator, GrpcConverterGenerator, GrpcUnconverterGenerator
from msggen.rust import RustGenerator
from pathlib import Path
import subprocess
@ -136,6 +136,9 @@ def gengrpc(service):
fname = repo_root() / "cln-grpc" / "src" / "convert.rs"
dest = open(fname, "w")
GrpcConverterGenerator(dest).generate(service)
GrpcUnconverterGenerator(dest).generate(service)
def genrustjsonrpc(service):
fname = repo_root() / "cln-rpc" / "src" / "model.rs"
dest = open(fname, "w")

View File

@ -249,3 +249,58 @@ class GrpcConverterGenerator:
raw = indent(text, " " * numindent)
self.dest.write(raw)
class GrpcUnconverterGenerator(GrpcConverterGenerator):
"""Generator to generate the conversions from GRPC to JSON-RPC (for requests).
"""
def generate(self, service: Service):
self.generate_requests(service)
def generate_composite(self, prefix, field: CompositeField) -> None:
# First pass: generate any sub-fields before we generate the
# top-level field itself.
for f in field.fields:
if isinstance(f, ArrayField):
self.generate_array(prefix, f)
# And now we can convert the current field:
self.write(f"""\
#[allow(unused_variables)]
impl From<&pb::{field.typename}> for {prefix}::{field.typename} {{
fn from(c: &pb::{field.typename}) -> Self {{
Self {{
""")
for f in field.fields:
name = f.normalized()
if isinstance(f, ArrayField):
self.write(f"{name}: c.{name}.iter().map(|s| s.into()).collect(),\n", numindent=3)
elif isinstance(f, EnumField):
raise ValueError("enums from i32 are not implemented yet")
elif isinstance(f, PrimitiveField):
typ = f.typename + ("?" if not f.required else "")
# We may need to reduce or increase the size of some
# types, or have some conversion such as
# hex-decoding. Also includes the `Some()` that grpc
# requires for non-native types.
rhs = {
'hex': f'hex::encode(&c.{name})',
'txid?': f'c.{name}.clone().map(|v| hex::encode(v))',
'pubkey': f'hex::encode(&c.{name})',
'pubkey?': f'c.{name}.clone().map(|v| hex::encode(v))',
}.get(
typ,
f'c.{name}.clone()' # default to just assignment
)
self.write(f"{name}: {rhs},\n", numindent=3)
self.write(f"""\
}}
}}
}}
""")