Clean up protocol code generators

This commit is contained in:
Přemysl Eric Janouch 2022-09-29 16:39:26 +02:00
parent 941ee2f10c
commit 86278c154c
Signed by: p
GPG Key ID: A0420B94F92B9493
6 changed files with 67 additions and 43 deletions

View File

@ -164,6 +164,7 @@ add_custom_command (OUTPUT xC-proto.c
COMMAND env LC_ALL=C awk
-f ${PROJECT_SOURCE_DIR}/xC-gen-proto.awk
-f ${PROJECT_SOURCE_DIR}/xC-gen-proto-c.awk
-v PrefixCamel=Relay
${PROJECT_SOURCE_DIR}/xC-proto > xC-proto.c
DEPENDS
${PROJECT_SOURCE_DIR}/xC-gen-proto.awk

View File

@ -62,8 +62,8 @@ function codegen_begin() {
"\t\t%s = !!v;\n" \
"\t}\n"
print "// Code generated from " FILENAME ". DO NOT EDIT."
print "// This file directly depends on liberty.c, but doesn't include it."
print ""
print "static bool"
print "proto_string_serialize(const struct str *s, struct str *w) {"
@ -73,7 +73,6 @@ function codegen_begin() {
print "\tstr_append_str(w, s);"
print "\treturn true;"
print "}"
print ""
print "static bool"
print "proto_string_deserialize(struct str *s, struct msg_unpacker *r) {"

View File

@ -70,7 +70,12 @@ function define_uint(size, shortname, gotype) {
"\t}\n"
}
function codegen_begin() {
# Currently two outputs cannot coexist within the same package.
function codegen_private(name) {
return "proto" name
}
function codegen_begin( funcname) {
define_sint("8")
define_sint("16")
define_sint("32")
@ -79,32 +84,17 @@ function codegen_begin() {
define_uint("16")
define_uint("32")
define_uint("64")
define_internal("bool", "bool")
CodegenAppendJSON["bool"] = \
"\tb = strconv.AppendBool(b, %s)\n"
CodegenSerialize["bool"] = \
"\tif %s {\n" \
"\t\tdata = append(data, 1)\n" \
"\t} else {\n" \
"\t\tdata = append(data, 0)\n" \
"\t}\n"
CodegenDeserialize["bool"] = \
"\tif data, ok = protoConsumeBoolFrom(data, &%s); !ok {\n" \
"\t\treturn nil, ok\n" \
"\t}\n"
define_internal("string", "string")
CodegenSerialize["string"] = \
"\tif data, ok = protoAppendStringTo(data, %s); !ok {\n" \
"\t\treturn nil, ok\n" \
"\t}\n"
CodegenDeserialize["string"] = \
"\tif data, ok = protoConsumeStringFrom(data, &%s); !ok {\n" \
"\t\treturn nil, ok\n" \
"\t}\n"
print "package main"
# Cater to "go generate", for what it's worth.
CodegenPackage = ENV["GOPACKAGE"]
if (!CodegenPackage)
CodegenPackage = "main"
print "// Code generated from " FILENAME ". DO NOT EDIT."
print ""
print "package " CodegenPackage
print ""
print "import ("
print "\t`encoding/base64`"
@ -117,10 +107,20 @@ function codegen_begin() {
print ")"
print ""
print "// protoConsumeBoolFrom tries to deserialize a boolean value"
CodegenAppendJSON["bool"] = \
"\tb = strconv.AppendBool(b, %s)\n"
CodegenSerialize["bool"] = \
"\tif %s {\n" \
"\t\tdata = append(data, 1)\n" \
"\t} else {\n" \
"\t\tdata = append(data, 0)\n" \
"\t}\n"
funcname = codegen_private("ConsumeBoolFrom")
print "// " funcname " tries to deserialize a boolean value"
print "// from the beginning of a byte stream. When successful,"
print "// it returns a subslice with any data that might follow."
print "func protoConsumeBoolFrom(data []byte, b *bool) ([]byte, bool) {"
print "func " funcname "(data []byte, b *bool) ([]byte, bool) {"
print "\tif len(data) < 1 {"
print "\t\treturn nil, false"
print "\t}"
@ -133,9 +133,15 @@ function codegen_begin() {
print "}"
print ""
print "// protoAppendStringTo tries to serialize a string value,"
CodegenDeserialize["bool"] = \
"\tif data, ok = " funcname "(data, &%s); !ok {\n" \
"\t\treturn nil, ok\n" \
"\t}\n"
funcname = codegen_private("AppendStringTo")
print "// " funcname " tries to serialize a string value,"
print "// appending it to the end of a byte stream."
print "func protoAppendStringTo(data []byte, s string) ([]byte, bool) {"
print "func " funcname "(data []byte, s string) ([]byte, bool) {"
print "\tif len(s) > math.MaxUint32 {"
print "\t\treturn nil, false"
print "\t}"
@ -144,10 +150,16 @@ function codegen_begin() {
print "}"
print ""
print "// protoConsumeStringFrom tries to deserialize a string value"
CodegenSerialize["string"] = \
"\tif data, ok = " funcname "(data, %s); !ok {\n" \
"\t\treturn nil, ok\n" \
"\t}\n"
funcname = codegen_private("ConsumeStringFrom")
print "// " funcname " tries to deserialize a string value"
print "// from the beginning of a byte stream. When successful,"
print "// it returns a subslice with any data that might follow."
print "func protoConsumeStringFrom(data []byte, s *string) ([]byte, bool) {"
print "func " funcname "(data []byte, s *string) ([]byte, bool) {"
print "\tif len(data) < 4 {"
print "\t\treturn nil, false"
print "\t}"
@ -163,9 +175,15 @@ function codegen_begin() {
print "}"
print ""
print "// protoUnmarshalEnumJSON converts a JSON fragment to an integer,"
CodegenDeserialize["string"] = \
"\tif data, ok = " funcname "(data, &%s); !ok {\n" \
"\t\treturn nil, ok\n" \
"\t}\n"
funcname = codegen_private("UnmarshalEnumJSON")
print "// " funcname " converts a JSON fragment to an integer,"
print "// ensuring that it's within the expected range of enum values."
print "func protoUnmarshalEnumJSON(data []byte) (int64, error) {"
print "func " funcname "(data []byte) (int64, error) {"
print "\tvar n int64"
print "\tif err := json.Unmarshal(data, &n); err != nil {"
print "\t\treturn 0, err"
@ -197,7 +215,7 @@ function codegen_enum_value(name, subname, value, cg, goname) {
"\t\t*v = " goname "\n")
}
function codegen_enum(name, cg, gotype, fields) {
function codegen_enum(name, cg, gotype, fields, funcname) {
gotype = PrefixCamel name
print "type " gotype " int8"
print ""
@ -227,11 +245,12 @@ function codegen_enum(name, cg, gotype, fields) {
print "}"
print ""
funcname = codegen_private("UnmarshalEnumJSON")
print "func (v *" gotype ") UnmarshalJSON(data []byte) error {"
print "\tvar s string"
print "\tif json.Unmarshal(data, &s) == nil {"
print "\t\t// Handled below."
print "\t} else if n, err := protoUnmarshalEnumJSON(data); err != nil {"
print "\t} else if n, err := " funcname "(data); err != nil {"
print "\t\treturn err"
print "\t} else {"
print "\t\t*v = " gotype "(n)"

View File

@ -51,6 +51,8 @@ function define_uint(size, shortname) {
}
function codegen_begin() {
print "// Code generated from " FILENAME ". DO NOT EDIT."
print ""
print "export class Reader extends DataView {"
print "\tconstructor() {"
print "\t\tsuper(...arguments)"

View File

@ -22,7 +22,7 @@
# unless this role is already filled by, e.g., WebSocket.
#
# Usage: env LC_ALL=C awk -f xC-gen-proto.awk -f xC-gen-proto-{c,go,js}.awk \
# xC-proto > xC-proto.{c,go,js} | {clang-format,gofmt,...}
# -v PrefixCamel=Relay xC-proto > xC-proto.{c,go,js} | {clang-format,gofmt,...}
# --- Utilities ----------------------------------------------------------------
@ -289,12 +289,14 @@ function deftype() {
return 0
}
BEGIN {
PrefixLower = "relay_"
PrefixUpper = "RELAY_"
PrefixCamel = "Relay"
{
if (PrefixCamel) {
PrefixLower = tolower(cameltosnake(PrefixCamel)) "_"
PrefixUpper = toupper(cameltosnake(PrefixCamel)) "_"
}
print "// Generated by xC-gen-proto.awk. DO NOT MODIFY."
# This is not in a BEGIN clause (even though it consumes all input),
# so that the code generator can insert the first FILENAME.
codegen_begin()
nexttoken()

View File

@ -8,7 +8,8 @@ all: $(outputs) public/ircfmt.woff2
xP: xP.go proto.go
go build -o $@
proto.go: ../xC-gen-proto.awk ../xC-gen-proto-go.awk ../xC-proto
$(AWK) -f ../xC-gen-proto.awk -f ../xC-gen-proto-go.awk ../xC-proto > $@
$(AWK) -f ../xC-gen-proto.awk -f ../xC-gen-proto-go.awk \
-v PrefixCamel=Relay ../xC-proto > $@
public/proto.js: ../xC-gen-proto.awk ../xC-gen-proto-js.awk ../xC-proto
$(AWK) -f ../xC-gen-proto.awk -f ../xC-gen-proto-js.awk ../xC-proto > $@
public/ircfmt.woff2: gen-ircfmt.awk