Skip to content

Commit 7ba83f3

Browse files
oyvindbergclaude
andauthored
Add gRPC code generation with effect type support, Kotlin-Quarkus-Mutiny tester, and full roundtrip testing (#186)
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
1 parent cbaa3da commit 7ba83f3

249 files changed

Lines changed: 22725 additions & 18 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

bleep.yaml

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -657,6 +657,87 @@ projects:
657657
sources:
658658
- ./generated-and-checked-in
659659
- ./src
660+
testers/grpc/java:
661+
dependencies:
662+
- com.google.protobuf:protobuf-java:4.29.3
663+
- com.novocode:junit-interface:0.11
664+
- io.grpc:grpc-netty-shaded:1.69.0
665+
- io.grpc:grpc-protobuf:1.69.0
666+
- io.grpc:grpc-stub:1.69.0
667+
- io.grpc:grpc-testing:1.69.0
668+
- io.grpc:grpc-inprocess:1.69.0
669+
- junit:junit:4.13.2
670+
dependsOn: foundations-jdbc
671+
folder: ./testers/grpc/java
672+
isTestProject: true
673+
java:
674+
options: -proc:none
675+
platform:
676+
name: jvm
677+
sources:
678+
- ./generated-and-checked-in
679+
- ./src/java
680+
testers/grpc/scala:
681+
dependencies:
682+
- com.google.protobuf:protobuf-java:4.29.3
683+
- com.novocode:junit-interface:0.11
684+
- io.grpc:grpc-netty-shaded:1.69.0
685+
- io.grpc:grpc-protobuf:1.69.0
686+
- io.grpc:grpc-stub:1.69.0
687+
- io.grpc:grpc-testing:1.69.0
688+
- io.grpc:grpc-inprocess:1.69.0
689+
- junit:junit:4.13.2
690+
dependsOn: foundations-jdbc
691+
extends: template-scala-3
692+
isTestProject: true
693+
sources:
694+
- ./generated-and-checked-in
695+
- ./src/scala
696+
testers/grpc/java-spring:
697+
dependencies:
698+
- com.google.protobuf:protobuf-java:4.29.3
699+
- com.novocode:junit-interface:0.11
700+
- io.grpc:grpc-netty-shaded:1.69.0
701+
- io.grpc:grpc-protobuf:1.69.0
702+
- io.grpc:grpc-stub:1.69.0
703+
- io.grpc:grpc-testing:1.69.0
704+
- io.grpc:grpc-inprocess:1.69.0
705+
- junit:junit:4.13.2
706+
- org.springframework.grpc:spring-grpc-core:0.3.0
707+
- org.springframework:spring-context:6.2.1
708+
dependsOn: foundations-jdbc
709+
folder: ./testers/grpc/java-spring
710+
isTestProject: true
711+
java:
712+
options: -proc:none
713+
platform:
714+
name: jvm
715+
sources:
716+
- ./generated-and-checked-in
717+
- ./src/java
718+
testers/grpc/java-quarkus:
719+
dependencies:
720+
- com.google.protobuf:protobuf-java:4.29.3
721+
- com.novocode:junit-interface:0.11
722+
- io.grpc:grpc-netty-shaded:1.69.0
723+
- io.grpc:grpc-protobuf:1.69.0
724+
- io.grpc:grpc-stub:1.69.0
725+
- io.grpc:grpc-testing:1.69.0
726+
- io.grpc:grpc-inprocess:1.69.0
727+
- io.quarkus:quarkus-arc:3.17.2
728+
- io.quarkus:quarkus-grpc:3.17.2
729+
- jakarta.enterprise:jakarta.enterprise.cdi-api:4.1.0
730+
- junit:junit:4.13.2
731+
dependsOn: foundations-jdbc
732+
folder: ./testers/grpc/java-quarkus
733+
isTestProject: true
734+
java:
735+
options: -proc:none
736+
platform:
737+
name: jvm
738+
sources:
739+
- ./generated-and-checked-in
740+
- ./src/java
660741
tests:
661742
dependencies: org.scalatest::scalatest:3.2.18
662743
dependsOn: typr
@@ -667,6 +748,9 @@ projects:
667748
- com.microsoft.sqlserver:mssql-jdbc:12.8.1.jre11
668749
- com.oracle.database.jdbc:ojdbc11:23.6.0.24.10
669750
- com.typesafe.play::play-json:2.10.6
751+
- com.google.protobuf:protobuf-java:4.29.3
752+
- io.grpc:grpc-protobuf:1.69.0
753+
- io.grpc:grpc-stub:1.69.0
670754
- org.apache.avro:avro:1.12.0
671755
- for3Use213: true
672756
module: io.get-coursier::coursier:2.1.24
@@ -738,6 +822,9 @@ scripts:
738822
generate-avro-test:
739823
main: scripts.GenerateAvroTest
740824
project: typr-scripts
825+
generate-grpc-test:
826+
main: scripts.GenerateGrpcTest
827+
project: typr-scripts
741828
generate-db2:
742829
main: scripts.GeneratedDb2
743830
project: typr-scripts

settings.gradle.kts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,12 @@ project(":testers:avro:kotlin-json").projectDir = file("testers/avro/kotlin-json
3636
include("testers:avro:kotlin-quarkus-mutiny")
3737
project(":testers:avro:kotlin-quarkus-mutiny").projectDir = file("testers/avro/kotlin-quarkus-mutiny")
3838

39+
// gRPC Kotlin testers
40+
include("testers:grpc:kotlin")
41+
project(":testers:grpc:kotlin").projectDir = file("testers/grpc/kotlin")
42+
include("testers:grpc:kotlin-quarkus")
43+
project(":testers:grpc:kotlin-quarkus").projectDir = file("testers/grpc/kotlin-quarkus")
44+
3945
// OpenAPI Kotlin testers
4046
include("testers:openapi:kotlin:jaxrs")
4147
project(":testers:openapi:kotlin:jaxrs").projectDir = file("testers/openapi/kotlin/jaxrs")
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
package com.example.grpc;
2+
3+
import com.google.protobuf.CodedInputStream;
4+
import com.google.protobuf.CodedOutputStream;
5+
import com.google.protobuf.WireFormat;
6+
import io.grpc.MethodDescriptor.Marshaller;
7+
import java.io.ByteArrayInputStream;
8+
import java.io.IOException;
9+
import java.io.InputStream;
10+
11+
public record BankTransfer(String accountNumber, String routingNumber) {
12+
public BankTransfer withAccountNumber(String accountNumber) {
13+
return new BankTransfer(accountNumber, routingNumber);
14+
}
15+
16+
public BankTransfer withRoutingNumber(String routingNumber) {
17+
return new BankTransfer(accountNumber, routingNumber);
18+
}
19+
20+
public static Marshaller<BankTransfer> MARSHALLER =
21+
new Marshaller<BankTransfer>() {
22+
@Override
23+
public InputStream stream(BankTransfer value) {
24+
var bytes = new byte[value.getSerializedSize()];
25+
var cos = CodedOutputStream.newInstance(bytes);
26+
try {
27+
value.writeTo(cos);
28+
cos.flush();
29+
} catch (IOException e) {
30+
throw new RuntimeException(e);
31+
}
32+
return new ByteArrayInputStream(bytes);
33+
}
34+
35+
@Override
36+
public BankTransfer parse(InputStream stream) {
37+
try {
38+
return BankTransfer.parseFrom(CodedInputStream.newInstance(stream));
39+
} catch (IOException e) {
40+
throw new RuntimeException(e);
41+
}
42+
}
43+
};
44+
45+
public static BankTransfer parseFrom(CodedInputStream input) throws IOException {
46+
String accountNumber = "";
47+
String routingNumber = "";
48+
while (!input.isAtEnd()) {
49+
var tag = input.readTag();
50+
if (WireFormat.getTagFieldNumber(tag) == 1) {
51+
accountNumber = input.readString();
52+
} else if (WireFormat.getTagFieldNumber(tag) == 2) {
53+
routingNumber = input.readString();
54+
} else {
55+
input.skipField(tag);
56+
}
57+
;
58+
}
59+
;
60+
return new BankTransfer(accountNumber, routingNumber);
61+
}
62+
63+
public Integer getSerializedSize() {
64+
Integer size = 0;
65+
size = size + CodedOutputStream.computeStringSize(1, this.accountNumber());
66+
size = size + CodedOutputStream.computeStringSize(2, this.routingNumber());
67+
return size;
68+
}
69+
70+
public void writeTo(CodedOutputStream output) throws IOException {
71+
output.writeString(1, this.accountNumber());
72+
output.writeString(2, this.routingNumber());
73+
}
74+
}
Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
package com.example.grpc;
2+
3+
import com.google.protobuf.CodedInputStream;
4+
import com.google.protobuf.CodedOutputStream;
5+
import com.google.protobuf.WireFormat;
6+
import io.grpc.MethodDescriptor.Marshaller;
7+
import java.io.ByteArrayInputStream;
8+
import java.io.IOException;
9+
import java.io.InputStream;
10+
import java.time.Instant;
11+
12+
public record ChatMessage(String sender, String content, Instant sentAt) {
13+
public ChatMessage withSender(String sender) {
14+
return new ChatMessage(sender, content, sentAt);
15+
}
16+
17+
public ChatMessage withContent(String content) {
18+
return new ChatMessage(sender, content, sentAt);
19+
}
20+
21+
public ChatMessage withSentAt(Instant sentAt) {
22+
return new ChatMessage(sender, content, sentAt);
23+
}
24+
25+
public static Marshaller<ChatMessage> MARSHALLER =
26+
new Marshaller<ChatMessage>() {
27+
@Override
28+
public InputStream stream(ChatMessage value) {
29+
var bytes = new byte[value.getSerializedSize()];
30+
var cos = CodedOutputStream.newInstance(bytes);
31+
try {
32+
value.writeTo(cos);
33+
cos.flush();
34+
} catch (IOException e) {
35+
throw new RuntimeException(e);
36+
}
37+
return new ByteArrayInputStream(bytes);
38+
}
39+
40+
@Override
41+
public ChatMessage parse(InputStream stream) {
42+
try {
43+
return ChatMessage.parseFrom(CodedInputStream.newInstance(stream));
44+
} catch (IOException e) {
45+
throw new RuntimeException(e);
46+
}
47+
}
48+
};
49+
50+
public static ChatMessage parseFrom(CodedInputStream input) throws IOException {
51+
String sender = "";
52+
String content = "";
53+
Instant sentAt = Instant.EPOCH;
54+
while (!input.isAtEnd()) {
55+
var tag = input.readTag();
56+
if (WireFormat.getTagFieldNumber(tag) == 1) {
57+
sender = input.readString();
58+
} else if (WireFormat.getTagFieldNumber(tag) == 2) {
59+
content = input.readString();
60+
} else if (WireFormat.getTagFieldNumber(tag) == 3) {
61+
var _length = input.readRawVarint32();
62+
var _oldLimit = input.pushLimit(_length);
63+
var _tsSeconds = 0L;
64+
var _tsNanos = 0;
65+
while (!input.isAtEnd()) {
66+
var _tsTag = input.readTag();
67+
if (WireFormat.getTagFieldNumber(_tsTag) == 1) {
68+
_tsSeconds = input.readInt64();
69+
} else if (WireFormat.getTagFieldNumber(_tsTag) == 2) {
70+
_tsNanos = input.readInt32();
71+
} else {
72+
input.skipField(_tsTag);
73+
}
74+
;
75+
}
76+
;
77+
sentAt = Instant.ofEpochSecond(_tsSeconds, (long) (_tsNanos));
78+
input.popLimit(_oldLimit);
79+
;
80+
} else {
81+
input.skipField(tag);
82+
}
83+
;
84+
}
85+
;
86+
return new ChatMessage(sender, content, sentAt);
87+
}
88+
89+
public Integer getSerializedSize() {
90+
Integer size = 0;
91+
size = size + CodedOutputStream.computeStringSize(1, this.sender());
92+
size = size + CodedOutputStream.computeStringSize(2, this.content());
93+
size =
94+
size
95+
+ CodedOutputStream.computeTagSize(3)
96+
+ CodedOutputStream.computeUInt32SizeNoTag(
97+
CodedOutputStream.computeInt64Size(1, this.sentAt().getEpochSecond())
98+
+ CodedOutputStream.computeInt32Size(2, this.sentAt().getNano()))
99+
+ CodedOutputStream.computeInt64Size(1, this.sentAt().getEpochSecond())
100+
+ CodedOutputStream.computeInt32Size(2, this.sentAt().getNano());
101+
return size;
102+
}
103+
104+
public void writeTo(CodedOutputStream output) throws IOException {
105+
output.writeString(1, this.sender());
106+
output.writeString(2, this.content());
107+
output.writeTag(3, 2);
108+
output.writeUInt32NoTag(
109+
CodedOutputStream.computeInt64Size(1, this.sentAt().getEpochSecond())
110+
+ CodedOutputStream.computeInt32Size(2, this.sentAt().getNano()));
111+
output.writeInt64(1, this.sentAt().getEpochSecond());
112+
output.writeInt32(2, this.sentAt().getNano());
113+
}
114+
}
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
package com.example.grpc;
2+
3+
import com.google.protobuf.CodedInputStream;
4+
import com.google.protobuf.CodedOutputStream;
5+
import com.google.protobuf.WireFormat;
6+
import io.grpc.MethodDescriptor.Marshaller;
7+
import java.io.ByteArrayInputStream;
8+
import java.io.IOException;
9+
import java.io.InputStream;
10+
11+
public record CreateOrderRequest(Order order) {
12+
public CreateOrderRequest withOrder(Order order) {
13+
return new CreateOrderRequest(order);
14+
}
15+
16+
public static Marshaller<CreateOrderRequest> MARSHALLER =
17+
new Marshaller<CreateOrderRequest>() {
18+
@Override
19+
public InputStream stream(CreateOrderRequest value) {
20+
var bytes = new byte[value.getSerializedSize()];
21+
var cos = CodedOutputStream.newInstance(bytes);
22+
try {
23+
value.writeTo(cos);
24+
cos.flush();
25+
} catch (IOException e) {
26+
throw new RuntimeException(e);
27+
}
28+
return new ByteArrayInputStream(bytes);
29+
}
30+
31+
@Override
32+
public CreateOrderRequest parse(InputStream stream) {
33+
try {
34+
return CreateOrderRequest.parseFrom(CodedInputStream.newInstance(stream));
35+
} catch (IOException e) {
36+
throw new RuntimeException(e);
37+
}
38+
}
39+
};
40+
41+
public static CreateOrderRequest parseFrom(CodedInputStream input) throws IOException {
42+
Order order = null;
43+
while (!input.isAtEnd()) {
44+
var tag = input.readTag();
45+
if (WireFormat.getTagFieldNumber(tag) == 1) {
46+
var _length = input.readRawVarint32();
47+
var _oldLimit = input.pushLimit(_length);
48+
order = Order.parseFrom(input);
49+
input.popLimit(_oldLimit);
50+
;
51+
} else {
52+
input.skipField(tag);
53+
}
54+
;
55+
}
56+
;
57+
return new CreateOrderRequest(order);
58+
}
59+
60+
public Integer getSerializedSize() {
61+
Integer size = 0;
62+
if (!this.order().equals(null)) {
63+
size =
64+
size
65+
+ CodedOutputStream.computeTagSize(1)
66+
+ CodedOutputStream.computeUInt32SizeNoTag(this.order().getSerializedSize())
67+
+ this.order().getSerializedSize();
68+
}
69+
return size;
70+
}
71+
72+
public void writeTo(CodedOutputStream output) throws IOException {
73+
if (!this.order().equals(null)) {
74+
output.writeTag(1, 2);
75+
output.writeUInt32NoTag(this.order().getSerializedSize());
76+
this.order().writeTo(output);
77+
;
78+
}
79+
}
80+
}

0 commit comments

Comments
 (0)