Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 10 additions & 5 deletions cTypeName.go.tmpl
Original file line number Diff line number Diff line change
@@ -1,31 +1,36 @@
{{- define "cSnakeCase" -}}
{{- $name := .Name -}}
{{- snakeCase (regexReplaceAll "([A-Z]+)([A-Z][a-z])" $name "${1}_${2}") -}}
{{- end -}}

{{- define "cTypeName" -}}
{{- $prefix := .Prefix -}}
{{- $name := .Name -}}
{{- printf "%s_%s" $prefix (snakeCase $name) -}}
{{- printf "%s_%s" $prefix (snakeCase (regexReplaceAll "([A-Z]+)([A-Z][a-z])" $name "${1}_${2}")) -}}
{{- end -}}

{{- define "cEnumValue" -}}
{{- $prefix := .Prefix -}}
{{- $typeName := .TypeName -}}
{{- $fieldName := .FieldName -}}
{{- printf "%s_%s_%s" (toUpper $prefix) (toUpper (snakeCase $typeName)) (toUpper (snakeCase $fieldName)) -}}
{{- printf "%s_%s_%s" (toUpper $prefix) (toUpper (snakeCase (regexReplaceAll "([A-Z]+)([A-Z][a-z])" $typeName "${1}_${2}"))) (toUpper (snakeCase (regexReplaceAll "([A-Z]+)([A-Z][a-z])" $fieldName "${1}_${2}"))) -}}
{{- end -}}

{{- define "cFieldName" -}}
{{- $name := .Name -}}
{{- snakeCase $name -}}
{{- template "cSnakeCase" dict "Name" $name -}}
{{- end -}}

{{- define "cMethodRequestTypeName" -}}
{{- $prefix := .Prefix -}}
{{- $serviceName := .ServiceName -}}
{{- $methodName := .MethodName -}}
{{- printf "%s_%s_%s_request" $prefix (snakeCase $serviceName) (snakeCase $methodName) -}}
{{- printf "%s_%s_%s_request" $prefix (snakeCase (regexReplaceAll "([A-Z]+)([A-Z][a-z])" $serviceName "${1}_${2}")) (snakeCase (regexReplaceAll "([A-Z]+)([A-Z][a-z])" $methodName "${1}_${2}")) -}}
{{- end -}}

{{- define "cMethodResponseTypeName" -}}
{{- $prefix := .Prefix -}}
{{- $serviceName := .ServiceName -}}
{{- $methodName := .MethodName -}}
{{- printf "%s_%s_%s_response" $prefix (snakeCase $serviceName) (snakeCase $methodName) -}}
{{- printf "%s_%s_%s_response" $prefix (snakeCase (regexReplaceAll "([A-Z]+)([A-Z][a-z])" $serviceName "${1}_${2}")) (snakeCase (regexReplaceAll "([A-Z]+)([A-Z][a-z])" $methodName "${1}_${2}")) -}}
{{- end -}}
22 changes: 12 additions & 10 deletions client.go.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -8,33 +8,35 @@ int {{ printf "%s_runtime_init" $prefix }}({{ printf "%s_error" $prefix }} *erro
void {{ printf "%s_runtime_cleanup" $prefix }}(void);

{{- range $_, $service := $services }}
typedef struct {{ printf "%s_%s_client" $prefix (snakeCase $service.Name) }} {{ printf "%s_%s_client" $prefix (snakeCase $service.Name) }};
{{- $serviceName := (snakeCase (regexReplaceAll "([A-Z]+)([A-Z][a-z])" $service.Name "${1}_${2}")) }}
typedef struct {{ printf "%s_%s_client" $prefix $serviceName }} {{ printf "%s_%s_client" $prefix $serviceName }};

{{ printf "%s_%s_client" $prefix (snakeCase $service.Name) }} *{{ printf "%s_%s_client_create" $prefix (snakeCase $service.Name) }}(const char *base_url, const {{ printf "%s_client_options" $prefix }} *options);
void {{ printf "%s_%s_client_destroy" $prefix (snakeCase $service.Name) }}({{ printf "%s_%s_client" $prefix (snakeCase $service.Name) }} *client);
int {{ printf "%s_%s_client_configure" $prefix (snakeCase $service.Name) }}({{ printf "%s_%s_client" $prefix (snakeCase $service.Name) }} *client, const {{ printf "%s_client_options" $prefix }} *options);
int {{ printf "%s_%s_client_send_prepared_request" $prefix (snakeCase $service.Name) }}(
{{ printf "%s_%s_client" $prefix (snakeCase $service.Name) }} *client,
{{ printf "%s_%s_client" $prefix $serviceName }} *{{ printf "%s_%s_client_create" $prefix $serviceName }}(const char *base_url, const {{ printf "%s_client_options" $prefix }} *options);
void {{ printf "%s_%s_client_destroy" $prefix $serviceName }}({{ printf "%s_%s_client" $prefix $serviceName }} *client);
int {{ printf "%s_%s_client_configure" $prefix $serviceName }}({{ printf "%s_%s_client" $prefix $serviceName }} *client, const {{ printf "%s_client_options" $prefix }} *options);
int {{ printf "%s_%s_client_send_prepared_request" $prefix $serviceName }}(
{{ printf "%s_%s_client" $prefix $serviceName }} *client,
const {{ printf "%s_prepared_request" $prefix }} *request,
{{ printf "%s_http_response" $prefix }} *response,
{{ printf "%s_error" $prefix }} *error
);

{{- range $_, $method := $service.Methods }}
int {{ printf "%s_%s_%s_prepare_request" $prefix (snakeCase $service.Name) (snakeCase $method.Name) }}(
{{- $methodName := (snakeCase (regexReplaceAll "([A-Z]+)([A-Z][a-z])" $method.Name "${1}_${2}")) }}
int {{ printf "%s_%s_%s_prepare_request" $prefix $serviceName $methodName }}(
const {{ template "cMethodRequestTypeName" dict "Prefix" $prefix "ServiceName" $service.Name "MethodName" $method.Name }} *request,
{{ printf "%s_prepared_request" $prefix }} *prepared_request,
{{ printf "%s_error" $prefix }} *error
);

int {{ printf "%s_%s_%s_parse_response" $prefix (snakeCase $service.Name) (snakeCase $method.Name) }}(
int {{ printf "%s_%s_%s_parse_response" $prefix $serviceName $methodName }}(
const {{ printf "%s_http_response" $prefix }} *http_response,
{{ template "cMethodResponseTypeName" dict "Prefix" $prefix "ServiceName" $service.Name "MethodName" $method.Name }} *response,
{{ printf "%s_error" $prefix }} *error
);

int {{ printf "%s_%s_%s" $prefix (snakeCase $service.Name) (snakeCase $method.Name) }}(
{{ printf "%s_%s_client" $prefix (snakeCase $service.Name) }} *client,
int {{ printf "%s_%s_%s" $prefix $serviceName $methodName }}(
{{ printf "%s_%s_client" $prefix $serviceName }} *client,
const {{ template "cMethodRequestTypeName" dict "Prefix" $prefix "ServiceName" $service.Name "MethodName" $method.Name }} *request,
{{ template "cMethodResponseTypeName" dict "Prefix" $prefix "ServiceName" $service.Name "MethodName" $method.Name }} *response,
{{ printf "%s_error" $prefix }} *error
Expand Down
41 changes: 41 additions & 0 deletions generator_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,47 @@ service EnumWire
runCmd(t, tmp, bin)
}

func TestAcronymBoundaryNamesSnakeCaseCorrectly(t *testing.T) {
root := repoRoot(t)
tmp := t.TempDir()

schemaPath := filepath.Join(tmp, "acronym_names.ridl")
schemaText := `webrpc = v1

name = acronym_names
version = v1.0.0
basepath = /rpc

struct EOAWalletData
- authID: string

service OIDCAuth
- ExchangeID(wallet: EOAWalletData) => (wallet: EOAWalletData)
`
if err := os.WriteFile(schemaPath, []byte(schemaText), 0o644); err != nil {
t.Fatalf("write acronym schema: %v", err)
}

header := filepath.Join(tmp, "acronym.gen.h")
impl := filepath.Join(tmp, "acronym.gen.c")
generateC(t, root, schemaPath, header, impl, "acronym")

headerText, err := os.ReadFile(header)
if err != nil {
t.Fatalf("read generated header: %v", err)
}
headerSrc := string(headerText)
if !strings.Contains(headerSrc, "typedef struct acronym_eoa_wallet_data acronym_eoa_wallet_data;") {
t.Fatalf("generated type name should preserve acronym boundary before Wallet")
}
if !strings.Contains(headerSrc, "auth_id;") {
t.Fatalf("generated field name should preserve acronym boundary before ID")
}
if !strings.Contains(headerSrc, "acronym_oidc_auth_exchange_id(") {
t.Fatalf("generated method name should preserve acronym boundaries in service and method names")
}
}

func TestGenerateFailsWhenEnumUsesReservedUnknownSentinel(t *testing.T) {
root := repoRoot(t)
tmp := t.TempDir()
Expand Down
50 changes: 26 additions & 24 deletions implClient.go.tmpl
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
{{- define "implClient" -}}
{{- $prefix := .Prefix -}}
{{- range $_, $service := .Services }}
struct {{ printf "%s_%s_client" $prefix (snakeCase $service.Name) }} {
{{- $serviceName := (snakeCase (regexReplaceAll "([A-Z]+)([A-Z][a-z])" $service.Name "${1}_${2}")) }}
struct {{ printf "%s_%s_client" $prefix $serviceName }} {
char *base_url;
char *bearer_token;
struct curl_slist *default_headers;
long timeout_ms;
};

static void {{ printf "%s_%s_client_free_config_parts" $prefix (snakeCase $service.Name) }}(char **bearer_token, struct curl_slist **default_headers) {
static void {{ printf "%s_%s_client_free_config_parts" $prefix $serviceName }}(char **bearer_token, struct curl_slist **default_headers) {
if (bearer_token && *bearer_token) {
free(*bearer_token);
*bearer_token = NULL;
Expand All @@ -19,13 +20,13 @@ static void {{ printf "%s_%s_client_free_config_parts" $prefix (snakeCase $servi
}
}

static void {{ printf "%s_%s_client_reset_config" $prefix (snakeCase $service.Name) }}({{ printf "%s_%s_client" $prefix (snakeCase $service.Name) }} *client) {
static void {{ printf "%s_%s_client_reset_config" $prefix $serviceName }}({{ printf "%s_%s_client" $prefix $serviceName }} *client) {
if (!client) return;
{{ printf "%s_%s_client_free_config_parts" $prefix (snakeCase $service.Name) }}(&client->bearer_token, &client->default_headers);
{{ printf "%s_%s_client_free_config_parts" $prefix $serviceName }}(&client->bearer_token, &client->default_headers);
client->timeout_ms = 10000L;
}

static int {{ printf "%s_%s_client_build_config" $prefix (snakeCase $service.Name) }}(
static int {{ printf "%s_%s_client_build_config" $prefix $serviceName }}(
const {{ printf "%s_client_options" $prefix }} *options,
char **bearer_token,
struct curl_slist **default_headers,
Expand Down Expand Up @@ -59,58 +60,58 @@ static int {{ printf "%s_%s_client_build_config" $prefix (snakeCase $service.Nam
return 1;

fail:
{{ printf "%s_%s_client_free_config_parts" $prefix (snakeCase $service.Name) }}(bearer_token, default_headers);
{{ printf "%s_%s_client_free_config_parts" $prefix $serviceName }}(bearer_token, default_headers);
*timeout_ms = 10000L;
return 0;
}

int {{ printf "%s_%s_client_configure" $prefix (snakeCase $service.Name) }}({{ printf "%s_%s_client" $prefix (snakeCase $service.Name) }} *client, const {{ printf "%s_client_options" $prefix }} *options) {
int {{ printf "%s_%s_client_configure" $prefix $serviceName }}({{ printf "%s_%s_client" $prefix $serviceName }} *client, const {{ printf "%s_client_options" $prefix }} *options) {
char *next_bearer_token = NULL;
struct curl_slist *next_default_headers = NULL;
long next_timeout_ms = 10000L;

if (!client) return 0;
if (!{{ printf "%s_%s_client_build_config" $prefix (snakeCase $service.Name) }}(options, &next_bearer_token, &next_default_headers, &next_timeout_ms)) {
if (!{{ printf "%s_%s_client_build_config" $prefix $serviceName }}(options, &next_bearer_token, &next_default_headers, &next_timeout_ms)) {
return 0;
}

{{ printf "%s_%s_client_reset_config" $prefix (snakeCase $service.Name) }}(client);
{{ printf "%s_%s_client_reset_config" $prefix $serviceName }}(client);
client->bearer_token = next_bearer_token;
client->default_headers = next_default_headers;
client->timeout_ms = next_timeout_ms;
return 1;
}

{{ printf "%s_%s_client" $prefix (snakeCase $service.Name) }} *{{ printf "%s_%s_client_create" $prefix (snakeCase $service.Name) }}(const char *base_url, const {{ printf "%s_client_options" $prefix }} *options) {
{{ printf "%s_%s_client" $prefix (snakeCase $service.Name) }} *client =
({{ printf "%s_%s_client" $prefix (snakeCase $service.Name) }} *)calloc(1, sizeof(*client));
{{ printf "%s_%s_client" $prefix $serviceName }} *{{ printf "%s_%s_client_create" $prefix $serviceName }}(const char *base_url, const {{ printf "%s_client_options" $prefix }} *options) {
{{ printf "%s_%s_client" $prefix $serviceName }} *client =
({{ printf "%s_%s_client" $prefix $serviceName }} *)calloc(1, sizeof(*client));
if (!client) return NULL;
client->base_url = {{ printf "%s_strdup" $prefix }}(base_url ? base_url : "");
if (!client->base_url) {
free(client);
return NULL;
}
{{ printf "%s_%s_client_reset_config" $prefix (snakeCase $service.Name) }}(client);
if (!{{ printf "%s_%s_client_configure" $prefix (snakeCase $service.Name) }}(client, options)) {
{{ printf "%s_%s_client_reset_config" $prefix $serviceName }}(client);
if (!{{ printf "%s_%s_client_configure" $prefix $serviceName }}(client, options)) {
free(client->base_url);
client->base_url = NULL;
{{ printf "%s_%s_client_reset_config" $prefix (snakeCase $service.Name) }}(client);
{{ printf "%s_%s_client_reset_config" $prefix $serviceName }}(client);
free(client);
return NULL;
}
return client;
}

void {{ printf "%s_%s_client_destroy" $prefix (snakeCase $service.Name) }}({{ printf "%s_%s_client" $prefix (snakeCase $service.Name) }} *client) {
void {{ printf "%s_%s_client_destroy" $prefix $serviceName }}({{ printf "%s_%s_client" $prefix $serviceName }} *client) {
if (!client) return;
free(client->base_url);
client->base_url = NULL;
{{ printf "%s_%s_client_reset_config" $prefix (snakeCase $service.Name) }}(client);
{{ printf "%s_%s_client_reset_config" $prefix $serviceName }}(client);
free(client);
}

int {{ printf "%s_%s_client_send_prepared_request" $prefix (snakeCase $service.Name) }}(
{{ printf "%s_%s_client" $prefix (snakeCase $service.Name) }} *client,
int {{ printf "%s_%s_client_send_prepared_request" $prefix $serviceName }}(
{{ printf "%s_%s_client" $prefix $serviceName }} *client,
const {{ printf "%s_prepared_request" $prefix }} *request,
{{ printf "%s_http_response" $prefix }} *response,
{{ printf "%s_error" $prefix }} *error
Expand All @@ -132,8 +133,9 @@ int {{ printf "%s_%s_client_send_prepared_request" $prefix (snakeCase $service.N
}

{{- range $_, $method := $service.Methods }}
int {{ printf "%s_%s_%s" $prefix (snakeCase $service.Name) (snakeCase $method.Name) }}(
{{ printf "%s_%s_client" $prefix (snakeCase $service.Name) }} *client,
{{- $methodName := (snakeCase (regexReplaceAll "([A-Z]+)([A-Z][a-z])" $method.Name "${1}_${2}")) }}
int {{ printf "%s_%s_%s" $prefix $serviceName $methodName }}(
{{ printf "%s_%s_client" $prefix $serviceName }} *client,
const {{ template "cMethodRequestTypeName" dict "Prefix" $prefix "ServiceName" $service.Name "MethodName" $method.Name }} *request,
{{ template "cMethodResponseTypeName" dict "Prefix" $prefix "ServiceName" $service.Name "MethodName" $method.Name }} *response,
{{ printf "%s_error" $prefix }} *error
Expand All @@ -149,13 +151,13 @@ int {{ printf "%s_%s_%s" $prefix (snakeCase $service.Name) (snakeCase $method.Na
goto fail;
}

if ({{ printf "%s_%s_%s_prepare_request" $prefix (snakeCase $service.Name) (snakeCase $method.Name) }}(request, &prepared_request, error) != 0) {
if ({{ printf "%s_%s_%s_prepare_request" $prefix $serviceName $methodName }}(request, &prepared_request, error) != 0) {
goto fail;
}
if ({{ printf "%s_%s_client_send_prepared_request" $prefix (snakeCase $service.Name) }}(client, &prepared_request, &http_response, error) != 0) {
if ({{ printf "%s_%s_client_send_prepared_request" $prefix $serviceName }}(client, &prepared_request, &http_response, error) != 0) {
goto fail;
}
if ({{ printf "%s_%s_%s_parse_response" $prefix (snakeCase $service.Name) (snakeCase $method.Name) }}(&http_response, response, error) != 0) {
if ({{ printf "%s_%s_%s_parse_response" $prefix $serviceName $methodName }}(&http_response, response, error) != 0) {
goto fail;
}
rc = 0;
Expand Down
14 changes: 8 additions & 6 deletions implMethodJSON.go.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,9 @@ static int {{ printf "%s_parse_json_response" $prefix }}(
}

{{- range $_, $service := .Services }}
{{- $serviceName := (snakeCase (regexReplaceAll "([A-Z]+)([A-Z][a-z])" $service.Name "${1}_${2}")) }}
{{- range $_, $method := $service.Methods }}
{{- $methodName := (snakeCase (regexReplaceAll "([A-Z]+)([A-Z][a-z])" $method.Name "${1}_${2}")) }}
static cJSON *{{ template "cMethodRequestTypeName" dict "Prefix" $prefix "ServiceName" $service.Name "MethodName" $method.Name }}_to_json(const {{ template "cMethodRequestTypeName" dict "Prefix" $prefix "ServiceName" $service.Name "MethodName" $method.Name }} *value) {
{{- if $method.Succinct }}
{{- if ne (len $method.Inputs) 1 }}
Expand All @@ -78,7 +80,7 @@ static cJSON *{{ template "cMethodRequestTypeName" dict "Prefix" $prefix "Servic
{
cJSON *root = NULL;
{{- $input := index $method.Inputs 0 -}}
{{- $fieldName := (snakeCase $input.Name) -}}
{{- $fieldName := (snakeCase (regexReplaceAll "([A-Z]+)([A-Z][a-z])" $input.Name "${1}_${2}")) -}}
{{ template "json_encode_value" dict "Prefix" $prefix "Type" $input.Type "Expr" (printf "value->%s" $fieldName) "OutVar" "root" "Types" $.Types }}
return root;
fail:
Expand All @@ -91,7 +93,7 @@ fail:
if (!root) return NULL;
{{- range $_, $input := $method.Inputs }}
{
{{- $fieldName := (snakeCase $input.Name) -}}
{{- $fieldName := (snakeCase (regexReplaceAll "([A-Z]+)([A-Z][a-z])" $input.Name "${1}_${2}")) -}}
{{- if $input.Optional }}
if (value->has_{{$fieldName}}) {
{{- end }}
Expand Down Expand Up @@ -128,7 +130,7 @@ static int {{ template "cMethodResponseTypeName" dict "Prefix" $prefix "ServiceN
}
{
{{- $output := index $method.Outputs 0 -}}
{{- $fieldName := (snakeCase $output.Name) -}}
{{- $fieldName := (snakeCase (regexReplaceAll "([A-Z]+)([A-Z][a-z])" $output.Name "${1}_${2}")) -}}
{{ template "json_decode_value" dict "Prefix" $prefix "Type" $output.Type "JsonExpr" "json" "DestExpr" (printf "out->%s" $fieldName) "Types" $.Types }}
return 0;
fail:
Expand All @@ -144,7 +146,7 @@ fail:
{
cJSON *field_json = cJSON_GetObjectItemCaseSensitive(json, "{{$output.Name}}");
int field_present = field_json != NULL;
{{- $fieldName := (snakeCase $output.Name) -}}
{{- $fieldName := (snakeCase (regexReplaceAll "([A-Z]+)([A-Z][a-z])" $output.Name "${1}_${2}")) -}}
{{- $allowsRequiredNull := false -}}
{{- if isCoreType $output.Type }}
{{- if or (eq (toString $output.Type) "null") (eq (toString $output.Type) "any") }}
Expand Down Expand Up @@ -180,7 +182,7 @@ fail:
{{- end }}
}

int {{ printf "%s_%s_%s_prepare_request" $prefix (snakeCase $service.Name) (snakeCase $method.Name) }}(
int {{ printf "%s_%s_%s_prepare_request" $prefix $serviceName $methodName }}(
const {{ template "cMethodRequestTypeName" dict "Prefix" $prefix "ServiceName" $service.Name "MethodName" $method.Name }} *request,
{{ printf "%s_prepared_request" $prefix }} *prepared_request,
{{ printf "%s_error" $prefix }} *error
Expand All @@ -206,7 +208,7 @@ fail:
return rc;
}

int {{ printf "%s_%s_%s_parse_response" $prefix (snakeCase $service.Name) (snakeCase $method.Name) }}(
int {{ printf "%s_%s_%s_parse_response" $prefix $serviceName $methodName }}(
const {{ printf "%s_http_response" $prefix }} *http_response,
{{ template "cMethodResponseTypeName" dict "Prefix" $prefix "ServiceName" $service.Name "MethodName" $method.Name }} *response,
{{ printf "%s_error" $prefix }} *error
Expand Down
4 changes: 2 additions & 2 deletions implStructJSON.go.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ static {{ toUpper $prefix }}_JSON_UNUSED cJSON *{{ template "cTypeName" dict "Pr
{{- end }}
{{- if not (get $json "ignored") }}
{
{{- $fieldName := (snakeCase $field.Name) -}}
{{- $fieldName := (snakeCase (regexReplaceAll "([A-Z]+)([A-Z][a-z])" $field.Name "${1}_${2}")) -}}
{{- if $field.Optional }}
if (value->has_{{$fieldName}}) {
{{- end }}
Expand Down Expand Up @@ -91,7 +91,7 @@ static {{ toUpper $prefix }}_JSON_UNUSED int {{ template "cTypeName" dict "Prefi
{
cJSON *field_json = cJSON_GetObjectItemCaseSensitive(json, "{{get $json "name"}}");
int field_present = field_json != NULL;
{{- $fieldName := (snakeCase $field.Name) -}}
{{- $fieldName := (snakeCase (regexReplaceAll "([A-Z]+)([A-Z][a-z])" $field.Name "${1}_${2}")) -}}
{{- $allowsRequiredNull := false -}}
{{- if isCoreType $field.Type }}
{{- if or (eq (toString $field.Type) "null") (eq (toString $field.Type) "any") }}
Expand Down
Loading
Loading