├── .github
└── workflows
│ └── ci-unit.yaml
├── .gitignore
├── LICENSE
├── NOTICE
├── README.md
├── benchmark
├── pom.xml
└── src
│ └── main
│ └── java
│ └── com
│ └── github
│ └── splunk
│ └── lightproto
│ └── benchmark
│ ├── ProtoBenchmark.java
│ ├── SimpleBenchmark.java
│ └── StringEncodingBenchmark.java
├── code-generator
├── pom.xml
└── src
│ └── main
│ ├── java
│ └── com
│ │ └── github
│ │ └── splunk
│ │ └── lightproto
│ │ └── generator
│ │ ├── LightProto.java
│ │ ├── LightProtoAbstractRepeated.java
│ │ ├── LightProtoBooleanField.java
│ │ ├── LightProtoBytesField.java
│ │ ├── LightProtoEnum.java
│ │ ├── LightProtoEnumField.java
│ │ ├── LightProtoField.java
│ │ ├── LightProtoGenerator.java
│ │ ├── LightProtoMessage.java
│ │ ├── LightProtoMessageField.java
│ │ ├── LightProtoNumberField.java
│ │ ├── LightProtoRepeatedBytesField.java
│ │ ├── LightProtoRepeatedEnumField.java
│ │ ├── LightProtoRepeatedMessageField.java
│ │ ├── LightProtoRepeatedNumberField.java
│ │ ├── LightProtoRepeatedStringField.java
│ │ ├── LightProtoStringField.java
│ │ └── Util.java
│ └── resources
│ └── com
│ └── github
│ └── splunk
│ └── lightproto
│ └── generator
│ └── LightProtoCodec.java
├── license-header.txt
├── maven-plugin
├── pom.xml
└── src
│ └── main
│ └── java
│ └── com
│ └── github
│ └── splunk
│ └── lightproto
│ └── maven
│ └── plugin
│ └── LightProtoMojo.java
├── pom.xml
└── tests
├── pom.xml
└── src
├── main
└── proto
│ ├── PulsarApi.proto
│ ├── PulsarMarkers.proto
│ ├── Test.proto
│ ├── addressbook.proto
│ ├── bytes.proto
│ ├── enums.proto
│ ├── messages.proto
│ ├── numbers.proto
│ ├── repeated_numbers.proto
│ ├── required.proto
│ └── strings.proto
└── test
└── java
└── com
└── github
└── splunk
└── lightproto
└── tests
├── AddressBookTest.java
├── BytesTest.java
├── EnumsTest.java
├── LightProtoCodecTest.java
├── MessagesTest.java
├── NumbersTest.java
├── RepeatedNumbersTest.java
├── RequiredTest.java
└── StringsTest.java
/.github/workflows/ci-unit.yaml:
--------------------------------------------------------------------------------
1 | #
2 | # Copyright 2020 Splunk Inc.
3 | #
4 | # Licensed under the Apache License, Version 2.0 (the "License");
5 | # you may not use this file except in compliance with the License.
6 | # You may obtain a copy of the License at
7 | #
8 | # http://www.apache.org/licenses/LICENSE-2.0
9 | #
10 | # Unless required by applicable law or agreed to in writing, software
11 | # distributed under the License is distributed on an "AS IS" BASIS,
12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | # See the License for the specific language governing permissions and
14 | # limitations under the License.
15 | #
16 |
17 | name: CI - Unit
18 | on:
19 | pull_request:
20 | branches:
21 | - master
22 | push:
23 | branches:
24 | - branch-*
25 |
26 | jobs:
27 |
28 | unit-tests:
29 | name:
30 | runs-on: ubuntu-latest
31 | container:
32 | image: maven:3.6.3-jdk-11
33 | timeout-minutes: 30
34 |
35 | steps:
36 |
37 | - name: checkout
38 | uses: actions/checkout@v2
39 | with:
40 | fetch-depth: 25
41 | ref: ${{ github.event.pull_request.head.sha }}
42 |
43 | - name: Cache local Maven repository
44 | uses: actions/cache@v2
45 | with:
46 | path: ~/.m2/repository
47 | key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
48 | restore-keys: |
49 | ${{ runner.os }}-maven-
50 |
51 | - name: build and run tests
52 | run: mvn -B -ntp -Dgpg.skip license:check install
53 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | target
2 | .project
3 | .settings
4 | .classpath
5 | .idea
6 | **/*.iml
7 | **/*.versionsBackup
8 |
9 | .DS_Store
10 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 |
2 | Apache License
3 | Version 2.0, January 2004
4 | http://www.apache.org/licenses/
5 |
6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
7 |
8 | 1. Definitions.
9 |
10 | "License" shall mean the terms and conditions for use, reproduction,
11 | and distribution as defined by Sections 1 through 9 of this document.
12 |
13 | "Licensor" shall mean the copyright owner or entity authorized by
14 | the copyright owner that is granting the License.
15 |
16 | "Legal Entity" shall mean the union of the acting entity and all
17 | other entities that control, are controlled by, or are under common
18 | control with that entity. For the purposes of this definition,
19 | "control" means (i) the power, direct or indirect, to cause the
20 | direction or management of such entity, whether by contract or
21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
22 | outstanding shares, or (iii) beneficial ownership of such entity.
23 |
24 | "You" (or "Your") shall mean an individual or Legal Entity
25 | exercising permissions granted by this License.
26 |
27 | "Source" form shall mean the preferred form for making modifications,
28 | including but not limited to software source code, documentation
29 | source, and configuration files.
30 |
31 | "Object" form shall mean any form resulting from mechanical
32 | transformation or translation of a Source form, including but
33 | not limited to compiled object code, generated documentation,
34 | and conversions to other media types.
35 |
36 | "Work" shall mean the work of authorship, whether in Source or
37 | Object form, made available under the License, as indicated by a
38 | copyright notice that is included in or attached to the work
39 | (an example is provided in the Appendix below).
40 |
41 | "Derivative Works" shall mean any work, whether in Source or Object
42 | form, that is based on (or derived from) the Work and for which the
43 | editorial revisions, annotations, elaborations, or other modifications
44 | represent, as a whole, an original work of authorship. For the purposes
45 | of this License, Derivative Works shall not include works that remain
46 | separable from, or merely link (or bind by name) to the interfaces of,
47 | the Work and Derivative Works thereof.
48 |
49 | "Contribution" shall mean any work of authorship, including
50 | the original version of the Work and any modifications or additions
51 | to that Work or Derivative Works thereof, that is intentionally
52 | submitted to Licensor for inclusion in the Work by the copyright owner
53 | or by an individual or Legal Entity authorized to submit on behalf of
54 | the copyright owner. For the purposes of this definition, "submitted"
55 | means any form of electronic, verbal, or written communication sent
56 | to the Licensor or its representatives, including but not limited to
57 | communication on electronic mailing lists, source code control systems,
58 | and issue tracking systems that are managed by, or on behalf of, the
59 | Licensor for the purpose of discussing and improving the Work, but
60 | excluding communication that is conspicuously marked or otherwise
61 | designated in writing by the copyright owner as "Not a Contribution."
62 |
63 | "Contributor" shall mean Licensor and any individual or Legal Entity
64 | on behalf of whom a Contribution has been received by Licensor and
65 | subsequently incorporated within the Work.
66 |
67 | 2. Grant of Copyright License. Subject to the terms and conditions of
68 | this License, each Contributor hereby grants to You a perpetual,
69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
70 | copyright license to reproduce, prepare Derivative Works of,
71 | publicly display, publicly perform, sublicense, and distribute the
72 | Work and such Derivative Works in Source or Object form.
73 |
74 | 3. Grant of Patent License. Subject to the terms and conditions of
75 | this License, each Contributor hereby grants to You a perpetual,
76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
77 | (except as stated in this section) patent license to make, have made,
78 | use, offer to sell, sell, import, and otherwise transfer the Work,
79 | where such license applies only to those patent claims licensable
80 | by such Contributor that are necessarily infringed by their
81 | Contribution(s) alone or by combination of their Contribution(s)
82 | with the Work to which such Contribution(s) was submitted. If You
83 | institute patent litigation against any entity (including a
84 | cross-claim or counterclaim in a lawsuit) alleging that the Work
85 | or a Contribution incorporated within the Work constitutes direct
86 | or contributory patent infringement, then any patent licenses
87 | granted to You under this License for that Work shall terminate
88 | as of the date such litigation is filed.
89 |
90 | 4. Redistribution. You may reproduce and distribute copies of the
91 | Work or Derivative Works thereof in any medium, with or without
92 | modifications, and in Source or Object form, provided that You
93 | meet the following conditions:
94 |
95 | (a) You must give any other recipients of the Work or
96 | Derivative Works a copy of this License; and
97 |
98 | (b) You must cause any modified files to carry prominent notices
99 | stating that You changed the files; and
100 |
101 | (c) You must retain, in the Source form of any Derivative Works
102 | that You distribute, all copyright, patent, trademark, and
103 | attribution notices from the Source form of the Work,
104 | excluding those notices that do not pertain to any part of
105 | the Derivative Works; and
106 |
107 | (d) If the Work includes a "NOTICE" text file as part of its
108 | distribution, then any Derivative Works that You distribute must
109 | include a readable copy of the attribution notices contained
110 | within such NOTICE file, excluding those notices that do not
111 | pertain to any part of the Derivative Works, in at least one
112 | of the following places: within a NOTICE text file distributed
113 | as part of the Derivative Works; within the Source form or
114 | documentation, if provided along with the Derivative Works; or,
115 | within a display generated by the Derivative Works, if and
116 | wherever such third-party notices normally appear. The contents
117 | of the NOTICE file are for informational purposes only and
118 | do not modify the License. You may add Your own attribution
119 | notices within Derivative Works that You distribute, alongside
120 | or as an addendum to the NOTICE text from the Work, provided
121 | that such additional attribution notices cannot be construed
122 | as modifying the License.
123 |
124 | You may add Your own copyright statement to Your modifications and
125 | may provide additional or different license terms and conditions
126 | for use, reproduction, or distribution of Your modifications, or
127 | for any such Derivative Works as a whole, provided Your use,
128 | reproduction, and distribution of the Work otherwise complies with
129 | the conditions stated in this License.
130 |
131 | 5. Submission of Contributions. Unless You explicitly state otherwise,
132 | any Contribution intentionally submitted for inclusion in the Work
133 | by You to the Licensor shall be under the terms and conditions of
134 | this License, without any additional terms or conditions.
135 | Notwithstanding the above, nothing herein shall supersede or modify
136 | the terms of any separate license agreement you may have executed
137 | with Licensor regarding such Contributions.
138 |
139 | 6. Trademarks. This License does not grant permission to use the trade
140 | names, trademarks, service marks, or product names of the Licensor,
141 | except as required for reasonable and customary use in describing the
142 | origin of the Work and reproducing the content of the NOTICE file.
143 |
144 | 7. Disclaimer of Warranty. Unless required by applicable law or
145 | agreed to in writing, Licensor provides the Work (and each
146 | Contributor provides its Contributions) on an "AS IS" BASIS,
147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
148 | implied, including, without limitation, any warranties or conditions
149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
150 | PARTICULAR PURPOSE. You are solely responsible for determining the
151 | appropriateness of using or redistributing the Work and assume any
152 | risks associated with Your exercise of permissions under this License.
153 |
154 | 8. Limitation of Liability. In no event and under no legal theory,
155 | whether in tort (including negligence), contract, or otherwise,
156 | unless required by applicable law (such as deliberate and grossly
157 | negligent acts) or agreed to in writing, shall any Contributor be
158 | liable to You for damages, including any direct, indirect, special,
159 | incidental, or consequential damages of any character arising as a
160 | result of this License or out of the use or inability to use the
161 | Work (including but not limited to damages for loss of goodwill,
162 | work stoppage, computer failure or malfunction, or any and all
163 | other commercial damages or losses), even if such Contributor
164 | has been advised of the possibility of such damages.
165 |
166 | 9. Accepting Warranty or Additional Liability. While redistributing
167 | the Work or Derivative Works thereof, You may choose to offer,
168 | and charge a fee for, acceptance of support, warranty, indemnity,
169 | or other liability obligations and/or rights consistent with this
170 | License. However, in accepting such obligations, You may act only
171 | on Your own behalf and on Your sole responsibility, not on behalf
172 | of any other Contributor, and only if You agree to indemnify,
173 | defend, and hold each Contributor harmless for any liability
174 | incurred by, or claims asserted against, such Contributor by reason
175 | of your accepting any such warranty or additional liability.
176 |
177 | END OF TERMS AND CONDITIONS
178 |
179 | APPENDIX: How to apply the Apache License to your work.
180 |
181 | To apply the Apache License to your work, attach the following
182 | boilerplate notice, with the fields enclosed by brackets "[]"
183 | replaced with your own identifying information. (Don't include
184 | the brackets!) The text should be enclosed in the appropriate
185 | comment syntax for the file format. We also recommend that a
186 | file or class name and description of purpose be included on the
187 | same "printed page" as the copyright notice for easier
188 | identification within third-party archives.
189 |
190 | Copyright [yyyy] [name of copyright owner]
191 |
192 | Licensed under the Apache License, Version 2.0 (the "License");
193 | you may not use this file except in compliance with the License.
194 | You may obtain a copy of the License at
195 |
196 | http://www.apache.org/licenses/LICENSE-2.0
197 |
198 | Unless required by applicable law or agreed to in writing, software
199 | distributed under the License is distributed on an "AS IS" BASIS,
200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
201 | See the License for the specific language governing permissions and
202 | limitations under the License.
203 |
--------------------------------------------------------------------------------
/NOTICE:
--------------------------------------------------------------------------------
1 |
2 | LightProto
3 | Copyright 2020 Splunk Inc.
4 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ### IMPORTANT
2 | Starting 21st of February 2024, splunk/lightproto project is archived.
3 | That means Splunk organization is no longer maintaining and supporting lightproto features/project.
4 |
5 | ### Light Proto serialization
6 |
7 | ### Features
8 |
9 | 1. Generate the fastest possible Java code for Protobuf SerDe
10 | 1. 100% Compatible with proto2 definition and wire protocol
11 | 1. Zero-copy deserialization using Netty ByteBuf
12 | 1. Deserialize from direct memory
13 | 1. Zero heap allocations in serialization / deserialization
14 | 1. Lazy deserialization of strings and bytes
15 | 1. Reusable mutable objects
16 | 1. No runtime dependency library
17 | 1. Java based code generator with Maven plugin
18 |
19 | ### Benchmark
20 |
21 | ```
22 | java -jar benchmark/target/benchmarks.jar
23 |
24 | Benchmark Mode Cnt Score Error Units
25 | ProtoBenchmark.lightProtoDeserialize thrpt 3 8.445 ± 1.734 ops/us
26 | ProtoBenchmark.lightProtoSerialize thrpt 3 4.056 ± 1.628 ops/us
27 | ProtoBenchmark.protobufDeserialize thrpt 3 2.465 ± 0.682 ops/us
28 | ProtoBenchmark.protobufSerialize thrpt 3 2.242 ± 0.186 ops/us
29 | SimpleBenchmark.lightProtoDeserialize thrpt 3 37.414 ± 4.980 ops/us
30 | SimpleBenchmark.lightProtoDeserializeReadString thrpt 3 17.367 ± 1.790 ops/us
31 | SimpleBenchmark.lightProtoSerialize thrpt 3 35.473 ± 6.325 ops/us
32 | SimpleBenchmark.protobufDeserialize thrpt 3 8.255 ± 1.104 ops/us
33 | SimpleBenchmark.protobufSerialize thrpt 3 18.960 ± 4.626 ops/us
34 | StringEncodingBenchmark.jdkEncoding thrpt 10 14.031 ± 0.394 ops/us
35 | StringEncodingBenchmark.jdkEncodingAscii thrpt 10 19.279 ± 0.448 ops/us
36 | StringEncodingBenchmark.nettyEncoding thrpt 10 27.273 ± 0.988 ops/us
37 | StringEncodingBenchmark.nettyEncodingAscii thrpt 10 36.140 ± 0.693 ops/us
38 | ```
39 |
--------------------------------------------------------------------------------
/benchmark/pom.xml:
--------------------------------------------------------------------------------
1 |
18 |
21 | 4.0.0
22 |
23 |
24 | com.github.splunk.lightproto
25 | lightproto
26 | 0.5-SNAPSHOT
27 | ..
28 |
29 |
30 | lightproto-benchmark
31 | jar
32 |
33 |
34 |
35 | ${project.groupId}
36 | lightproto-tests
37 | ${project.version}
38 |
39 |
40 | io.netty
41 | netty-buffer
42 |
43 |
44 | org.openjdk.jmh
45 | jmh-core
46 |
47 |
48 | org.openjdk.jmh
49 | jmh-generator-annprocess
50 |
51 |
52 |
53 |
54 |
55 |
56 | org.apache.maven.plugins
57 | maven-shade-plugin
58 | 3.2.1
59 |
60 |
61 | package
62 |
63 | shade
64 |
65 |
66 | benchmarks
67 |
68 |
70 | org.openjdk.jmh.Main
71 |
72 |
73 |
74 |
75 | *:*
76 |
77 | META-INF/*.SF
78 | META-INF/*.DSA
79 | META-INF/*.RSA
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
--------------------------------------------------------------------------------
/benchmark/src/main/java/com/github/splunk/lightproto/benchmark/ProtoBenchmark.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright 2020 Splunk Inc.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.github.splunk.lightproto.benchmark;
17 |
18 | import com.google.protobuf.CodedOutputStream;
19 | import com.github.splunk.lightproto.tests.AddressBook;
20 | import com.github.splunk.lightproto.tests.AddressBookProtos;
21 | import com.github.splunk.lightproto.tests.Person;
22 | import io.netty.buffer.ByteBuf;
23 | import io.netty.buffer.PooledByteBufAllocator;
24 | import io.netty.buffer.Unpooled;
25 | import org.openjdk.jmh.annotations.*;
26 | import org.openjdk.jmh.infra.Blackhole;
27 |
28 | import java.util.concurrent.TimeUnit;
29 |
30 | @State(Scope.Benchmark)
31 | @Warmup(iterations = 3)
32 | @OutputTimeUnit(TimeUnit.MICROSECONDS)
33 | @Measurement(iterations = 3)
34 | @Fork(value = 1)
35 | public class ProtoBenchmark {
36 |
37 | final static byte[] serialized;
38 |
39 | static {
40 | AddressBook ab = new AddressBook();
41 | Person p1 = ab.addPerson();
42 | p1.setName("name");
43 | p1.setEmail("name@example.com");
44 | p1.setId(5);
45 | Person.PhoneNumber p1_pn1 = p1.addPhone();
46 | p1_pn1.setNumber("xxx-zzz-yyyyy");
47 | p1_pn1.setType(Person.PhoneType.HOME);
48 |
49 | Person.PhoneNumber p1_pn2 = p1.addPhone();
50 | p1_pn2.setNumber("xxx-zzz-yyyyy");
51 | p1_pn2.setType(Person.PhoneType.MOBILE);
52 |
53 | Person p2 = ab.addPerson();
54 | p2.setName("name 2");
55 | p2.setEmail("name2@example.com");
56 | p2.setId(6);
57 |
58 | Person.PhoneNumber p2_pn1 = p2.addPhone();
59 | p2_pn1.setNumber("xxx-zzz-yyyyy");
60 | p2_pn1.setType(Person.PhoneType.HOME);
61 |
62 | serialized = new byte[ab.getSerializedSize()];
63 | ab.writeTo(Unpooled.wrappedBuffer(serialized).resetWriterIndex());
64 | }
65 |
66 | private final AddressBook frame = new AddressBook();
67 |
68 | private final ByteBuf buffer = PooledByteBufAllocator.DEFAULT.buffer(1024);
69 | byte[] data = new byte[1024];
70 | private final ByteBuf serializeByteBuf = Unpooled.wrappedBuffer(serialized);
71 |
72 | @Benchmark
73 | public void protobufSerialize(Blackhole bh) throws Exception {
74 | AddressBookProtos.AddressBook.Builder pbab = AddressBookProtos.AddressBook.newBuilder();
75 | AddressBookProtos.Person.Builder pb_p1 = AddressBookProtos.Person.newBuilder();
76 | pb_p1.setName("name 1");
77 | pb_p1.setEmail("name1@example.com");
78 | pb_p1.setId(5);
79 | AddressBookProtos.Person.PhoneNumber.Builder pb1_pn1 = AddressBookProtos.Person.PhoneNumber.newBuilder();
80 | pb1_pn1.setNumber("xxx-zzz-1111");
81 | pb1_pn1.setType(AddressBookProtos.Person.PhoneType.HOME);
82 |
83 | AddressBookProtos.Person.PhoneNumber.Builder pb1_pn2 = AddressBookProtos.Person.PhoneNumber.newBuilder();
84 | pb1_pn2.setNumber("xxx-zzz-2222");
85 | pb1_pn2.setType(AddressBookProtos.Person.PhoneType.MOBILE);
86 |
87 | pb_p1.addPhone(pb1_pn1);
88 | pb_p1.addPhone(pb1_pn2);
89 |
90 | AddressBookProtos.Person.Builder pb_p2 = AddressBookProtos.Person.newBuilder();
91 | pb_p2.setName("name 2");
92 | pb_p2.setEmail("name2@example.com");
93 | pb_p2.setId(6);
94 |
95 | AddressBookProtos.Person.PhoneNumber.Builder pb2_pn1 = AddressBookProtos.Person.PhoneNumber.newBuilder();
96 | pb2_pn1.setNumber("xxx-zzz-2222");
97 | pb2_pn1.setType(AddressBookProtos.Person.PhoneType.HOME);
98 |
99 | pb_p2.addPhone(pb2_pn1);
100 |
101 | pbab.addPerson(pb_p1);
102 | pbab.addPerson(pb_p2);
103 |
104 | CodedOutputStream s = CodedOutputStream.newInstance(data);
105 | pbab.build().writeTo(s);
106 |
107 | bh.consume(pbab);
108 | bh.consume(s);
109 | }
110 |
111 | @Benchmark
112 | public void lightProtoSerialize(Blackhole bh) {
113 | frame.clear();
114 |
115 | Person p1 = frame.addPerson();
116 | p1.setName("name");
117 | p1.setEmail("name@example.com");
118 | p1.setId(5);
119 | Person.PhoneNumber p1_pn1 = p1.addPhone();
120 | p1_pn1.setNumber("xxx-zzz-yyyyy");
121 | p1_pn1.setType(Person.PhoneType.HOME);
122 |
123 | Person.PhoneNumber p1_pn2 = p1.addPhone();
124 | p1_pn2.setNumber("xxx-zzz-yyyyy");
125 | p1_pn2.setType(Person.PhoneType.MOBILE);
126 |
127 | Person p2 = frame.addPerson();
128 | p2.setName("name 2");
129 | p2.setEmail("name2@example.com");
130 | p2.setId(6);
131 |
132 | Person.PhoneNumber p2_pn1 = p1.addPhone();
133 | p2_pn1.setNumber("xxx-zzz-yyyyy");
134 | p2_pn1.setType(Person.PhoneType.HOME);
135 |
136 | frame.writeTo(buffer);
137 | buffer.clear();
138 |
139 | bh.consume(frame);
140 | }
141 |
142 | @Benchmark
143 | public void protobufDeserialize(Blackhole bh) throws Exception {
144 | AddressBookProtos.AddressBook ab = AddressBookProtos.AddressBook.newBuilder().mergeFrom(serialized).build();
145 | bh.consume(ab);
146 | }
147 |
148 | @Benchmark
149 | public void lightProtoDeserialize(Blackhole bh) {
150 | frame.parseFrom(serializeByteBuf, serializeByteBuf.readableBytes());
151 | serializeByteBuf.resetReaderIndex();
152 | bh.consume(frame);
153 | }
154 |
155 |
156 | }
157 |
--------------------------------------------------------------------------------
/benchmark/src/main/java/com/github/splunk/lightproto/benchmark/SimpleBenchmark.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright 2020 Splunk Inc.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.github.splunk.lightproto.benchmark;
17 |
18 | import com.google.protobuf.CodedOutputStream;
19 | import com.github.splunk.lightproto.tests.Frame;
20 | import com.github.splunk.lightproto.tests.Point;
21 | import com.github.splunk.lightproto.tests.Test;
22 | import io.netty.buffer.ByteBuf;
23 | import io.netty.buffer.PooledByteBufAllocator;
24 | import io.netty.buffer.Unpooled;
25 | import org.openjdk.jmh.annotations.*;
26 | import org.openjdk.jmh.infra.Blackhole;
27 |
28 | import java.io.IOException;
29 | import java.util.concurrent.TimeUnit;
30 |
31 | @State(Scope.Benchmark)
32 | @Warmup(iterations = 3)
33 | @OutputTimeUnit(TimeUnit.MICROSECONDS)
34 | @Measurement(iterations = 3)
35 | @Fork(value = 1)
36 | public class SimpleBenchmark {
37 |
38 | final static byte[] serialized;
39 |
40 | static {
41 | Test.Point.Builder b = Test.Point.newBuilder();
42 | b.setX(1);
43 | b.setY(2);
44 | b.setZ(3);
45 |
46 | Test.Frame.Builder frameBuilder = Test.Frame.newBuilder();
47 | frameBuilder.setName("xyz");
48 | frameBuilder.setPoint(b.build());
49 |
50 | Test.Frame frame = frameBuilder.build();
51 | int size = frame.getSerializedSize();
52 |
53 | serialized = new byte[size];
54 | CodedOutputStream s = CodedOutputStream.newInstance(serialized);
55 | try {
56 | frame.writeTo(s);
57 | } catch (IOException ignored) {
58 | }
59 | }
60 |
61 | byte[] data = new byte[1024];
62 | Frame frame = new Frame();
63 | ByteBuf buffer = PooledByteBufAllocator.DEFAULT.buffer(1024);
64 | private final ByteBuf serializeByteBuf = Unpooled.wrappedBuffer(serialized);
65 |
66 | @Benchmark
67 | public void protobufSerialize(Blackhole bh) throws Exception {
68 | Test.Point.Builder b = Test.Point.newBuilder();
69 | b.setX(1);
70 | b.setY(2);
71 | b.setZ(3);
72 |
73 | Test.Frame.Builder frameBuilder = Test.Frame.newBuilder();
74 | frameBuilder.setName("xyz");
75 | frameBuilder.setPoint(b.build());
76 |
77 | Test.Frame frame = frameBuilder.build();
78 |
79 | CodedOutputStream s = CodedOutputStream.newInstance(data);
80 | frame.writeTo(s);
81 | bh.consume(b);
82 | bh.consume(s);
83 | bh.consume(frame);
84 | }
85 |
86 | @Benchmark
87 | public void lightProtoSerialize(Blackhole bh) {
88 | frame.clear();
89 | Point p = frame.setPoint();
90 | p.setX(1);
91 | p.setY(2);
92 | p.setZ(3);
93 | frame.setName("xyz");
94 |
95 | p.writeTo(buffer);
96 | buffer.clear();
97 |
98 | bh.consume(p);
99 | }
100 |
101 | @Benchmark
102 | public void protobufDeserialize(Blackhole bh) throws Exception {
103 | Test.Frame.Builder b = Test.Frame.newBuilder().mergeFrom(serialized);
104 | Test.Frame f = b.build();
105 | f.getName();
106 | bh.consume(f);
107 | }
108 |
109 | @Benchmark
110 | public void lightProtoDeserialize(Blackhole bh) {
111 | frame.parseFrom(serializeByteBuf, serializeByteBuf.readableBytes());
112 | serializeByteBuf.resetReaderIndex();
113 | bh.consume(frame);
114 | }
115 |
116 | @Benchmark
117 | public void lightProtoDeserializeReadString(Blackhole bh) {
118 | frame.parseFrom(serializeByteBuf, serializeByteBuf.readableBytes());
119 | bh.consume(frame.getName());
120 | serializeByteBuf.resetReaderIndex();
121 | }
122 |
123 | }
124 |
--------------------------------------------------------------------------------
/benchmark/src/main/java/com/github/splunk/lightproto/benchmark/StringEncodingBenchmark.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright 2020 Splunk Inc.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.github.splunk.lightproto.benchmark;
17 |
18 | import java.nio.charset.StandardCharsets;
19 | import java.util.concurrent.TimeUnit;
20 |
21 | import org.openjdk.jmh.annotations.Benchmark;
22 | import org.openjdk.jmh.annotations.Fork;
23 | import org.openjdk.jmh.annotations.Measurement;
24 | import org.openjdk.jmh.annotations.OutputTimeUnit;
25 | import org.openjdk.jmh.annotations.Scope;
26 | import org.openjdk.jmh.annotations.State;
27 | import org.openjdk.jmh.annotations.Warmup;
28 | import org.openjdk.jmh.infra.Blackhole;
29 |
30 | import io.netty.buffer.ByteBuf;
31 | import io.netty.buffer.ByteBufAllocator;
32 | import io.netty.buffer.ByteBufUtil;
33 |
34 | @State(Scope.Benchmark)
35 | @Warmup(iterations = 3)
36 | @OutputTimeUnit(TimeUnit.MICROSECONDS)
37 | @Measurement(iterations = 10)
38 | @Fork(value = 1)
39 | public class StringEncodingBenchmark {
40 |
41 | private static final String testString = "UTF16 Ελληνικά Русский 日本語";
42 | private static final String testStringAscii = "Neque porro quisquam est qui dolorem ipsum";
43 |
44 | @Benchmark
45 | public void jdkEncoding(Blackhole bh) {
46 | byte[] bytes = testString.getBytes(StandardCharsets.UTF_8);
47 | bh.consume(bytes);
48 | }
49 |
50 | ByteBuf buffer = ByteBufAllocator.DEFAULT.buffer(1024);
51 |
52 | @Benchmark
53 | public void nettyEncoding(Blackhole bh) {
54 | buffer.clear();
55 | ByteBufUtil.writeUtf8(buffer, testString);
56 | bh.consume(buffer);
57 | }
58 |
59 | @Benchmark
60 | public void jdkEncodingAscii(Blackhole bh) {
61 | byte[] bytes = testStringAscii.getBytes(StandardCharsets.UTF_8);
62 | bh.consume(bytes);
63 | }
64 |
65 | @Benchmark
66 | public void nettyEncodingAscii(Blackhole bh) {
67 | buffer.clear();
68 | ByteBufUtil.writeUtf8(buffer, testStringAscii);
69 | bh.consume(buffer);
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/code-generator/pom.xml:
--------------------------------------------------------------------------------
1 |
18 |
20 | 4.0.0
21 |
22 |
23 | com.github.splunk.lightproto
24 | lightproto
25 | 0.5-SNAPSHOT
26 | ..
27 |
28 |
29 | lightproto-code-generator
30 | jar
31 |
32 |
33 |
34 | io.protostuff
35 | protostuff-parser
36 |
37 |
38 |
39 | org.slf4j
40 | slf4j-api
41 |
42 |
43 |
44 | com.google.guava
45 | guava
46 |
47 |
48 |
49 | org.jibx
50 | jibx-tools
51 |
52 |
53 |
54 | org.jboss.forge.roaster
55 | roaster-api
56 |
57 |
58 | org.jboss.forge.roaster
59 | roaster-jdt
60 | runtime
61 |
62 |
63 |
64 |
--------------------------------------------------------------------------------
/code-generator/src/main/java/com/github/splunk/lightproto/generator/LightProto.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright 2020 Splunk Inc.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.github.splunk.lightproto.generator;
17 |
18 | import io.protostuff.parser.Proto;
19 | import org.jboss.forge.roaster.Roaster;
20 | import org.slf4j.Logger;
21 | import org.slf4j.LoggerFactory;
22 |
23 | import java.io.*;
24 | import java.nio.file.Files;
25 | import java.util.ArrayList;
26 | import java.util.Collections;
27 | import java.util.List;
28 | import java.util.stream.Collectors;
29 |
30 | public class LightProto {
31 |
32 | private static final Logger log = LoggerFactory.getLogger(LightProto.class);
33 | private final Proto proto;
34 | private final String outerClassName;
35 | private final boolean useOuterClass;
36 | private final List enums;
37 | private final List messages;
38 |
39 | public LightProto(Proto proto, String outerClassName, boolean useOuterClass) {
40 | this.proto = proto;
41 | this.outerClassName = outerClassName;
42 | this.useOuterClass = useOuterClass;
43 | this.enums = proto.getEnumGroups().stream().map(LightProtoEnum::new).collect(Collectors.toList());
44 | this.messages = proto.getMessages().stream().map(m -> new LightProtoMessage(m, useOuterClass)).collect(Collectors.toList());
45 | }
46 |
47 | public List generate(File directory) throws IOException {
48 | directory.mkdirs();
49 |
50 | if (useOuterClass) {
51 | return generateWithSingleOuterClass(directory);
52 | } else {
53 | return generateIndividualClasses(directory);
54 | }
55 | }
56 |
57 | public List generateIndividualClasses(File outDirectory) throws IOException {
58 | List generatedFiles = new ArrayList<>();
59 | for (LightProtoEnum e : enums) {
60 | File file = new File(outDirectory, e.getName() + ".java");
61 | StringWriter sw = new StringWriter();
62 | try (PrintWriter pw = new PrintWriter(sw)) {
63 | pw.format("package %s;\n", proto.getJavaPackageName());
64 | e.generate(pw);
65 | }
66 |
67 | formatAndWrite(file, sw.toString());
68 | log.info("LightProto generated enum {}", file);
69 | generatedFiles.add(file);
70 | }
71 |
72 | for (LightProtoMessage m : messages) {
73 | File file = new File(outDirectory, m.getName() + ".java");
74 | StringWriter sw = new StringWriter();
75 | try (PrintWriter pw = new PrintWriter(sw)) {
76 | pw.format("package %s;\n", proto.getJavaPackageName());
77 | m.generate(pw);
78 | }
79 |
80 | formatAndWrite(file, sw.toString());
81 | log.info("LightProto generated class {}", file);
82 | generatedFiles.add(file);
83 | }
84 |
85 | return generatedFiles;
86 | }
87 |
88 | public List generateWithSingleOuterClass(File outDirectory) throws IOException {
89 | File outFile = new File(outDirectory, outerClassName + ".java");
90 |
91 | StringWriter sw = new StringWriter();
92 | try (PrintWriter pw = new PrintWriter(sw)) {
93 | pw.format("package %s;\n", proto.getJavaPackageName());
94 | pw.format("public final class %s {\n", outerClassName);
95 | pw.format(" private %s() {}\n", outerClassName);
96 |
97 | enums.forEach(e -> e.generate(pw));
98 | messages.forEach(m -> m.generate(pw));
99 |
100 | pw.println("}");
101 | }
102 |
103 | formatAndWrite(outFile, sw.toString());
104 |
105 | log.info("LightProto generated {}", outFile);
106 | return Collections.singletonList(outFile);
107 | }
108 |
109 | private void formatAndWrite(File file, String content) throws IOException {
110 | String formattedCode = Roaster.format(content);
111 | try (Writer w = Files.newBufferedWriter(file.toPath())) {
112 | w.write(formattedCode);
113 | }
114 | }
115 | }
116 |
--------------------------------------------------------------------------------
/code-generator/src/main/java/com/github/splunk/lightproto/generator/LightProtoAbstractRepeated.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright 2020 Splunk Inc.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.github.splunk.lightproto.generator;
17 |
18 | import io.protostuff.parser.Field;
19 |
20 | import java.io.PrintWriter;
21 |
22 | public abstract class LightProtoAbstractRepeated> extends LightProtoField {
23 |
24 | protected final String pluralName;
25 | protected final String singularName;
26 |
27 | public LightProtoAbstractRepeated(FieldType field, int index) {
28 | super(field, index);
29 | this.pluralName = Util.plural(ccName);
30 | this.singularName = Util.singular(ccName);
31 | }
32 |
33 | public void has(PrintWriter w) {
34 | }
35 |
36 | public void fieldClear(PrintWriter w, String enclosingType) {
37 | w.format(" public %s %s() {\n", enclosingType, Util.camelCase("clear", field.getName()));
38 | clear(w);
39 | w.format(" return this;\n");
40 | w.format(" }\n");
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/code-generator/src/main/java/com/github/splunk/lightproto/generator/LightProtoBooleanField.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright 2020 Splunk Inc.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.github.splunk.lightproto.generator;
17 |
18 | import io.protostuff.parser.Field;
19 |
20 | import java.io.PrintWriter;
21 |
22 | public class LightProtoBooleanField extends LightProtoNumberField {
23 |
24 | public LightProtoBooleanField(Field> field, int index) {
25 | super(field, index);
26 | }
27 |
28 | @Override
29 | public void getter(PrintWriter w) {
30 | w.format(" public %s %s() {\n", field.getJavaType(), Util.camelCase("is", ccName));
31 | if (!field.isDefaultValueSet()) {
32 | w.format(" if (!%s()) {\n", Util.camelCase("has", ccName));
33 | w.format(" throw new IllegalStateException(\"Field '%s' is not set\");\n", field.getName());
34 | w.format(" }\n");
35 | }
36 | w.format(" return %s;\n", ccName);
37 | w.format(" }\n");
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/code-generator/src/main/java/com/github/splunk/lightproto/generator/LightProtoBytesField.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright 2020 Splunk Inc.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.github.splunk.lightproto.generator;
17 |
18 | import io.protostuff.parser.Field;
19 |
20 | import java.io.PrintWriter;
21 |
22 | public class LightProtoBytesField extends LightProtoField {
23 |
24 | public LightProtoBytesField(Field.Bytes field, int index) {
25 | super(field, index);
26 | }
27 |
28 | @Override
29 | public void declaration(PrintWriter w) {
30 | w.format("private io.netty.buffer.ByteBuf %s = null;\n", ccName);
31 | w.format("private int _%sIdx = -1;\n", ccName);
32 | w.format("private int _%sLen = -1;\n", ccName);
33 | }
34 |
35 | @Override
36 | public void parse(PrintWriter w) {
37 | w.format("_%sLen = LightProtoCodec.readVarInt(_buffer);\n", ccName);
38 | w.format("_%sIdx = _buffer.readerIndex();\n", ccName);
39 | w.format("_buffer.skipBytes(_%sLen);\n", ccName);
40 | }
41 |
42 | @Override
43 | public void copy(PrintWriter w) {
44 | w.format("%s(_other.%s());\n", Util.camelCase("set", ccName), Util.camelCase("get", ccName));
45 | }
46 |
47 | @Override
48 | public void setter(PrintWriter w, String enclosingType) {
49 | w.format("public %s %s(byte[] %s) {\n", enclosingType, Util.camelCase("set", ccName), ccName);
50 | w.format(" %s(io.netty.buffer.Unpooled.wrappedBuffer(%s));\n", Util.camelCase("set", ccName), ccName);
51 | w.format(" return this;\n");
52 | w.format("}\n");
53 |
54 | w.format("public %s %s(io.netty.buffer.ByteBuf %s) {\n", enclosingType, Util.camelCase("set", ccName), ccName);
55 | w.format(" this.%s = %s;\n", ccName, ccName);
56 | w.format(" _bitField%d |= %s;\n", bitFieldIndex(), fieldMask());
57 | w.format(" _%sIdx = -1;\n", ccName);
58 | w.format(" _%sLen = %s.readableBytes();\n", ccName, ccName);
59 | w.format(" _cachedSize = -1;\n");
60 | w.format(" return this;\n");
61 | w.format("}\n");
62 | }
63 |
64 | @Override
65 | public void getter(PrintWriter w) {
66 | w.format("public int %s() {\n", Util.camelCase("get", ccName, "size"));
67 | w.format(" if (!%s()) {\n", Util.camelCase("has", ccName));
68 | w.format(" throw new IllegalStateException(\"Field '%s' is not set\");\n", field.getName());
69 | w.format(" }\n");
70 | w.format(" return _%sLen;\n", ccName);
71 | w.format("}\n");
72 |
73 | w.format("public byte[] %s() {\n", Util.camelCase("get", ccName));
74 | w.format(" io.netty.buffer.ByteBuf _b = %s();\n", Util.camelCase("get", ccName, "slice"));
75 | w.format(" byte[] res = new byte[_b.readableBytes()];\n");
76 | w.format(" _b.getBytes(0, res);\n");
77 | w.format(" return res;\n");
78 | w.format("}\n");
79 |
80 | w.format("public io.netty.buffer.ByteBuf %s() {\n", Util.camelCase("get", ccName, "slice"));
81 | w.format(" if (!%s()) {\n", Util.camelCase("has", ccName));
82 | w.format(" throw new IllegalStateException(\"Field '%s' is not set\");\n", field.getName());
83 | w.format(" }\n");
84 | w.format(" if (%s == null) {\n", ccName);
85 | w.format(" return _parsedBuffer.slice(_%sIdx, _%sLen);\n", ccName, ccName);
86 | w.format(" } else {\n");
87 | w.format(" return %s.slice(0, _%sLen);\n", ccName, ccName);
88 | w.format(" }\n");
89 | w.format("}\n");
90 | }
91 |
92 | @Override
93 | public void clear(PrintWriter w) {
94 | w.format("%s = null;\n", ccName);
95 | w.format("_%sIdx = -1;\n", ccName);
96 | w.format("_%sLen = -1;\n", ccName);
97 | }
98 |
99 | @Override
100 | public void serializedSize(PrintWriter w) {
101 | w.format("_size += %s_SIZE;\n", tagName());
102 | w.format("_size += LightProtoCodec.computeVarIntSize(_%sLen) + _%sLen;\n", ccName, ccName);
103 | }
104 |
105 | @Override
106 | public void serialize(PrintWriter w) {
107 | w.format("LightProtoCodec.writeVarInt(_b, %s);\n", tagName());
108 | w.format("LightProtoCodec.writeVarInt(_b, _%sLen);\n", ccName);
109 |
110 | w.format("if (_%sIdx == -1) {\n", ccName);
111 | w.format(" _b.writeBytes(%s);\n", ccName);
112 | w.format("} else {\n");
113 | w.format(" _parsedBuffer.getBytes(_%sIdx, _b, _%sLen);\n", ccName, ccName);
114 | w.format("}\n");
115 | }
116 |
117 |
118 | @Override
119 | protected String typeTag() {
120 | return "LightProtoCodec.WIRETYPE_LENGTH_DELIMITED";
121 | }
122 | }
123 |
--------------------------------------------------------------------------------
/code-generator/src/main/java/com/github/splunk/lightproto/generator/LightProtoEnum.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright 2020 Splunk Inc.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.github.splunk.lightproto.generator;
17 |
18 | import io.protostuff.parser.EnumGroup;
19 |
20 | import java.io.PrintWriter;
21 |
22 | public class LightProtoEnum {
23 | private final EnumGroup eg;
24 |
25 | public LightProtoEnum(EnumGroup eg) {
26 | this.eg = eg;
27 | }
28 |
29 | public String getName() {
30 | return eg.getName();
31 | }
32 |
33 | public void generate(PrintWriter w) {
34 | w.format(" public enum %s {\n", eg.getName());
35 | eg.getSortedValues().forEach(v ->
36 | w.format(" %s(%d),\n", v.getName(), v.getNumber()));
37 | w.println(" ;");
38 | w.println(" private final int value;");
39 | w.format(" private %s(int value) {\n", eg.getName());
40 | w.println(" this.value = value;");
41 | w.println(" }");
42 | w.println(" public int getValue() {");
43 | w.println(" return value;");
44 | w.println(" }");
45 |
46 | w.format(" public static %s valueOf(int n) {\n", eg.getName());
47 | w.format(" switch (n) {\n");
48 | eg.getSortedValues().forEach(v ->
49 | w.format(" case %d: return %s;\n", v.getNumber(), v.getName()));
50 | w.println(" default: return null;\n");
51 | w.println(" }");
52 | w.println(" }");
53 | eg.getSortedValues().forEach(v ->
54 | w.format(" public static final int %s_VALUE = %d;\n", v.getName(), v.getNumber()));
55 | w.println(" }");
56 | w.println();
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/code-generator/src/main/java/com/github/splunk/lightproto/generator/LightProtoEnumField.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright 2020 Splunk Inc.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.github.splunk.lightproto.generator;
17 |
18 | import io.protostuff.parser.Field;
19 |
20 | import java.io.PrintWriter;
21 |
22 | public class LightProtoEnumField extends LightProtoNumberField {
23 |
24 | public LightProtoEnumField(Field> field, int index) {
25 | super(field, index);
26 | }
27 |
28 | @Override
29 | public void parse(PrintWriter w) {
30 | w.format("%s _%s = %s;\n", field.getJavaType(), ccName, parseNumber(field));
31 | w.format("if (_%s != null) {\n", ccName);
32 | w.format(" _bitField%d |= %s;\n", bitFieldIndex(), fieldMask());
33 | w.format(" %s = _%s;\n", ccName, ccName);
34 | w.format("}\n");
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/code-generator/src/main/java/com/github/splunk/lightproto/generator/LightProtoField.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright 2020 Splunk Inc.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.github.splunk.lightproto.generator;
17 |
18 | import io.protostuff.parser.Field;
19 | import io.protostuff.parser.MessageField;
20 |
21 | import java.io.PrintWriter;
22 |
23 | public abstract class LightProtoField> {
24 |
25 | protected final FieldType field;
26 | protected final int index;
27 | protected final String ccName;
28 |
29 | protected LightProtoField(FieldType field, int index) {
30 | this.field = field;
31 | this.index = index;
32 | this.ccName = Util.camelCase(field.getName());
33 | }
34 |
35 | public static LightProtoField create(Field field, int index) {
36 | if (field.isRepeated()) {
37 | if (field.isMessageField()) {
38 | return new LightProtoRepeatedMessageField((MessageField) field, index);
39 | } else if (field.isStringField()) {
40 | return new LightProtoRepeatedStringField((Field.String) field, index);
41 | } else if (field.isEnumField()) {
42 | return new LightProtoRepeatedEnumField(field, index);
43 | } else if (field.isNumberField() || field.isBoolField()) {
44 | return new LightProtoRepeatedNumberField(field, index);
45 | } else if (field.isBytesField()) {
46 | return new LightProtoRepeatedBytesField((Field.Bytes) field, index);
47 | }
48 | } else if (field.isMessageField()) {
49 | return new LightProtoMessageField((MessageField) field, index);
50 | } else if (field.isBytesField()) {
51 | return new LightProtoBytesField((Field.Bytes) field, index);
52 | } else if (field.isStringField()) {
53 | return new LightProtoStringField((Field.String) field, index);
54 | } else if (field.isEnumField()) {
55 | return new LightProtoEnumField(field, index);
56 | } else if (field.isNumberField()) {
57 | return new LightProtoNumberField(field, index);
58 | } else if (field.isBoolField()) {
59 | return new LightProtoBooleanField(field, index);
60 | }
61 |
62 | throw new IllegalArgumentException("Unknown field: " + field);
63 | }
64 |
65 | public int index() {
66 | return index;
67 | }
68 |
69 | public boolean isRepeated() {
70 | return field.isRepeated();
71 | }
72 |
73 | public boolean isEnum() {
74 | return field.isEnumField();
75 | }
76 |
77 | public boolean isRequired() {
78 | return field.isRequired();
79 | }
80 |
81 | public void docs(PrintWriter w) {
82 | field.getDocs().forEach(d -> w.format(" // %s\n", d));
83 | }
84 |
85 | abstract public void declaration(PrintWriter w);
86 |
87 | public void tags(PrintWriter w) {
88 | w.format(" private static final int %s = %d;\n", fieldNumber(), field.getNumber());
89 | w.format(" private static final int %s = (%s << LightProtoCodec.TAG_TYPE_BITS) | %s;\n", tagName(), fieldNumber(), typeTag());
90 | w.format(" private static final int %s_SIZE = LightProtoCodec.computeVarIntSize(%s);\n", tagName(), tagName());
91 | if (!field.isRepeated()) {
92 | w.format(" private static final int %s = 1 << (%d %% 32);\n", fieldMask(), index);
93 | }
94 | }
95 |
96 | public void has(PrintWriter w) {
97 | w.format(" public boolean %s() {\n", Util.camelCase("has", field.getName()));
98 | w.format(" return (_bitField%d & %s) != 0;\n", bitFieldIndex(), fieldMask());
99 | w.format(" }\n");
100 | }
101 |
102 | abstract public void clear(PrintWriter w);
103 |
104 | public void fieldClear(PrintWriter w, String enclosingType) {
105 | w.format(" public %s %s() {\n", enclosingType, Util.camelCase("clear", field.getName()));
106 | w.format(" _bitField%d &= ~%s;\n", bitFieldIndex(), fieldMask());
107 | clear(w);
108 | w.format(" return this;\n");
109 | w.format(" }\n");
110 | }
111 |
112 | abstract public void setter(PrintWriter w, String enclosingType);
113 |
114 | abstract public void getter(PrintWriter w);
115 |
116 | abstract public void serializedSize(PrintWriter w);
117 |
118 | abstract public void serialize(PrintWriter w);
119 |
120 | abstract public void parse(PrintWriter w);
121 |
122 | abstract public void copy(PrintWriter w);
123 |
124 | public boolean isPackable() {
125 | return field.isRepeated() && field.isPackable();
126 | }
127 |
128 | public void parsePacked(PrintWriter w) {
129 | }
130 |
131 | abstract protected String typeTag();
132 |
133 | protected String tagName() {
134 | return "_" + Util.upperCase(field.getName(), "tag");
135 | }
136 |
137 | protected String fieldNumber() {
138 | return "_" + Util.upperCase(field.getName(), "fieldNumber");
139 | }
140 |
141 | protected String fieldMask() {
142 | return "_" + Util.upperCase(field.getName(), "mask");
143 | }
144 |
145 | protected int bitFieldIndex() {
146 | return index / 32;
147 | }
148 | }
149 |
--------------------------------------------------------------------------------
/code-generator/src/main/java/com/github/splunk/lightproto/generator/LightProtoGenerator.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright 2020 Splunk Inc.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.github.splunk.lightproto.generator;
17 |
18 | import com.google.common.base.Joiner;
19 | import com.google.common.base.Splitter;
20 | import io.protostuff.parser.Proto;
21 | import io.protostuff.parser.ProtoUtil;
22 | import org.jboss.forge.roaster.Roaster;
23 | import org.jboss.forge.roaster.model.source.JavaClassSource;
24 | import org.slf4j.Logger;
25 | import org.slf4j.LoggerFactory;
26 |
27 | import java.io.*;
28 | import java.nio.file.Files;
29 | import java.nio.file.Path;
30 | import java.nio.file.Paths;
31 | import java.util.*;
32 |
33 | public class LightProtoGenerator {
34 |
35 | public static List generate(List inputs, File outputDirectory,
36 | String classPrefix, boolean useOuterClass) throws Exception {
37 | List generatedFiles = new ArrayList<>();
38 | Set javaPackages = new HashSet<>();
39 |
40 | for (File input : inputs) {
41 | Proto proto = new Proto();
42 | ProtoUtil.loadFrom(input, proto);
43 |
44 | String fileWithoutExtension = Splitter.on(".").splitToList(input.getName()).get(0);
45 | String outerClassName = Util.camelCaseFirstUpper(classPrefix, fileWithoutExtension);
46 |
47 | String javaPackageName = proto.getJavaPackageName();
48 | String javaDir = Joiner.on('/').join(javaPackageName.split("\\."));
49 | Path targetDir = Paths.get(String.format("%s/%s", outputDirectory, javaDir));
50 |
51 | LightProto lightProto = new LightProto(proto, outerClassName, useOuterClass);
52 | generatedFiles.addAll(lightProto.generate(targetDir.toFile()));
53 |
54 | javaPackages.add(javaPackageName);
55 | }
56 |
57 | // Include the coded class once per every generated java package
58 | for (String javaPackage : javaPackages) {
59 | try (InputStream is = LightProtoGenerator.class.getResourceAsStream("/com/github/splunk/lightproto/generator/LightProtoCodec.java")) {
60 | JavaClassSource codecClass = (JavaClassSource) Roaster.parse(is);
61 | codecClass.setPackage(javaPackage);
62 |
63 | String javaDir = Joiner.on('/').join(javaPackage.split("\\."));
64 | Path codecFile = Paths.get(String.format("%s/%s/LightProtoCodec.java", outputDirectory, javaDir));
65 | try (Writer w = Files.newBufferedWriter(codecFile)) {
66 | w.write(codecClass.toString());
67 | }
68 | }
69 | }
70 |
71 | return generatedFiles;
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/code-generator/src/main/java/com/github/splunk/lightproto/generator/LightProtoMessage.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright 2020 Splunk Inc.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.github.splunk.lightproto.generator;
17 |
18 | import io.protostuff.parser.Message;
19 |
20 | import java.io.PrintWriter;
21 | import java.util.ArrayList;
22 | import java.util.List;
23 | import java.util.stream.Collectors;
24 |
25 | public class LightProtoMessage {
26 |
27 | private final Message message;
28 | private final boolean isNested;
29 | private final List enums;
30 | private final List fields;
31 | private final List nestedMessages;
32 |
33 | public LightProtoMessage(Message message, boolean isNested) {
34 | this.message = message;
35 | this.isNested = isNested;
36 | this.enums = message.getNestedEnumGroups().stream().map(LightProtoEnum::new).collect(Collectors.toList());
37 | this.nestedMessages = message.getNestedMessages().stream().map(m -> new LightProtoMessage(m, true)).collect(Collectors.toList());
38 |
39 | this.fields = new ArrayList<>();
40 | for (int i = 0; i < message.getFields().size(); i++) {
41 | fields.add(LightProtoField.create(message.getFields().get(i), i));
42 | }
43 | }
44 |
45 | public String getName() {
46 | return message.getName();
47 | }
48 |
49 | public void generate(PrintWriter w) {
50 | w.format(" public %s final class %s {\n", isNested ? "static" : "", message.getName());
51 |
52 | enums.forEach(e -> e.generate(w));
53 | nestedMessages.forEach(nm -> nm.generate(w));
54 | fields.forEach(field -> {
55 | field.docs(w);
56 | field.declaration(w);
57 | field.tags(w);
58 | field.has(w);
59 | field.getter(w);
60 | field.setter(w, message.getName());
61 | field.fieldClear(w, message.getName());
62 | w.println();
63 | });
64 |
65 | generateBitFields(w);
66 | generateSerialize(w);
67 | generateGetSerializedSize(w);
68 | generateParseFrom(w);
69 | generateCheckRequiredFields(w);
70 | generateClear(w);
71 | generateCopyFrom(w);
72 |
73 | w.println(" public byte[] toByteArray() {");
74 | w.println(" byte[] a = new byte[getSerializedSize()];");
75 | w.println(" io.netty.buffer.ByteBuf b = io.netty.buffer.Unpooled.wrappedBuffer(a).writerIndex(0);");
76 | w.println(" this.writeTo(b);");
77 | w.println(" return a;");
78 | w.println(" }");
79 |
80 | w.println(" public void parseFrom(byte[] a) {");
81 | w.println(" io.netty.buffer.ByteBuf b = io.netty.buffer.Unpooled.wrappedBuffer(a);");
82 | w.println(" this.parseFrom(b, b.readableBytes());");
83 | w.println(" }");
84 |
85 | w.println(" private int _cachedSize;\n");
86 | w.println(" private io.netty.buffer.ByteBuf _parsedBuffer;\n");
87 | w.println(" }");
88 | w.println();
89 | }
90 |
91 | private void generateParseFrom(PrintWriter w) {
92 | w.format(" public void parseFrom(io.netty.buffer.ByteBuf _buffer, int _size) {\n");
93 | w.format(" clear();\n");
94 | w.format(" int _endIdx = _buffer.readerIndex() + _size;\n");
95 | w.format(" while (_buffer.readerIndex() < _endIdx) {\n");
96 | w.format(" int _tag = LightProtoCodec.readVarInt(_buffer);\n");
97 | w.format(" switch (_tag) {\n");
98 |
99 | for (LightProtoField field : fields) {
100 | w.format(" case %s:\n", field.tagName());
101 | if (!field.isRepeated() && !field.isEnum()) {
102 | w.format(" _bitField%d |= %s;\n", field.bitFieldIndex(), field.fieldMask());
103 | }
104 | field.parse(w);
105 | w.format(" break;\n");
106 | }
107 |
108 | for (LightProtoField field : fields) {
109 | if (field.isPackable()) {
110 | w.format(" case %s_PACKED:\n", field.tagName());
111 | field.parsePacked(w);
112 | w.format(" break;\n");
113 | }
114 | }
115 |
116 | w.format(" default:\n");
117 | w.format(" LightProtoCodec.skipUnknownField(_tag, _buffer);\n");
118 | w.format(" }\n");
119 | w.format(" }\n");
120 | if (hasRequiredFields()) {
121 | w.format(" checkRequiredFields();\n");
122 | }
123 | w.format(" _parsedBuffer = _buffer;\n");
124 | w.format(" }\n");
125 | }
126 |
127 | private void generateClear(PrintWriter w) {
128 | w.format(" public %s clear() {\n", message.getName());
129 | for (LightProtoField f : fields) {
130 | f.clear(w);
131 | }
132 |
133 | w.format(" _parsedBuffer = null;\n");
134 | w.format(" _cachedSize = -1;\n");
135 | for (int i = 0; i < bitFieldsCount(); i++) {
136 | w.format(" _bitField%d = 0;\n", i);
137 | }
138 |
139 | w.format(" return this;\n");
140 | w.format(" }\n");
141 | }
142 |
143 | private void generateCopyFrom(PrintWriter w) {
144 | w.format("public %s copyFrom(%s _other) {\n", message.getName(), message.getName());
145 | w.format(" _cachedSize = -1;\n");
146 | for (LightProtoField f : fields) {
147 | if (f.isRepeated()) {
148 | f.copy(w);
149 | } else {
150 | w.format(" if (_other.%s()) {\n", Util.camelCase("has", f.ccName));
151 | f.copy(w);
152 | w.format(" }\n");
153 | }
154 | }
155 |
156 | w.format(" return this;\n");
157 | w.format(" }\n");
158 | }
159 |
160 | private void generateSerialize(PrintWriter w) {
161 | w.format(" public int writeTo(io.netty.buffer.ByteBuf _b) {\n");
162 | if (hasRequiredFields()) {
163 | w.format(" checkRequiredFields();\n");
164 | }
165 | w.format(" int _writeIdx = _b.writerIndex();\n");
166 | for (LightProtoField f : fields) {
167 |
168 | if (f.isRequired() || f.isRepeated()) {
169 | // If required, skip the has() check
170 | f.serialize(w);
171 | } else {
172 | w.format(" if (%s()) {\n", Util.camelCase("has", f.field.getName()));
173 | f.serialize(w);
174 | w.format(" }\n");
175 | }
176 | }
177 |
178 | w.format(" return (_b.writerIndex() - _writeIdx);\n");
179 | w.format(" }\n");
180 | }
181 |
182 | private void generateGetSerializedSize(PrintWriter w) {
183 | w.format("public int getSerializedSize() {\n");
184 | w.format(" if (_cachedSize > -1) {\n");
185 | w.format(" return _cachedSize;\n");
186 | w.format(" }\n");
187 | w.format("\n");
188 |
189 | w.format(" int _size = 0;\n");
190 | fields.forEach(field -> {
191 | if (field.isRequired() || field.isRepeated()) {
192 | field.serializedSize(w);
193 | } else {
194 | w.format(" if (%s()) {\n", Util.camelCase("has", field.field.getName()));
195 | field.serializedSize(w);
196 | w.format(" }\n");
197 | }
198 | });
199 |
200 | w.format(" _cachedSize = _size;\n");
201 | w.format(" return _size;\n");
202 | w.format(" }\n");
203 | }
204 |
205 | private void generateBitFields(PrintWriter w) {
206 | for (int i = 0; i < bitFieldsCount(); i++) {
207 | w.format("private int _bitField%d;\n", i);
208 | w.format("private static final int _REQUIRED_FIELDS_MASK%d = 0", i);
209 | int idx = i;
210 | fields.forEach(f -> {
211 | if (f.isRequired() && f.index() / 32 == idx) {
212 | w.format(" | %s", f.fieldMask());
213 | }
214 | });
215 | w.println(";");
216 | }
217 | }
218 |
219 | private void generateCheckRequiredFields(PrintWriter w) {
220 | if (!hasRequiredFields()) {
221 | return;
222 | }
223 |
224 | w.format(" private void checkRequiredFields() {\n");
225 | w.format(" if (");
226 | for (int i = 0; i < bitFieldsCount(); i++) {
227 | if (i != 0) {
228 | w.print("\n || ");
229 | }
230 |
231 | w.format("(_bitField%d & _REQUIRED_FIELDS_MASK%d) != _REQUIRED_FIELDS_MASK%d", i, i, i);
232 | }
233 |
234 | w.format(") {\n");
235 | w.format(" throw new IllegalStateException(\"Some required fields are missing\");\n");
236 | w.format(" }\n");
237 | w.format("}\n");
238 | }
239 |
240 | private int bitFieldsCount() {
241 | if (message.getFieldCount() == 0) {
242 | return 0;
243 | }
244 |
245 | return (int) Math.ceil(message.getFields().size() / 32.0);
246 | }
247 |
248 |
249 | private boolean hasRequiredFields() {
250 | for (LightProtoField field : fields) {
251 | if (field.isRequired()) {
252 | return true;
253 | }
254 | }
255 |
256 | return false;
257 | }
258 | }
259 |
--------------------------------------------------------------------------------
/code-generator/src/main/java/com/github/splunk/lightproto/generator/LightProtoMessageField.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright 2020 Splunk Inc.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.github.splunk.lightproto.generator;
17 |
18 | import io.protostuff.parser.MessageField;
19 |
20 | import java.io.PrintWriter;
21 |
22 | public class LightProtoMessageField extends LightProtoField {
23 |
24 | public LightProtoMessageField(MessageField field, int index) {
25 | super(field, index);
26 | }
27 |
28 | @Override
29 | public void declaration(PrintWriter w) {
30 | w.format("private %s %s;\n", field.getJavaType(), ccName);
31 | }
32 |
33 | @Override
34 | public void setter(PrintWriter w, String enclosingType) {
35 | w.format("public %s %s() {\n", field.getJavaType(), Util.camelCase("set", ccName));
36 | w.format(" if (%s == null) {\n", ccName);
37 | w.format(" %s = new %s();\n", ccName, field.getJavaType());
38 | w.format(" }\n");
39 | w.format(" _bitField%d |= %s;\n", bitFieldIndex(), fieldMask());
40 | w.format(" _cachedSize = -1;\n");
41 | w.format(" return %s;\n", ccName);
42 | w.format("}\n");
43 | }
44 |
45 | @Override
46 | public void copy(PrintWriter w) {
47 | w.format("%s().copyFrom(_other.%s);\n", Util.camelCase("set", ccName), ccName);
48 | }
49 |
50 | public void getter(PrintWriter w) {
51 | w.format("public %s %s() {\n", field.getJavaType(), Util.camelCase("get", field.getName()));
52 | w.format(" if (!%s()) {\n", Util.camelCase("has", ccName));
53 | w.format(" throw new IllegalStateException(\"Field '%s' is not set\");\n", field.getName());
54 | w.format(" }\n");
55 | w.format(" return %s;\n", ccName);
56 | w.format("}\n");
57 | }
58 |
59 | @Override
60 | public void parse(PrintWriter w) {
61 | w.format("int %sSize = LightProtoCodec.readVarInt(_buffer);\n", ccName);
62 | w.format("%s().parseFrom(_buffer, %sSize);\n", Util.camelCase("set", ccName), ccName);
63 | }
64 |
65 | @Override
66 | public void serializedSize(PrintWriter w) {
67 | String tmpName = Util.camelCase("_msgSize", ccName);
68 | w.format("_size += LightProtoCodec.computeVarIntSize(%s);\n", tagName());
69 | w.format("int %s = %s.getSerializedSize();\n", tmpName, ccName);
70 | w.format("_size += LightProtoCodec.computeVarIntSize(%s) + %s;\n", tmpName, tmpName);
71 | }
72 |
73 | @Override
74 | public void serialize(PrintWriter w) {
75 | w.format("LightProtoCodec.writeVarInt(_b, %s);\n", tagName());
76 | w.format("LightProtoCodec.writeVarInt(_b, %s.getSerializedSize());\n", ccName);
77 | w.format("%s.writeTo(_b);\n", ccName);
78 | }
79 |
80 | @Override
81 | public void clear(PrintWriter w) {
82 | w.format("if (%s()){\n", Util.camelCase("has", ccName));
83 | w.format(" %s.clear();\n", ccName);
84 | w.format("}\n");
85 | }
86 |
87 | @Override
88 | protected String typeTag() {
89 | return "LightProtoCodec.WIRETYPE_LENGTH_DELIMITED";
90 | }
91 | }
92 |
--------------------------------------------------------------------------------
/code-generator/src/main/java/com/github/splunk/lightproto/generator/LightProtoNumberField.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright 2020 Splunk Inc.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.github.splunk.lightproto.generator;
17 |
18 | import com.google.common.collect.Maps;
19 | import io.protostuff.parser.Field;
20 |
21 | import java.io.PrintWriter;
22 | import java.util.Map;
23 |
24 | import static com.github.splunk.lightproto.generator.Util.camelCase;
25 |
26 | public class LightProtoNumberField extends LightProtoField> {
27 |
28 |
29 | private static final Map typeToTag = Maps.newHashMap();
30 |
31 | static {
32 | typeToTag.put("double", "LightProtoCodec.WIRETYPE_FIXED64");
33 | typeToTag.put("float", "LightProtoCodec.WIRETYPE_FIXED32");
34 | typeToTag.put("bool", "LightProtoCodec.WIRETYPE_VARINT");
35 | typeToTag.put("int32", "LightProtoCodec.WIRETYPE_VARINT");
36 | typeToTag.put("int64", "LightProtoCodec.WIRETYPE_VARINT");
37 | typeToTag.put("uint32", "LightProtoCodec.WIRETYPE_VARINT");
38 | typeToTag.put("uint64", "LightProtoCodec.WIRETYPE_VARINT");
39 | typeToTag.put("sint32", "LightProtoCodec.WIRETYPE_VARINT");
40 | typeToTag.put("sint64", "LightProtoCodec.WIRETYPE_VARINT");
41 | typeToTag.put("fixed32", "LightProtoCodec.WIRETYPE_FIXED32");
42 | typeToTag.put("fixed64", "LightProtoCodec.WIRETYPE_FIXED64");
43 | typeToTag.put("sfixed32", "LightProtoCodec.WIRETYPE_FIXED32");
44 | typeToTag.put("sfixed64", "LightProtoCodec.WIRETYPE_FIXED64");
45 | }
46 |
47 | public LightProtoNumberField(Field> field, int index) {
48 | super(field, index);
49 | }
50 |
51 | static void serializeNumber(PrintWriter w, Field> field, String name) {
52 | if (field.isEnumField()) {
53 | w.format(" LightProtoCodec.writeVarInt(_b, %s.getValue());\n", name);
54 | } else if (field.getProtoType().equals("bool")) {
55 | w.format(" _b.writeBoolean(%s);\n", name);
56 | } else if (field.getProtoType().equals("int32")) {
57 | w.format(" LightProtoCodec.writeVarInt(_b, %s);\n", name);
58 | } else if (field.getProtoType().equals("uint32")) {
59 | w.format(" LightProtoCodec.writeVarInt(_b, %s);\n", name);
60 | } else if (field.getProtoType().equals("sint32")) {
61 | w.format(" LightProtoCodec.writeSignedVarInt(_b, %s);\n", name);
62 | } else if (field.getProtoType().equals("sint64")) {
63 | w.format(" LightProtoCodec.writeSignedVarInt64(_b, %s);\n", name);
64 | } else if (field.getProtoType().equals("int64")) {
65 | w.format(" LightProtoCodec.writeVarInt64(_b, %s);\n", name);
66 | } else if (field.getProtoType().equals("uint64")) {
67 | w.format(" LightProtoCodec.writeVarInt64(_b, %s);\n", name);
68 | } else if (field.getProtoType().equals("fixed32")) {
69 | w.format(" LightProtoCodec.writeFixedInt32(_b, %s);\n", name);
70 | } else if (field.getProtoType().equals("fixed64")) {
71 | w.format(" LightProtoCodec.writeFixedInt64(_b, %s);\n", name);
72 | } else if (field.getProtoType().equals("sfixed32")) {
73 | w.format(" LightProtoCodec.writeFixedInt32(_b, %s);\n", name);
74 | } else if (field.getProtoType().equals("sfixed64")) {
75 | w.format(" LightProtoCodec.writeFixedInt64(_b, %s);\n", name);
76 | } else if (field.getProtoType().equals("double")) {
77 | w.format(" LightProtoCodec.writeDouble(_b, %s);\n", name);
78 | } else if (field.getProtoType().equals("float")) {
79 | w.format(" LightProtoCodec.writeFloat(_b, %s);\n", name);
80 | } else {
81 | throw new IllegalArgumentException("Failed to write serializer for field: " + field.getProtoType());
82 | }
83 | }
84 |
85 | static String parseNumber(Field> field) {
86 | if (field.isEnumField()) {
87 | return String.format("%s.valueOf(LightProtoCodec.readVarInt(_buffer))", field.getJavaType());
88 | } else if (field.getProtoType().equals("bool")) {
89 | return "LightProtoCodec.readVarInt(_buffer) == 1";
90 | } else if (field.getProtoType().equals("int32")) {
91 | return "LightProtoCodec.readVarInt(_buffer)";
92 | } else if (field.getProtoType().equals("uint32")) {
93 | return "LightProtoCodec.readVarInt(_buffer)";
94 | } else if (field.getProtoType().equals("sint32")) {
95 | return "LightProtoCodec.readSignedVarInt(_buffer)";
96 | } else if (field.getProtoType().equals("sint64")) {
97 | return "LightProtoCodec.readSignedVarInt64(_buffer)";
98 | } else if (field.getProtoType().equals("int64")) {
99 | return "LightProtoCodec.readVarInt64(_buffer)";
100 | } else if (field.getProtoType().equals("uint64")) {
101 | return "LightProtoCodec.readVarInt64(_buffer)";
102 | } else if (field.getProtoType().equals("fixed32")) {
103 | return "LightProtoCodec.readFixedInt32(_buffer)";
104 | } else if (field.getProtoType().equals("fixed64")) {
105 | return "LightProtoCodec.readFixedInt64(_buffer)";
106 | } else if (field.getProtoType().equals("sfixed32")) {
107 | return "LightProtoCodec.readFixedInt32(_buffer)";
108 | } else if (field.getProtoType().equals("sfixed64")) {
109 | return "LightProtoCodec.readFixedInt64(_buffer)";
110 | } else if (field.getProtoType().equals("double")) {
111 | return "LightProtoCodec.readDouble(_buffer)";
112 | } else if (field.getProtoType().equals("float")) {
113 | return "LightProtoCodec.readFloat(_buffer)";
114 | } else {
115 | throw new IllegalArgumentException("Failed to write parser for field: " + field.getProtoType());
116 | }
117 | }
118 |
119 | static String serializedSizeOfNumber(Field> field, String name) {
120 | if (field.isEnumField()) {
121 | return String.format("LightProtoCodec.computeVarIntSize(%s.getValue())", name);
122 | } else if (field.getProtoType().equals("sint32")) {
123 | return String.format("LightProtoCodec.computeSignedVarIntSize(%s)", name);
124 | } else if (field.getProtoType().equals("sint64")) {
125 | return String.format("LightProtoCodec.computeSignedVarInt64Size(%s)", name);
126 | } else if (field.getProtoType().equals("int32")) {
127 | return String.format("LightProtoCodec.computeVarIntSize(%s)", name);
128 | } else if (field.getProtoType().equals("uint32")) {
129 | return String.format("LightProtoCodec.computeVarIntSize(%s)", name);
130 | } else if (field.getProtoType().equals("int64")) {
131 | return String.format("LightProtoCodec.computeVarInt64Size(%s)", name);
132 | } else if (field.getProtoType().equals("uint64")) {
133 | return String.format("LightProtoCodec.computeVarInt64Size(%s)", name);
134 | } else if (field.getProtoType().equals("fixed32")) {
135 | return "4";
136 | } else if (field.getProtoType().equals("fixed64")) {
137 | return "8";
138 | } else if (field.getProtoType().equals("sfixed32")) {
139 | return "4";
140 | } else if (field.getProtoType().equals("sfixed64")) {
141 | return "8";
142 | } else if (field.getProtoType().equals("bool")) {
143 | return "1";
144 | } else if (field.getProtoType().equals("double")) {
145 | return "8";
146 | } else if (field.getProtoType().equals("float")) {
147 | return "4";
148 | } else {
149 | throw new IllegalArgumentException("Failed to write serializer for field: " + field.getProtoType());
150 | }
151 | }
152 |
153 | static String typeTag(Field> field) {
154 | if (field.isEnumField()) {
155 | return "LightProtoCodec.WIRETYPE_VARINT";
156 | } else {
157 | return typeToTag.get(field.getProtoType());
158 | }
159 | }
160 |
161 | public void getter(PrintWriter w) {
162 | w.format(" public %s %s() {\n", field.getJavaType(), Util.camelCase("get", field.getName()));
163 | if (!field.isDefaultValueSet()) {
164 | w.format(" if (!%s()) {\n", Util.camelCase("has", ccName));
165 | w.format(" throw new IllegalStateException(\"Field '%s' is not set\");\n", field.getName());
166 | w.format(" }\n");
167 | }
168 | w.format(" return %s;\n", ccName);
169 | w.format(" }\n");
170 | }
171 |
172 | @Override
173 | public void parse(PrintWriter w) {
174 | w.format("%s = %s;\n", ccName, parseNumber(field));
175 | }
176 |
177 | @Override
178 | public void serialize(PrintWriter w) {
179 | w.format("LightProtoCodec.writeVarInt(_b, %s);\n", tagName());
180 | serializeNumber(w, field, ccName);
181 | }
182 |
183 | @Override
184 | public void setter(PrintWriter w, String enclosingType) {
185 | w.format("public %s %s(%s %s) {\n", enclosingType, Util.camelCase("set", field.getName()), field.getJavaType(), camelCase(field.getName()));
186 | w.format(" this.%s = %s;\n", camelCase(field.getName()), camelCase(field.getName()));
187 | w.format(" _bitField%d |= %s;\n", bitFieldIndex(), fieldMask());
188 | w.format(" _cachedSize = -1;\n");
189 | w.format(" return this;\n");
190 | w.format("}\n");
191 | }
192 |
193 | @Override
194 | public void declaration(PrintWriter w) {
195 | if (field.isDefaultValueSet()) {
196 | w.format("private %s %s = %s;\n", field.getJavaType(), ccName, field.getDefaultValueAsString());
197 | } else {
198 | w.format("private %s %s;\n", field.getJavaType(), ccName);
199 | }
200 | }
201 |
202 | @Override
203 | public void copy(PrintWriter w) {
204 | w.format("%s(_other.%s);\n", Util.camelCase("set", ccName), ccName);
205 | }
206 |
207 | @Override
208 | public void clear(PrintWriter w) {
209 | if (field.isDefaultValueSet()) {
210 | w.format("%s = %s;\n", ccName, field.getDefaultValueAsString());
211 | }
212 | }
213 |
214 | @Override
215 | public void serializedSize(PrintWriter w) {
216 | w.format("_size += %s_SIZE;\n", tagName());
217 | w.format("_size += %s;\n", serializedSizeOfNumber(field, ccName));
218 | }
219 |
220 | @Override
221 | protected String typeTag() {
222 | return typeTag(field);
223 | }
224 | }
225 |
--------------------------------------------------------------------------------
/code-generator/src/main/java/com/github/splunk/lightproto/generator/LightProtoRepeatedBytesField.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright 2020 Splunk Inc.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.github.splunk.lightproto.generator;
17 |
18 | import io.protostuff.parser.Field;
19 |
20 | import java.io.PrintWriter;
21 |
22 | public class LightProtoRepeatedBytesField extends LightProtoAbstractRepeated {
23 |
24 | protected final String pluralName;
25 | protected final String singularName;
26 |
27 | public LightProtoRepeatedBytesField(Field.Bytes field, int index) {
28 | super(field, index);
29 | this.pluralName = Util.plural(ccName);
30 | this.singularName = Util.singular(ccName);
31 | }
32 |
33 | @Override
34 | public void declaration(PrintWriter w) {
35 | w.format("private java.util.List %s = null;\n", pluralName);
36 | w.format("private int _%sCount = 0;\n", pluralName);
37 | }
38 |
39 | @Override
40 | public void parse(PrintWriter w) {
41 | w.format("LightProtoCodec.BytesHolder _%sBh = _%sBytesHolder();\n", ccName, Util.camelCase("new", singularName));
42 | w.format("_%sBh.len = LightProtoCodec.readVarInt(_buffer);\n", ccName);
43 | w.format("_%sBh.idx = _buffer.readerIndex();\n", ccName);
44 | w.format("_buffer.skipBytes(_%sBh.len);\n", ccName);
45 | }
46 |
47 | @Override
48 | public void getter(PrintWriter w) {
49 | w.format("public int %s() {\n", Util.camelCase("get", pluralName, "count"));
50 | w.format(" return _%sCount;\n", pluralName);
51 | w.format("}\n");
52 |
53 | w.format("public int %s(int idx) {\n", Util.camelCase("get", singularName, "size", "at"));
54 | w.format(" if (idx < 0 || idx >= _%sCount) {\n", pluralName);
55 | w.format(" throw new IndexOutOfBoundsException(\"Index \" + idx + \" is out of the list size (\" + _%sCount + \") for field '%s'\");\n", pluralName, field.getName());
56 | w.format(" }\n");
57 | w.format(" return %s.get(idx).len;\n", pluralName);
58 | w.format("}\n");
59 |
60 |
61 | w.format("public byte[] %s(int idx) {\n", Util.camelCase("get", singularName, "at"));
62 | w.format(" io.netty.buffer.ByteBuf _b = %s(idx);\n", Util.camelCase("get", singularName, "slice", "at"));
63 | w.format(" byte[] res = new byte[_b.readableBytes()];\n");
64 | w.format(" _b.getBytes(0, res);\n", ccName);
65 | w.format(" return res;\n");
66 | w.format("}\n");
67 |
68 | w.format("public io.netty.buffer.ByteBuf %s(int idx) {\n", Util.camelCase("get", singularName, "slice", "at"));
69 | w.format(" if (idx < 0 || idx >= _%sCount) {\n", pluralName);
70 | w.format(" throw new IndexOutOfBoundsException(\"Index \" + idx + \" is out of the list size (\" + _%sCount + \") for field '%s'\");\n", pluralName, field.getName());
71 | w.format(" }\n");
72 | w.format(" LightProtoCodec.BytesHolder _bh = %s.get(idx);\n", pluralName);
73 | w.format(" if (_bh.b == null) {\n");
74 | w.format(" return _parsedBuffer.slice(_bh.idx, _bh.len);\n");
75 | w.format(" } else {\n");
76 | w.format(" return _bh.b.slice(0, _bh.len);\n");
77 | w.format(" }\n");
78 | w.format("}\n");
79 | }
80 |
81 | @Override
82 | public void serialize(PrintWriter w) {
83 | w.format("for (int i = 0; i < _%sCount; i++) {\n", pluralName);
84 | w.format(" LightProtoCodec.BytesHolder _bh = %s.get(i);\n", pluralName);
85 | w.format(" LightProtoCodec.writeVarInt(_b, %s);\n", tagName());
86 | w.format(" LightProtoCodec.writeVarInt(_b, _bh.len);\n");
87 | w.format(" if (_bh.idx == -1) {\n");
88 | w.format(" _bh.b.getBytes(0, _b, _bh.len);\n");
89 | w.format(" } else {\n");
90 | w.format(" _parsedBuffer.getBytes(_bh.idx, _b, _bh.len);\n");
91 | w.format(" }\n");
92 | w.format("}\n");
93 | }
94 |
95 | @Override
96 | public void setter(PrintWriter w, String enclosingType) {
97 | w.format("public void %s(byte[] %s) {\n", Util.camelCase("add", singularName), singularName);
98 | w.format(" %s(io.netty.buffer.Unpooled.wrappedBuffer(%s));\n", Util.camelCase("add", singularName), singularName);
99 | w.format("}\n");
100 |
101 | w.format("public void %s(io.netty.buffer.ByteBuf %s) {\n", Util.camelCase("add", singularName), singularName);
102 | w.format(" if (%s == null) {\n", pluralName);
103 | w.format(" %s = new java.util.ArrayList();\n", pluralName);
104 | w.format(" }\n");
105 | w.format(" LightProtoCodec.BytesHolder _bh = _%sBytesHolder();\n", Util.camelCase("new", singularName));
106 | w.format(" _cachedSize = -1;\n");
107 | w.format(" _bh.b = %s;\n", singularName);
108 | w.format(" _bh.idx = -1;\n");
109 | w.format(" _bh.len = %s.readableBytes();\n", singularName);
110 | w.format("}\n");
111 |
112 |
113 | w.format("private LightProtoCodec.BytesHolder _%sBytesHolder() {\n", Util.camelCase("new", singularName));
114 | w.format(" if (%s == null) {\n", pluralName);
115 | w.format(" %s = new java.util.ArrayList();\n", pluralName);
116 | w.format(" }\n");
117 | w.format(" LightProtoCodec.BytesHolder _bh;\n");
118 | w.format(" if (%s.size() == _%sCount) {\n", pluralName, pluralName);
119 | w.format(" _bh = new LightProtoCodec.BytesHolder();\n");
120 | w.format(" %s.add(_bh);\n", pluralName);
121 | w.format(" } else {\n");
122 | w.format(" _bh = %s.get(_%sCount);\n", pluralName, pluralName);
123 | w.format(" }\n");
124 | w.format(" _%sCount++;\n", pluralName);
125 | w.format(" return _bh;\n");
126 | w.format("}\n");
127 | }
128 |
129 | @Override
130 | public void copy(PrintWriter w) {
131 | w.format("for (int i = 0; i < _other.%s(); i++) {\n", Util.camelCase("get", pluralName, "count"));
132 | w.format(" %s(_other.%s(i));\n", Util.camelCase("add", singularName), Util.camelCase("get", singularName, "at"));
133 | w.format("}\n");
134 | }
135 |
136 | @Override
137 | public void serializedSize(PrintWriter w) {
138 | w.format("for (int i = 0; i < _%sCount; i++) {\n", pluralName);
139 | w.format(" LightProtoCodec.BytesHolder _bh = %s.get(i);\n", pluralName);
140 | w.format(" _size += %s_SIZE;\n", tagName());
141 | w.format(" _size += LightProtoCodec.computeVarIntSize(_bh.len) + _bh.len;\n");
142 | w.format("}\n");
143 | }
144 |
145 | @Override
146 | public void clear(PrintWriter w) {
147 | w.format("for (int i = 0; i < _%sCount; i++) {\n", pluralName);
148 | w.format(" LightProtoCodec.BytesHolder _bh = %s.get(i);\n", pluralName);
149 | w.format(" _bh.b = null;\n");
150 | w.format(" _bh.idx = -1;\n");
151 | w.format(" _bh.len = -1;\n");
152 | w.format("}\n");
153 | w.format("_%sCount = 0;\n", pluralName);
154 | }
155 |
156 | @Override
157 | protected String typeTag() {
158 | return "LightProtoCodec.WIRETYPE_LENGTH_DELIMITED";
159 | }
160 | }
161 |
--------------------------------------------------------------------------------
/code-generator/src/main/java/com/github/splunk/lightproto/generator/LightProtoRepeatedEnumField.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright 2020 Splunk Inc.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.github.splunk.lightproto.generator;
17 |
18 | import io.protostuff.parser.Field;
19 |
20 | import java.io.PrintWriter;
21 |
22 | public class LightProtoRepeatedEnumField extends LightProtoRepeatedNumberField {
23 |
24 | public LightProtoRepeatedEnumField(Field> field, int index) {
25 | super(field, index);
26 | }
27 |
28 | @Override
29 | public void parse(PrintWriter w) {
30 | w.format("%s _%s = %s;\n", field.getJavaType(), ccName, LightProtoNumberField.parseNumber(field));
31 | w.format("if (_%s != null) {\n", ccName);
32 | w.format(" %s(_%s);\n", Util.camelCase("add", singularName), ccName);
33 | w.format("}\n");
34 | }
35 |
36 | public void parsePacked(PrintWriter w) {
37 | w.format("int _%s = LightProtoCodec.readVarInt(_buffer);\n", Util.camelCase(singularName, "size"));
38 | w.format("int _%s = _buffer.readerIndex() + _%s;\n", Util.camelCase(singularName, "endIdx"), Util.camelCase(singularName, "size"));
39 | w.format("while (_buffer.readerIndex() < _%s) {\n", Util.camelCase(singularName, "endIdx"));
40 | w.format(" %s _%sPacked = %s;\n", field.getJavaType(), ccName, LightProtoNumberField.parseNumber(field));
41 | w.format(" if (_%sPacked != null) {\n", ccName);
42 | w.format(" %s(_%sPacked);\n", Util.camelCase("add", singularName), ccName);
43 | w.format(" }\n");
44 | w.format("}\n");
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/code-generator/src/main/java/com/github/splunk/lightproto/generator/LightProtoRepeatedMessageField.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright 2020 Splunk Inc.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.github.splunk.lightproto.generator;
17 |
18 | import io.protostuff.parser.MessageField;
19 |
20 | import java.io.PrintWriter;
21 |
22 | public class LightProtoRepeatedMessageField extends LightProtoAbstractRepeated {
23 |
24 | protected final String pluralName;
25 | protected final String singularName;
26 |
27 | public LightProtoRepeatedMessageField(MessageField field, int index) {
28 | super(field, index);
29 | this.pluralName = Util.plural(ccName);
30 | this.singularName = Util.singular(ccName);
31 | }
32 |
33 | @Override
34 | public void declaration(PrintWriter w) {
35 | w.format("private java.util.List<%s> %s = null;\n", field.getJavaType(), pluralName);
36 | w.format("private int _%sCount = 0;\n", pluralName);
37 | }
38 |
39 | @Override
40 | public void getter(PrintWriter w) {
41 | w.format("public int %s() {\n", Util.camelCase("get", pluralName, "count"));
42 | w.format(" return _%sCount;\n", pluralName);
43 | w.format("}\n");
44 | w.format("public %s %s(int idx) {\n", field.getJavaType(), Util.camelCase("get", singularName, "at"));
45 | w.format(" if (idx < 0 || idx >= _%sCount) {\n", pluralName);
46 | w.format(" throw new IndexOutOfBoundsException(\"Index \" + idx + \" is out of the list size (\" + _%sCount + \") for field '%s'\");\n", pluralName, field.getName());
47 | w.format(" }\n");
48 | w.format(" return %s.get(idx);\n", pluralName);
49 | w.format("}\n");
50 |
51 | w.format("public java.util.List<%s> %s() {\n", field.getJavaType(), Util.camelCase("get", pluralName, "list"));
52 | w.format(" if (_%sCount == 0) {\n", pluralName);
53 | w.format(" return java.util.Collections.emptyList();\n");
54 | w.format(" } else {\n");
55 | w.format(" return %s.subList(0, _%sCount);\n", pluralName, pluralName);
56 | w.format(" }\n");
57 | w.format("}\n");
58 | }
59 |
60 | @Override
61 | public void parse(PrintWriter w) {
62 | w.format("int _%sSize = LightProtoCodec.readVarInt(_buffer);\n", ccName);
63 | w.format("%s().parseFrom(_buffer, _%sSize);\n", Util.camelCase("add", singularName), ccName);
64 | }
65 |
66 | @Override
67 | public void serialize(PrintWriter w) {
68 | w.format("for (int i = 0; i < _%sCount; i++) {\n", pluralName);
69 | w.format(" %s _item = %s.get(i);\n", field.getJavaType(), pluralName);
70 | w.format(" LightProtoCodec.writeVarInt(_b, %s);\n", tagName());
71 | w.format(" LightProtoCodec.writeVarInt(_b, _item.getSerializedSize());\n");
72 | w.format(" _item.writeTo(_b);\n");
73 | w.format("}\n");
74 | }
75 |
76 | @Override
77 | public void copy(PrintWriter w) {
78 | w.format("for (int i = 0; i < _other.%s(); i++) {\n", Util.camelCase("get", pluralName, "count"));
79 | w.format(" %s().copyFrom(_other.%s(i));\n", Util.camelCase("add", singularName), Util.camelCase("get", singularName, "at"));
80 | w.format("}\n");
81 | }
82 |
83 | @Override
84 | public void setter(PrintWriter w, String enclosingType) {
85 | w.format("public %s %s() {\n", field.getJavaType(), Util.camelCase("add", singularName));
86 | w.format(" if (%s == null) {\n", pluralName);
87 | w.format(" %s = new java.util.ArrayList<%s>();\n", pluralName, field.getJavaType());
88 | w.format(" }\n");
89 | w.format(" if (%s.size() == _%sCount) {\n", pluralName, pluralName);
90 | w.format(" %s.add(new %s());\n", pluralName, field.getJavaType());
91 | w.format(" }\n");
92 | w.format(" _cachedSize = -1;\n");
93 | w.format(" return %s.get(_%sCount++);\n", pluralName, pluralName);
94 | w.format("}\n");
95 |
96 |
97 | w.format("public %s %s(Iterable<%s> %s) {\n", enclosingType, Util.camelCase("addAll", pluralName), field.getJavaType(), pluralName);
98 | w.format(" for (%s _o : %s) {\n", field.getJavaType(), pluralName);
99 | w.format(" %s().copyFrom(_o);\n", Util.camelCase("add", singularName));
100 | w.format(" }\n");
101 | w.format(" return this;\n");
102 | w.format("}\n");
103 |
104 |
105 | }
106 |
107 | @Override
108 | public void serializedSize(PrintWriter w) {
109 | String tmpName = Util.camelCase("_msgSize", field.getName());
110 |
111 | w.format("for (int i = 0; i < _%sCount; i++) {\n", pluralName);
112 | w.format(" %s _item = %s.get(i);\n", field.getJavaType(), pluralName);
113 | w.format(" _size += %s_SIZE;\n", tagName());
114 | w.format(" int %s = _item.getSerializedSize();\n", tmpName);
115 | w.format(" _size += LightProtoCodec.computeVarIntSize(%s) + %s;\n", tmpName, tmpName);
116 | w.format("}\n");
117 | }
118 |
119 | @Override
120 | public void clear(PrintWriter w) {
121 | w.format("for (int i = 0; i < _%sCount; i++) {\n", pluralName);
122 | w.format(" %s.get(i).clear();\n", pluralName);
123 | w.format("}\n");
124 | w.format("_%sCount = 0;\n", pluralName);
125 | }
126 |
127 | @Override
128 | protected String typeTag() {
129 | return "LightProtoCodec.WIRETYPE_LENGTH_DELIMITED";
130 | }
131 | }
132 |
--------------------------------------------------------------------------------
/code-generator/src/main/java/com/github/splunk/lightproto/generator/LightProtoRepeatedNumberField.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright 2020 Splunk Inc.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.github.splunk.lightproto.generator;
17 |
18 | import io.protostuff.parser.Field;
19 |
20 | import java.io.PrintWriter;
21 |
22 | public class LightProtoRepeatedNumberField extends LightProtoAbstractRepeated> {
23 |
24 | protected final String pluralName;
25 | protected final String singularName;
26 |
27 | public LightProtoRepeatedNumberField(Field> field, int index) {
28 | super(field, index);
29 | this.pluralName = Util.plural(ccName);
30 | this.singularName = Util.singular(ccName);
31 | }
32 |
33 | @Override
34 | public void declaration(PrintWriter w) {
35 | w.format("private %s[] %s = null;\n", field.getJavaType(), pluralName);
36 | w.format("private int _%sCount = 0;\n", pluralName);
37 | }
38 |
39 | @Override
40 | public void parse(PrintWriter w) {
41 | w.format("%s(%s);\n", Util.camelCase("add", singularName), LightProtoNumberField.parseNumber(field));
42 | }
43 |
44 | public void parsePacked(PrintWriter w) {
45 | w.format("int _%s = LightProtoCodec.readVarInt(_buffer);\n", Util.camelCase(singularName, "size"));
46 | w.format("int _%s = _buffer.readerIndex() + _%s;\n", Util.camelCase(singularName, "endIdx"), Util.camelCase(singularName, "size"));
47 | w.format("while (_buffer.readerIndex() < _%s) {\n", Util.camelCase(singularName, "endIdx"));
48 | w.format("%s(%s);\n", Util.camelCase("add", singularName), LightProtoNumberField.parseNumber(field));
49 | w.format("}\n");
50 | }
51 |
52 | @Override
53 | public void getter(PrintWriter w) {
54 | w.format("private static final int %s_PACKED = (%s << LightProtoCodec.TAG_TYPE_BITS) | LightProtoCodec.WIRETYPE_LENGTH_DELIMITED;\n", tagName(), fieldNumber());
55 | w.format("public int %s() {\n", Util.camelCase("get", pluralName, "count"));
56 | w.format(" return _%sCount;\n", pluralName);
57 | w.format("}\n");
58 | w.format("public %s %s(int idx) {\n", field.getJavaType(), Util.camelCase("get", singularName, "at"));
59 | w.format(" if (idx < 0 || idx >= _%sCount) {\n", pluralName);
60 | w.format(" throw new IndexOutOfBoundsException(\"Index \" + idx + \" is out of the list size (\" + _%sCount + \") for field '%s'\");\n", pluralName, field.getName());
61 | w.format(" }\n");
62 | w.format(" return %s[idx];\n", pluralName);
63 | w.format("}\n");
64 | }
65 |
66 | @Override
67 | public void serialize(PrintWriter w) {
68 | if (field.getOption("packed") == Boolean.TRUE) {
69 | w.format(" LightProtoCodec.writeVarInt(_b, %s_PACKED);\n", tagName());
70 | w.format(" int _%sSize = 0;\n", pluralName);
71 | w.format("for (int i = 0; i < _%sCount; i++) {\n", pluralName);
72 | w.format(" %s _item = %s[i];\n", field.getJavaType(), pluralName);
73 | w.format(" _%sSize += %s;\n", pluralName, LightProtoNumberField.serializedSizeOfNumber(field, "_item"));
74 | w.format("}\n");
75 | w.format(" LightProtoCodec.writeVarInt(_b, _%sSize);\n", pluralName);
76 | w.format("for (int i = 0; i < _%sCount; i++) {\n", pluralName);
77 | w.format(" %s _item = %s[i];\n", field.getJavaType(), pluralName);
78 | LightProtoNumberField.serializeNumber(w, field, "_item");
79 | w.format("}\n");
80 | } else {
81 | w.format("for (int i = 0; i < _%sCount; i++) {\n", pluralName);
82 | w.format(" %s _item = %s[i];\n", field.getJavaType(), pluralName);
83 | w.format(" LightProtoCodec.writeVarInt(_b, %s);\n", tagName());
84 | LightProtoNumberField.serializeNumber(w, field, "_item");
85 | w.format("}\n");
86 | }
87 | }
88 |
89 | @Override
90 | public void setter(PrintWriter w, String enclosingType) {
91 | w.format("public void %s(%s %s) {\n", Util.camelCase("add", singularName), field.getJavaType(), singularName);
92 | w.format(" if (%s == null) {\n", pluralName);
93 | w.format(" %s = new %s[4];\n", pluralName, field.getJavaType());
94 | w.format(" }\n");
95 | w.format(" if (%s.length == _%sCount) {\n", pluralName, pluralName);
96 | w.format(" %s = java.util.Arrays.copyOf(%s, _%sCount * 2);\n", pluralName, pluralName, pluralName);
97 | w.format(" }\n");
98 | w.format(" _cachedSize = -1;\n");
99 | w.format(" %s[_%sCount++] = %s;\n", pluralName, pluralName, singularName);
100 | w.format("}\n");
101 | }
102 |
103 | @Override
104 | public void copy(PrintWriter w) {
105 | w.format("for (int i = 0; i < _other.%s(); i++) {\n", Util.camelCase("get", pluralName, "count"));
106 | w.format(" %s(_other.%s(i));\n", Util.camelCase("add", singularName), Util.camelCase("get", singularName, "at"));
107 | w.format("}\n");
108 | }
109 |
110 | @Override
111 | public void serializedSize(PrintWriter w) {
112 |
113 | if (field.getOption("packed") == Boolean.TRUE) {
114 | w.format(" _size += %s_SIZE;\n", tagName());
115 | w.format(" int _%sSize = 0;\n", pluralName);
116 | w.format("for (int i = 0; i < _%sCount; i++) {\n", pluralName);
117 | w.format(" %s _item = %s[i];\n", field.getJavaType(), pluralName);
118 | w.format(" _%sSize += %s;\n", pluralName, LightProtoNumberField.serializedSizeOfNumber(field, "_item"));
119 | w.format("}\n");
120 | w.format(" _size += LightProtoCodec.computeVarIntSize(_%sSize);\n", pluralName);
121 | w.format(" _size += _%sSize;\n", pluralName);
122 | } else {
123 | w.format("for (int i = 0; i < _%sCount; i++) {\n", pluralName);
124 | w.format(" %s _item = %s[i];\n", field.getJavaType(), pluralName);
125 | w.format(" _size += %s_SIZE;\n", tagName());
126 | w.format(" _size += %s;\n", LightProtoNumberField.serializedSizeOfNumber(field, "_item"));
127 | w.format("}\n");
128 | }
129 | }
130 |
131 | @Override
132 | public void clear(PrintWriter w) {
133 | w.format("_%sCount = 0;\n", pluralName);
134 | }
135 |
136 | @Override
137 | protected String typeTag() {
138 | return LightProtoNumberField.typeTag(field);
139 | }
140 |
141 | }
142 |
--------------------------------------------------------------------------------
/code-generator/src/main/java/com/github/splunk/lightproto/generator/LightProtoRepeatedStringField.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright 2020 Splunk Inc.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.github.splunk.lightproto.generator;
17 |
18 | import io.protostuff.parser.Field;
19 |
20 | import java.io.PrintWriter;
21 |
22 | public class LightProtoRepeatedStringField extends LightProtoAbstractRepeated {
23 |
24 | protected final String pluralName;
25 | protected final String singularName;
26 |
27 | public LightProtoRepeatedStringField(Field.String field, int index) {
28 | super(field, index);
29 | this.pluralName = Util.plural(ccName);
30 | this.singularName = Util.singular(ccName);
31 | }
32 |
33 | @Override
34 | public void declaration(PrintWriter w) {
35 | w.format("private java.util.List %s = null;\n", pluralName);
36 | w.format("private int _%sCount = 0;\n", pluralName);
37 | }
38 |
39 | @Override
40 | public void parse(PrintWriter w) {
41 | w.format("LightProtoCodec.StringHolder _%sSh = _%sStringHolder();\n", ccName, Util.camelCase("new", singularName));
42 | w.format("_%sSh.len = LightProtoCodec.readVarInt(_buffer);\n", ccName);
43 | w.format("_%sSh.idx = _buffer.readerIndex();\n", ccName);
44 | w.format("_buffer.skipBytes(_%sSh.len);\n", ccName);
45 | }
46 |
47 | @Override
48 | public void getter(PrintWriter w) {
49 | w.format("public int %s() {\n", Util.camelCase("get", pluralName, "count"));
50 | w.format(" return _%sCount;\n", pluralName);
51 | w.format("}\n");
52 | w.format("public %s %s(int idx) {\n", field.getJavaType(), Util.camelCase("get", singularName, "at"));
53 | w.format(" if (idx < 0 || idx >= _%sCount) {\n", pluralName);
54 | w.format(" throw new IndexOutOfBoundsException(\"Index \" + idx + \" is out of the list size (\" + _%sCount + \") for field '%s'\");\n", pluralName, field.getName());
55 | w.format(" }\n");
56 | w.format(" LightProtoCodec.StringHolder _sh = %s.get(idx);\n", pluralName);
57 | w.format(" if (_sh.s == null) {\n");
58 | w.format(" _sh.s = LightProtoCodec.readString(_parsedBuffer, _sh.idx, _sh.len);\n");
59 | w.format(" }\n");
60 | w.format(" return _sh.s;\n");
61 | w.format("}\n");
62 |
63 | w.format("public java.util.List %s() {\n", Util.camelCase("get", pluralName, "list"));
64 | w.format(" if (_%sCount == 0) {\n", pluralName);
65 | w.format(" return java.util.Collections.emptyList();\n");
66 | w.format(" } else {\n");
67 | w.format(" java.util.List _l = new java.util.ArrayList<>();\n");
68 | w.format(" for (int i = 0; i < _%sCount; i++) {\n", pluralName);
69 | w.format(" _l.add(%s(i));\n", Util.camelCase("get", singularName, "at"));
70 | w.format(" }\n");
71 | w.format(" return _l;\n");
72 | w.format(" }\n");
73 | w.format("}\n");
74 | }
75 |
76 | @Override
77 | public void serialize(PrintWriter w) {
78 | w.format("for (int i = 0; i < _%sCount; i++) {\n", pluralName);
79 | w.format(" LightProtoCodec.StringHolder _sh = %s.get(i);\n", pluralName);
80 | w.format(" LightProtoCodec.writeVarInt(_b, %s);\n", tagName());
81 | w.format(" LightProtoCodec.writeVarInt(_b, _sh.len);\n");
82 | w.format(" if (_sh.idx == -1) {\n");
83 | w.format(" LightProtoCodec.writeString(_b, _sh.s, _sh.len);\n");
84 | w.format(" } else {\n");
85 | w.format(" _parsedBuffer.getBytes(_sh.idx, _b, _sh.len);\n");
86 | w.format(" }\n");
87 | w.format("}\n");
88 | }
89 |
90 | @Override
91 | public void copy(PrintWriter w) {
92 | w.format("for (int i = 0; i < _other.%s(); i++) {\n", Util.camelCase("get", pluralName, "count"));
93 | w.format(" %s(_other.%s(i));\n", Util.camelCase("add", singularName), Util.camelCase("get", singularName, "at"));
94 | w.format("}\n");
95 | }
96 |
97 | @Override
98 | public void setter(PrintWriter w, String enclosingType) {
99 | w.format("public void %s(String %s) {\n", Util.camelCase("add", singularName), singularName);
100 | w.format(" if (%s == null) {\n", pluralName);
101 | w.format(" %s = new java.util.ArrayList();\n", pluralName);
102 | w.format(" }\n");
103 | w.format(" LightProtoCodec.StringHolder _sh = _%sStringHolder();\n", Util.camelCase("new", singularName));
104 | w.format(" _cachedSize = -1;\n");
105 | w.format(" _sh.s = %s;\n", singularName);
106 | w.format(" _sh.idx = -1;\n");
107 | w.format(" _sh.len = LightProtoCodec.computeStringUTF8Size(_sh.s);\n");
108 | w.format("}\n");
109 |
110 | w.format("public %s %s(Iterable %s) {\n", enclosingType, Util.camelCase("addAll", pluralName), pluralName);
111 | w.format(" for (String _s : %s) {\n", pluralName);
112 | w.format(" %s(_s);\n", Util.camelCase("add", singularName));
113 | w.format(" }\n");
114 | w.format(" return this;\n");
115 | w.format("}\n");
116 |
117 |
118 | w.format("private LightProtoCodec.StringHolder _%sStringHolder() {\n", Util.camelCase("new", singularName));
119 | w.format(" if (%s == null) {\n", pluralName);
120 | w.format(" %s = new java.util.ArrayList();\n", pluralName);
121 | w.format(" }\n");
122 | w.format(" LightProtoCodec.StringHolder _sh;\n");
123 | w.format(" if (%s.size() == _%sCount) {\n", pluralName, pluralName);
124 | w.format(" _sh = new LightProtoCodec.StringHolder();\n");
125 | w.format(" %s.add(_sh);\n", pluralName);
126 | w.format(" } else {\n");
127 | w.format(" _sh = %s.get(_%sCount);\n", pluralName, pluralName);
128 | w.format(" }\n");
129 | w.format(" _%sCount++;\n", pluralName);
130 | w.format(" return _sh;\n");
131 | w.format("}\n");
132 | }
133 |
134 | @Override
135 | public void serializedSize(PrintWriter w) {
136 | w.format("for (int i = 0; i < _%sCount; i++) {\n", pluralName);
137 | w.format(" LightProtoCodec.StringHolder _sh = %s.get(i);\n", pluralName);
138 | w.format(" _size += %s_SIZE;\n", tagName());
139 | w.format(" _size += LightProtoCodec.computeVarIntSize(_sh.len) + _sh.len;\n");
140 | w.format("}\n");
141 | }
142 |
143 | @Override
144 | public void clear(PrintWriter w) {
145 | w.format("for (int i = 0; i < _%sCount; i++) {\n", pluralName);
146 | w.format(" LightProtoCodec.StringHolder _sh = %s.get(i);\n", pluralName);
147 | w.format(" _sh.s = null;\n");
148 | w.format(" _sh.idx = -1;\n");
149 | w.format(" _sh.len = -1;\n");
150 | w.format("}\n");
151 | w.format("_%sCount = 0;\n", pluralName);
152 | }
153 |
154 | @Override
155 | protected String typeTag() {
156 | return "LightProtoCodec.WIRETYPE_LENGTH_DELIMITED";
157 | }
158 | }
159 |
--------------------------------------------------------------------------------
/code-generator/src/main/java/com/github/splunk/lightproto/generator/LightProtoStringField.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright 2020 Splunk Inc.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.github.splunk.lightproto.generator;
17 |
18 | import io.protostuff.parser.Field;
19 |
20 | import java.io.PrintWriter;
21 |
22 | import static com.github.splunk.lightproto.generator.Util.camelCase;
23 |
24 | public class LightProtoStringField extends LightProtoField {
25 |
26 | public LightProtoStringField(Field.String field, int index) {
27 | super(field, index);
28 | }
29 |
30 | @Override
31 | public void declaration(PrintWriter w) {
32 | if (field.isDefaultValueSet()) {
33 | w.format("private String %s = \"%s\";\n", ccName, field.getDefaultValue());
34 | } else {
35 | w.format("private String %s;\n", ccName);
36 | }
37 | w.format("private int _%sBufferIdx = -1;\n", ccName);
38 | w.format("private int _%sBufferLen = -1;\n", ccName);
39 | }
40 |
41 | @Override
42 | public void setter(PrintWriter w, String enclosingType) {
43 | w.format("public %s %s(%s %s) {\n", enclosingType, Util.camelCase("set", field.getName()), field.getJavaType(), camelCase(field.getName()));
44 | w.format(" this.%s = %s;\n", camelCase(field.getName()), camelCase(field.getName()));
45 | w.format(" _bitField%d |= %s;\n", bitFieldIndex(), fieldMask());
46 | w.format(" _%sBufferIdx = -1;\n", ccName);
47 | w.format(" _%sBufferLen = LightProtoCodec.computeStringUTF8Size(%s);\n", ccName, ccName);
48 | w.format(" _cachedSize = -1;\n");
49 | w.format(" return this;\n");
50 | w.format("}\n");
51 | }
52 |
53 | @Override
54 | public void copy(PrintWriter w) {
55 | w.format("%s(_other.%s());\n", Util.camelCase("set", ccName), Util.camelCase("get", ccName));
56 | }
57 |
58 | @Override
59 | public void getter(PrintWriter w) {
60 | w.format("public %s %s() {\n", field.getJavaType(), Util.camelCase("get", field.getName()));
61 | if (!field.isDefaultValueSet()) {
62 | w.format(" if (!%s()) {\n", Util.camelCase("has", ccName));
63 | w.format(" throw new IllegalStateException(\"Field '%s' is not set\");\n", field.getName());
64 | w.format(" }\n");
65 | }
66 | w.format(" if (%s == null) {\n", camelCase(field.getName()));
67 | w.format(" %s = LightProtoCodec.readString(_parsedBuffer, _%sBufferIdx, _%sBufferLen);\n", ccName, ccName, ccName);
68 | w.format(" }\n");
69 | w.format(" return %s;\n", camelCase(field.getName()));
70 | w.format("}\n");
71 | }
72 |
73 | @Override
74 | public void clear(PrintWriter w) {
75 | w.format("%s = %s;\n", ccName, field.getDefaultValue());
76 | w.format("_%sBufferIdx = -1;\n", ccName);
77 | w.format("_%sBufferLen = -1;\n", ccName);
78 | }
79 |
80 | @Override
81 | public void serializedSize(PrintWriter w) {
82 | w.format("_size += %s_SIZE;\n", tagName());
83 | w.format("_size += LightProtoCodec.computeVarIntSize(_%sBufferLen);\n", ccName);
84 | w.format("_size += _%sBufferLen;\n", ccName);
85 | }
86 |
87 | @Override
88 | public void serialize(PrintWriter w) {
89 | w.format("LightProtoCodec.writeVarInt(_b, %s);\n", tagName());
90 | w.format("LightProtoCodec.writeVarInt(_b, _%sBufferLen);\n", ccName);
91 | w.format("if (_%sBufferIdx == -1) {\n", ccName);
92 | w.format(" LightProtoCodec.writeString(_b, %s, _%sBufferLen);\n", ccName, ccName);
93 | w.format("} else {\n");
94 | w.format(" _parsedBuffer.getBytes(_%sBufferIdx, _b, _%sBufferLen);\n", ccName, ccName);
95 | w.format("}\n");
96 | }
97 |
98 | @Override
99 | public void parse(PrintWriter w) {
100 | w.format("_%sBufferLen = LightProtoCodec.readVarInt(_buffer);\n", ccName);
101 | w.format("_%sBufferIdx = _buffer.readerIndex();\n", ccName);
102 | w.format("_buffer.skipBytes(_%sBufferLen);\n", ccName);
103 | }
104 |
105 | @Override
106 | protected String typeTag() {
107 | return "LightProtoCodec.WIRETYPE_LENGTH_DELIMITED";
108 | }
109 | }
110 |
--------------------------------------------------------------------------------
/code-generator/src/main/java/com/github/splunk/lightproto/generator/Util.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright 2020 Splunk Inc.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.github.splunk.lightproto.generator;
17 |
18 | import org.jibx.schema.codegen.extend.DefaultNameConverter;
19 | import org.jibx.schema.codegen.extend.NameConverter;
20 |
21 | import static com.google.common.base.CaseFormat.LOWER_CAMEL;
22 | import static com.google.common.base.CaseFormat.LOWER_UNDERSCORE;
23 |
24 | public class Util {
25 |
26 | public static String camelCase(String... parts) {
27 | StringBuilder sb = new StringBuilder();
28 | for (int i = 0; i < parts.length; i++) {
29 | String s = parts[i];
30 | if (s == null || s.isEmpty()) {
31 | continue;
32 | }
33 | if (s.contains("_")) {
34 | s = LOWER_UNDERSCORE.to(LOWER_CAMEL, s);
35 | }
36 |
37 | if (i != 0) {
38 | sb.append(Character.toUpperCase(s.charAt(0)));
39 | sb.append(s.substring(1));
40 | } else {
41 | sb.append(s);
42 | }
43 | }
44 |
45 | return sb.toString();
46 | }
47 |
48 | public static String camelCaseFirstUpper(String... parts) {
49 | String s = camelCase(parts);
50 | return Character.toUpperCase(s.charAt(0)) + s.substring(1);
51 | }
52 |
53 | public static String upperCase(String... parts) {
54 | StringBuilder sb = new StringBuilder();
55 | for (int i = 0; i < parts.length; i++) {
56 | String s = LOWER_CAMEL.to(LOWER_UNDERSCORE, parts[i]);
57 | if (i != 0) {
58 | sb.append('_');
59 | }
60 |
61 | sb.append(s);
62 | }
63 |
64 | return sb.toString().toUpperCase();
65 | }
66 |
67 | private static final NameConverter nameTools = new DefaultNameConverter();
68 |
69 | public static String plural(String s) {
70 | return nameTools.pluralize(s);
71 | }
72 |
73 | public static String singular(String s) {
74 | return nameTools.depluralize(s);
75 | }
76 | }
77 |
--------------------------------------------------------------------------------
/code-generator/src/main/resources/com/github/splunk/lightproto/generator/LightProtoCodec.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright 2020 Splunk Inc.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.github.splunk.lightproto.generator;
17 |
18 | import io.netty.buffer.ByteBuf;
19 | import io.netty.buffer.ByteBufUtil;
20 |
21 | import java.nio.charset.StandardCharsets;
22 |
23 | class LightProtoCodec {
24 | static final int TAG_TYPE_MASK = 7;
25 | static final int TAG_TYPE_BITS = 3;
26 | static final int WIRETYPE_VARINT = 0;
27 | static final int WIRETYPE_FIXED64 = 1;
28 | static final int WIRETYPE_LENGTH_DELIMITED = 2;
29 | static final int WIRETYPE_START_GROUP = 3;
30 | static final int WIRETYPE_END_GROUP = 4;
31 | static final int WIRETYPE_FIXED32 = 5;
32 | private LightProtoCodec() {
33 | }
34 |
35 | private static int getTagType(int tag) {
36 | return tag & TAG_TYPE_MASK;
37 | }
38 |
39 | static int getFieldId(int tag) {
40 | return tag >>> TAG_TYPE_BITS;
41 | }
42 |
43 | static void writeVarInt(ByteBuf b, int n) {
44 | if (n >= 0) {
45 | _writeVarInt(b, n);
46 | } else {
47 | writeVarInt64(b, n);
48 | }
49 | }
50 |
51 | static void writeSignedVarInt(ByteBuf b, int n) {
52 | writeVarInt(b, encodeZigZag32(n));
53 | }
54 |
55 | static int readSignedVarInt(ByteBuf b) {
56 | return decodeZigZag32(readVarInt(b));
57 | }
58 |
59 | static long readSignedVarInt64(ByteBuf b) {
60 | return decodeZigZag64(readVarInt64(b));
61 | }
62 |
63 | static void writeFloat(ByteBuf b, float n) {
64 | writeFixedInt32(b, Float.floatToRawIntBits(n));
65 | }
66 |
67 | static void writeDouble(ByteBuf b, double n) {
68 | writeFixedInt64(b, Double.doubleToRawLongBits(n));
69 | }
70 |
71 | static float readFloat(ByteBuf b) {
72 | return Float.intBitsToFloat(readFixedInt32(b));
73 | }
74 |
75 | static double readDouble(ByteBuf b) {
76 | return Double.longBitsToDouble(readFixedInt64(b));
77 | }
78 |
79 | private static void _writeVarInt(ByteBuf b, int n) {
80 | while (true) {
81 | if ((n & ~0x7F) == 0) {
82 | b.writeByte(n);
83 | return;
84 | } else {
85 | b.writeByte((n & 0x7F) | 0x80);
86 | n >>>= 7;
87 | }
88 | }
89 | }
90 |
91 | static void writeVarInt64(ByteBuf b, long value) {
92 | while (true) {
93 | if ((value & ~0x7FL) == 0) {
94 | b.writeByte((int) value);
95 | return;
96 | } else {
97 | b.writeByte(((int) value & 0x7F) | 0x80);
98 | value >>>= 7;
99 | }
100 | }
101 | }
102 |
103 | static void writeFixedInt32(ByteBuf b, int n) {
104 | b.writeIntLE(n);
105 | }
106 |
107 | static void writeFixedInt64(ByteBuf b, long n) {
108 | b.writeLongLE(n);
109 | }
110 |
111 | static int readFixedInt32(ByteBuf b) {
112 | return b.readIntLE();
113 | }
114 |
115 | static long readFixedInt64(ByteBuf b) {
116 | return b.readLongLE();
117 | }
118 |
119 |
120 | static void writeSignedVarInt64(ByteBuf b, long n) {
121 | writeVarInt64(b, encodeZigZag64(n));
122 | }
123 |
124 | private static int encodeZigZag32(final int n) {
125 | return (n << 1) ^ (n >> 31);
126 | }
127 |
128 | private static long encodeZigZag64(final long n) {
129 | return (n << 1) ^ (n >> 63);
130 | }
131 |
132 | private static int decodeZigZag32(int n) {
133 | return n >>> 1 ^ -(n & 1);
134 | }
135 |
136 | private static long decodeZigZag64(long n) {
137 | return n >>> 1 ^ -(n & 1L);
138 | }
139 |
140 | static int readVarInt(ByteBuf buf) {
141 | byte tmp = buf.readByte();
142 | if (tmp >= 0) {
143 | return tmp;
144 | }
145 | int result = tmp & 0x7f;
146 | if ((tmp = buf.readByte()) >= 0) {
147 | result |= tmp << 7;
148 | } else {
149 | result |= (tmp & 0x7f) << 7;
150 | if ((tmp = buf.readByte()) >= 0) {
151 | result |= tmp << 14;
152 | } else {
153 | result |= (tmp & 0x7f) << 14;
154 | if ((tmp = buf.readByte()) >= 0) {
155 | result |= tmp << 21;
156 | } else {
157 | result |= (tmp & 0x7f) << 21;
158 | result |= (tmp = buf.readByte()) << 28;
159 | if (tmp < 0) {
160 | // Discard upper 32 bits.
161 | for (int i = 0; i < 5; i++) {
162 | if (buf.readByte() >= 0) {
163 | return result;
164 | }
165 | }
166 | throw new IllegalArgumentException("Encountered a malformed varint.");
167 | }
168 | }
169 | }
170 | }
171 | return result;
172 | }
173 |
174 | static long readVarInt64(ByteBuf buf) {
175 | int shift = 0;
176 | long result = 0;
177 | while (shift < 64) {
178 | final byte b = buf.readByte();
179 | result |= (long) (b & 0x7F) << shift;
180 | if ((b & 0x80) == 0) {
181 | return result;
182 | }
183 | shift += 7;
184 | }
185 | throw new IllegalArgumentException("Encountered a malformed varint.");
186 | }
187 |
188 | static int computeSignedVarIntSize(final int value) {
189 | return computeVarUIntSize(encodeZigZag32(value));
190 | }
191 |
192 | static int computeSignedVarInt64Size(final long value) {
193 | return computeVarInt64Size(encodeZigZag64(value));
194 | }
195 |
196 | static int computeVarIntSize(final int value) {
197 | if (value < 0) {
198 | return 10;
199 | } else {
200 | return computeVarUIntSize(value);
201 | }
202 | }
203 |
204 | static int computeVarUIntSize(final int value) {
205 | if ((value & (0xffffffff << 7)) == 0) {
206 | return 1;
207 | } else if ((value & (0xffffffff << 14)) == 0) {
208 | return 2;
209 | } else if ((value & (0xffffffff << 21)) == 0) {
210 | return 3;
211 | } else if ((value & (0xffffffff << 28)) == 0) {
212 | return 4;
213 | } else {
214 | return 5;
215 | }
216 | }
217 |
218 | static int computeVarInt64Size(final long value) {
219 | if ((value & (0xffffffffffffffffL << 7)) == 0) {
220 | return 1;
221 | } else if ((value & (0xffffffffffffffffL << 14)) == 0) {
222 | return 2;
223 | } else if ((value & (0xffffffffffffffffL << 21)) == 0) {
224 | return 3;
225 | } else if ((value & (0xffffffffffffffffL << 28)) == 0) {
226 | return 4;
227 | } else if ((value & (0xffffffffffffffffL << 35)) == 0) {
228 | return 5;
229 | } else if ((value & (0xffffffffffffffffL << 42)) == 0) {
230 | return 6;
231 | } else if ((value & (0xffffffffffffffffL << 49)) == 0) {
232 | return 7;
233 | } else if ((value & (0xffffffffffffffffL << 56)) == 0) {
234 | return 8;
235 | } else if ((value & (0xffffffffffffffffL << 63)) == 0) {
236 | return 9;
237 | } else {
238 | return 10;
239 | }
240 | }
241 |
242 | static int computeStringUTF8Size(String s) {
243 | return ByteBufUtil.utf8Bytes(s);
244 | }
245 |
246 | static void writeString(ByteBuf b, String s, int bytesCount) {
247 | ByteBufUtil.reserveAndWriteUtf8(b, s, bytesCount);
248 | }
249 |
250 | static String readString(ByteBuf b, int index, int len) {
251 | return b.toString(index, len, StandardCharsets.UTF_8);
252 | }
253 |
254 | static void skipUnknownField(int tag, ByteBuf buffer) {
255 | int tagType = getTagType(tag);
256 | switch (tagType) {
257 | case WIRETYPE_VARINT:
258 | readVarInt(buffer);
259 | break;
260 | case WIRETYPE_FIXED64:
261 | buffer.skipBytes(8);
262 | break;
263 | case WIRETYPE_LENGTH_DELIMITED:
264 | int len = readVarInt(buffer);
265 | buffer.skipBytes(len);
266 | break;
267 | case WIRETYPE_FIXED32:
268 | buffer.skipBytes(4);
269 | break;
270 | default:
271 | throw new IllegalArgumentException("Invalid unknonwn tag type: " + tagType);
272 | }
273 | }
274 |
275 | static final class StringHolder {
276 | String s;
277 | int idx;
278 | int len;
279 | }
280 |
281 | static final class BytesHolder {
282 | ByteBuf b;
283 | int idx;
284 | int len;
285 | }
286 | }
287 |
--------------------------------------------------------------------------------
/license-header.txt:
--------------------------------------------------------------------------------
1 | Copyright 2020 Splunk Inc.
2 |
3 | Licensed under the Apache License, Version 2.0 (the "License");
4 | you may not use this file except in compliance with the License.
5 | You may obtain a copy of the License at
6 |
7 | http://www.apache.org/licenses/LICENSE-2.0
8 |
9 | Unless required by applicable law or agreed to in writing, software
10 | distributed under the License is distributed on an "AS IS" BASIS,
11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | See the License for the specific language governing permissions and
13 | limitations under the License.
--------------------------------------------------------------------------------
/maven-plugin/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
19 |
21 | 4.0.0
22 |
23 | com.github.splunk.lightproto
24 | lightproto
25 | 0.5-SNAPSHOT
26 | ../pom.xml
27 |
28 |
29 | lightproto-maven-plugin
30 | maven-plugin
31 |
32 | lightproto-maven-plugin
33 |
34 |
35 |
36 | ${project.groupId}
37 | lightproto-code-generator
38 | ${project.version}
39 |
40 |
41 |
42 | org.apache.maven
43 | maven-plugin-api
44 | 2.0
45 |
46 |
47 | org.apache.maven.plugin-tools
48 | maven-plugin-annotations
49 | 3.2
50 | provided
51 |
52 |
53 | org.apache.maven
54 | maven-project
55 | 2.2.1
56 |
57 |
58 |
59 |
60 |
61 |
62 | org.apache.maven.plugins
63 | maven-plugin-plugin
64 |
65 | lightproto
66 | true
67 |
68 |
69 |
70 | mojo-descriptor
71 |
72 | descriptor
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
--------------------------------------------------------------------------------
/maven-plugin/src/main/java/com/github/splunk/lightproto/maven/plugin/LightProtoMojo.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright 2020 Splunk Inc.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.github.splunk.lightproto.maven.plugin;
17 |
18 | import com.github.splunk.lightproto.generator.LightProtoGenerator;
19 | import org.apache.maven.plugin.AbstractMojo;
20 | import org.apache.maven.plugin.MojoExecutionException;
21 | import org.apache.maven.plugins.annotations.LifecyclePhase;
22 | import org.apache.maven.plugins.annotations.Mojo;
23 | import org.apache.maven.plugins.annotations.Parameter;
24 | import org.apache.maven.plugins.annotations.ResolutionScope;
25 | import org.apache.maven.project.MavenProject;
26 |
27 | import java.io.File;
28 | import java.util.Arrays;
29 | import java.util.List;
30 |
31 | /**
32 | * Goal which generates Java code from the proto definition
33 | */
34 | @Mojo(
35 | name = "generate",
36 | defaultPhase = LifecyclePhase.GENERATE_SOURCES,
37 | requiresDependencyResolution = ResolutionScope.COMPILE,
38 | threadSafe = true
39 | )
40 | public class LightProtoMojo extends AbstractMojo {
41 |
42 | @Parameter(property = "classPrefix", defaultValue = "", required = false)
43 | private String classPrefix;
44 |
45 | @Parameter(property = "singleOuterClass", defaultValue = "false", required = false)
46 | private boolean singleOuterClass;
47 |
48 | @Parameter(property = "sources", required = false)
49 | private List sources;
50 |
51 | @Parameter(defaultValue = "${project}", required = true, readonly = true)
52 | private MavenProject project;
53 |
54 | @Parameter(defaultValue="generated-sources/protobuf/java", required = false)
55 | private String targetSourcesSubDir;
56 |
57 | @Parameter(defaultValue="generated-test-sources/protobuf/java", required = false)
58 | private String targetTestSourcesSubDir;
59 |
60 | private void generate(List protoFiles, File outputDirectory) throws MojoExecutionException {
61 | try {
62 | LightProtoGenerator.generate(protoFiles, outputDirectory, classPrefix, singleOuterClass);
63 | } catch (Exception e) {
64 | getLog().error("Failed to generate lightproto code for " + protoFiles + ": " + e.getMessage(), e);
65 | throw new MojoExecutionException("Failed to generate lightproto code for " + protoFiles, e);
66 |
67 | }
68 | }
69 |
70 | public void execute() throws MojoExecutionException {
71 | File baseDir = project.getBasedir();
72 | File targetDir = new File(project.getBuild().getDirectory());
73 |
74 | if (sources == null || sources.isEmpty()) {
75 | File[] mainFilesArray = new File(baseDir, "src/main/proto").listFiles((dir, name) -> name.endsWith(".proto"));
76 | if (mainFilesArray != null && mainFilesArray.length > 0) {
77 | List mainFiles = Arrays.asList(mainFilesArray);
78 | File generatedSourcesDir = new File(targetDir, targetSourcesSubDir);
79 | generate(mainFiles, new File(targetDir, targetSourcesSubDir));
80 |
81 | project.addCompileSourceRoot(generatedSourcesDir.toString());
82 | }
83 |
84 | File[] testFilesArray = new File(baseDir, "src/test/proto").listFiles((dir, name) -> name.endsWith(".proto"));
85 | if (testFilesArray != null && testFilesArray.length > 0) {
86 | List testFiles = Arrays.asList(testFilesArray);
87 | File generatedTestSourcesDir = new File(targetDir, targetTestSourcesSubDir);
88 | generate(testFiles, generatedTestSourcesDir);
89 |
90 | project.addTestCompileSourceRoot(generatedTestSourcesDir.toString());
91 | }
92 | } else {
93 | File generatedSourcesDir = new File(targetDir, targetSourcesSubDir);
94 | generate(sources, generatedSourcesDir);
95 | project.addCompileSourceRoot(generatedSourcesDir.toString());
96 | }
97 | }
98 | }
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
19 |
22 | 4.0.0
23 |
24 | com.github.splunk.lightproto
25 | lightproto
26 | 0.5-SNAPSHOT
27 | pom
28 |
29 | lightproto
30 | https://github.com/splunk/lightproto
31 | Protobuf compatible code generator
32 |
33 |
34 | Splunk
35 | https://splunk.com
36 |
37 | 2020
38 |
39 |
40 |
41 | Splunk Inc.
42 | https://splunk.com/
43 |
44 |
45 |
46 |
47 | https://github.com/splunk/lightproto
48 | scm:git:https://github.com/splunk/lightproto.git
49 | scm:git:ssh://git@github.com:splunk/lightproto.git
50 |
51 |
52 |
53 |
54 | Apache License, Version 2.0
55 | https://www.apache.org/licenses/LICENSE-2.0.txt
56 | repo
57 |
58 |
59 |
60 |
61 | UTF-8
62 | 3.13.0
63 | ${protobuf.version}
64 |
65 | 1.7.2
66 | 1.7.25
67 | 5.7.0
68 | 30.1-jre
69 | 4.1.56.Final
70 | 1.3.3
71 | 2.22.2.Final
72 |
73 | 1.27
74 |
75 | 3.8.1
76 | 3.0.0-M5
77 | 3.2.1
78 | 3.6.0
79 | 1.6
80 | 3.2.0
81 | 1.6.8
82 | 0.6.1
83 | 1.6.2
84 | 3.0
85 |
86 |
87 |
88 | code-generator
89 | benchmark
90 | maven-plugin
91 | tests
92 |
93 |
94 |
95 |
96 |
97 | org.apache.maven.plugins
98 | maven-compiler-plugin
99 | ${maven-compiler.version}
100 |
101 | 1.8
102 | 1.8
103 | 1.8
104 |
105 |
106 |
107 |
108 | com.mycila
109 | license-maven-plugin
110 | ${license-maven-plugin.version}
111 |
112 |
113 |
114 |
115 | LICENSE
116 | NOTICE
117 |
118 |
119 | JAVADOC_STYLE
120 |
121 |
122 |
123 |
124 | org.apache.maven.plugins
125 | maven-gpg-plugin
126 | ${maven-gpg-plugin.version}
127 |
128 |
129 | sign-artifacts
130 | verify
131 |
132 | sign
133 |
134 |
135 |
136 |
137 |
138 | org.sonatype.plugins
139 | nexus-staging-maven-plugin
140 | ${nexus-staging-maven-plugin.version}
141 | true
142 |
143 | ossrh
144 | https://oss.sonatype.org/
145 | true
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 | org.xolstice.maven.plugins
154 | protobuf-maven-plugin
155 | ${protobuf-maven-plugin.version}
156 |
157 |
158 | maven-surefire-plugin
159 | ${maven-surefire.version}
160 |
161 |
162 | org.apache.maven.plugins
163 | maven-plugin-plugin
164 | ${maven-plugin-plugin.version}
165 |
166 |
167 |
168 |
169 |
170 |
171 |
172 |
173 | io.protostuff
174 | protostuff-parser
175 | ${protostuff.version}
176 |
177 |
178 |
179 | org.junit
180 | junit-bom
181 | ${junit.version}
182 | pom
183 | import
184 |
185 |
186 |
187 | org.slf4j
188 | slf4j-api
189 | ${slf4j.version}
190 |
191 |
192 | com.google.guava
193 | guava
194 | ${guava.version}
195 |
196 |
197 | io.netty
198 | netty-bom
199 | ${netty.version}
200 | pom
201 | import
202 |
203 |
204 | com.google.protobuf
205 | protobuf-java
206 | ${protobuf.version}
207 |
208 |
209 |
210 | org.jibx
211 | jibx-tools
212 | ${jibx.version}
213 |
214 |
215 |
216 | org.openjdk.jmh
217 | jmh-core
218 | ${jmh.version}
219 |
220 |
221 | org.openjdk.jmh
222 | jmh-generator-annprocess
223 | ${jmh.version}
224 | provided
225 |
226 |
227 |
228 | org.jboss.forge.roaster
229 | roaster-api
230 | ${roaster.version}
231 |
232 |
233 | org.jboss.forge.roaster
234 | roaster-jdt
235 | ${roaster.version}
236 |
237 |
238 |
239 | org.junit.jupiter
240 | junit-jupiter
241 | ${junit.version}
242 |
243 |
244 |
245 |
246 |
247 |
248 |
249 | release
250 |
251 |
252 |
253 | org.apache.maven.plugins
254 | maven-source-plugin
255 | ${maven-source-plugin.version}
256 |
257 |
258 | attach-sources
259 |
260 | jar-no-fork
261 |
262 |
263 |
264 |
265 |
266 | org.apache.maven.plugins
267 | maven-javadoc-plugin
268 | ${maven-javadoc-plugin.version}
269 |
270 |
271 | attach-javadocs
272 |
273 | jar
274 |
275 |
276 |
277 |
278 |
279 | org.apache.maven.plugins
280 | maven-gpg-plugin
281 | ${maven-gpg-plugin.version}
282 |
283 |
284 | sign-artifacts
285 | verify
286 |
287 | sign
288 |
289 |
290 |
291 |
292 |
293 | org.sonatype.plugins
294 | nexus-staging-maven-plugin
295 | ${nexus-staging-maven-plugin.version}
296 | true
297 |
298 | ossrh
299 | https://oss.sonatype.org/
300 | true
301 |
302 |
303 |
304 |
305 |
306 |
307 |
308 |
309 |
310 |
311 | ossrh
312 | https://oss.sonatype.org/content/repositories/snapshots
313 |
314 |
315 | ossrh
316 | https://oss.sonatype.org/service/local/staging/deploy/maven2/
317 |
318 |
319 |
320 |
--------------------------------------------------------------------------------
/tests/pom.xml:
--------------------------------------------------------------------------------
1 |
18 |
21 | 4.0.0
22 |
23 | com.github.splunk.lightproto
24 | lightproto
25 | 0.5-SNAPSHOT
26 |
27 | lightproto-tests
28 |
29 |
30 |
31 |
32 | com.google.protobuf
33 | protobuf-java
34 |
35 |
36 |
37 | io.netty
38 | netty-buffer
39 |
40 |
41 |
42 | org.junit.jupiter
43 | junit-jupiter
44 | test
45 |
46 |
47 |
48 |
49 |
50 |
51 | kr.motd.maven
52 | os-maven-plugin
53 | 1.6.2
54 |
55 |
56 |
57 |
58 |
59 | org.xolstice.maven.plugins
60 | protobuf-maven-plugin
61 |
62 | com.google.protobuf:protoc:${protoc.version}:exe:${os.detected.classifier}
63 |
64 | true
65 |
66 |
67 |
68 | generate-sources
69 |
70 | compile
71 |
72 |
73 |
74 |
75 |
76 |
77 | ${project.groupId}
78 | lightproto-maven-plugin
79 | ${project.version}
80 |
81 |
82 |
83 | generate
84 |
85 |
86 |
87 |
88 |
89 |
90 |
--------------------------------------------------------------------------------
/tests/src/main/proto/PulsarMarkers.proto:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright 2020 Splunk Inc.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | syntax = "proto2";
17 |
18 | package pulsar.proto;
19 | option java_package = "org.apache.pulsar.common.api.proto";
20 | option optimize_for = LITE_RUNTIME;
21 |
22 | enum MarkerType {
23 | UNKNOWN_MARKER = 0;
24 |
25 | // Replicated subscription markers
26 | REPLICATED_SUBSCRIPTION_SNAPSHOT_REQUEST = 10;
27 | REPLICATED_SUBSCRIPTION_SNAPSHOT_RESPONSE = 11;
28 | REPLICATED_SUBSCRIPTION_SNAPSHOT = 12;
29 | REPLICATED_SUBSCRIPTION_UPDATE = 13;
30 |
31 | // Next markers start at 20
32 | TXN_COMMITTING = 20;
33 | TXN_COMMIT = 21;
34 | TXN_ABORT = 22;
35 | }
36 |
37 | /// --- Replicated subscriptions ---
38 |
39 | // A cluster uses this message to request the current
40 | // message id from all the other clusters.
41 | message ReplicatedSubscriptionsSnapshotRequest {
42 | required string snapshot_id = 1;
43 | optional string source_cluster = 2;
44 | }
45 |
46 | // When a cluster receives the snapshot request, it replies
47 | // by sending back the response (only to original asking cluster)
48 | message ReplicatedSubscriptionsSnapshotResponse {
49 | required string snapshot_id = 1;
50 | optional ClusterMessageId cluster = 2;
51 | }
52 |
53 | // This message is used to store the snapshot in the
54 | // local topic. It's not meant to be replicated to other
55 | // clusters
56 | message ReplicatedSubscriptionsSnapshot {
57 | required string snapshot_id = 1;
58 | optional MessageIdDataX local_message_id = 2;
59 | repeated ClusterMessageId clusters = 3;
60 | }
61 |
62 | // When the replicated subscription mark-delete position
63 | // is updated in the source cluster, this message will be
64 | // sent to all clusters to updated the mirrored subscriptions
65 | message ReplicatedSubscriptionsUpdate {
66 | required string subscription_name = 1;
67 | repeated ClusterMessageId clusters = 2;
68 | }
69 |
70 | message MessageIdDataX {
71 | required uint64 ledger_id = 1;
72 | required uint64 entry_id = 2;
73 | }
74 |
75 | // Represent one cluster and an associated message id.
76 | // The message id is local to that particular cluster
77 | message ClusterMessageId {
78 | required string cluster = 1;
79 | required MessageIdDataX message_id = 2;
80 | }
81 |
82 | /// --- Transaction marker ---
83 | message TxnCommitMarker {
84 | repeated MessageIdDataX message_id = 1;
85 | }
--------------------------------------------------------------------------------
/tests/src/main/proto/Test.proto:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright 2020 Splunk Inc.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | syntax = "proto2";
17 | package com.github.splunk.lightproto.tests;
18 |
19 | message Point {
20 | required int32 x = 1;
21 | required int32 y = 2;
22 | optional int32 z = 3;
23 | }
24 |
25 | message Frame {
26 | required string name = 1;
27 | required Point point = 2;
28 | }
29 |
--------------------------------------------------------------------------------
/tests/src/main/proto/addressbook.proto:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright 2020 Splunk Inc.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | syntax = "proto2";
17 | package tutorial;
18 |
19 | option java_package = "com.github.splunk.lightproto.tests";
20 | option java_outer_classname = "AddressBookProtos";
21 |
22 | message Person {
23 | required string name = 1;
24 | required int32 id = 2;
25 | optional string email = 3;
26 |
27 | enum PhoneType {
28 | MOBILE = 0;
29 | HOME = 1;
30 | WORK = 2;
31 | }
32 |
33 | message PhoneNumber {
34 | required string number = 1;
35 | optional PhoneType type = 2 [default = HOME];
36 | }
37 |
38 | repeated PhoneNumber phone = 4;
39 | }
40 |
41 | // Our address book file is just one of these.
42 | message AddressBook {
43 | repeated Person person = 1;
44 | }
45 |
--------------------------------------------------------------------------------
/tests/src/main/proto/bytes.proto:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright 2020 Splunk Inc.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | syntax = "proto2";
17 | package com.github.splunk.lightproto.tests;
18 |
19 | message B {
20 | optional bytes payload = 1;
21 | repeated bytes extra_items = 2;
22 | }
23 |
--------------------------------------------------------------------------------
/tests/src/main/proto/enums.proto:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright 2020 Splunk Inc.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | syntax = "proto2";
17 | package com.github.splunk.lightproto.tests;
18 |
19 | enum E1 {
20 | A1 = 1;
21 | B1 = 2;
22 | C1 = 5;
23 | }
24 |
25 | enum E2 {
26 | A2 = 1;
27 | B2 = 2;
28 | C2 = 5;
29 | D2 = 6;
30 | }
31 |
32 | message EnumTest1 {
33 | required E1 e = 1;
34 | }
35 |
36 | message EnumTest2 {
37 | required E2 e = 1;
38 | }
39 |
40 | message EnumTest1Optional {
41 | optional E1 e = 1;
42 | }
43 |
44 | message EnumTest1Repeated {
45 | repeated E1 e = 1;
46 | }
47 |
48 | message EnumTest2Repeated {
49 | repeated E2 e = 1;
50 | }
51 |
52 | message EnumTest1Packed {
53 | repeated E1 e = 1 [packed = true];
54 | }
55 |
56 | message EnumTest2Packed {
57 | repeated E2 e = 1 [packed = true];
58 | }
59 |
--------------------------------------------------------------------------------
/tests/src/main/proto/messages.proto:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright 2020 Splunk Inc.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | syntax = "proto2";
17 | package com.github.splunk.lightproto.tests;
18 |
19 | message X {
20 | optional string a = 1;
21 | optional string b = 2;
22 | }
23 |
24 | message M {
25 | message KV {
26 | message XX {
27 | optional int32 n = 1;
28 | }
29 |
30 | required string k = 1;
31 | required string v = 2;
32 | optional XX xx = 3;
33 | }
34 |
35 | optional X x = 1;
36 | repeated KV items = 2;
37 | }
38 |
39 |
--------------------------------------------------------------------------------
/tests/src/main/proto/numbers.proto:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright 2020 Splunk Inc.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | syntax = "proto2";
17 | package com.github.splunk.lightproto.tests;
18 |
19 |
20 | enum Enum1 {
21 | X1_0 = 0;
22 | X1_1 = 1;
23 | X1_2 = 2;
24 | }
25 |
26 | message Numbers {
27 | enum Enum2 {
28 | X2_0 = 0;
29 | X2_1 = 1;
30 | X2_2 = 2;
31 | }
32 |
33 | optional int32 x_int32 = 1;
34 | optional int64 x_int64 = 2;
35 | optional uint32 x_uint32 = 3;
36 | optional uint64 x_uint64 = 4;
37 | optional sint32 x_sint32 = 5;
38 | optional sint64 x_sint64 = 6;
39 | optional fixed32 x_fixed32 = 7;
40 | optional fixed64 x_fixed64 = 8;
41 | optional sfixed32 x_sfixed32 = 9;
42 | optional sfixed64 x_sfixed64 = 10;
43 | optional float x_float = 11;
44 | optional double x_double = 12;
45 | optional bool x_bool = 13;
46 | optional Enum1 enum1 = 14;
47 | optional Enum2 enum2 = 15;
48 | }
49 |
50 |
--------------------------------------------------------------------------------
/tests/src/main/proto/repeated_numbers.proto:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright 2020 Splunk Inc.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | syntax = "proto2";
17 | package com.github.splunk.lightproto.tests;
18 |
19 | message Repeated {
20 | enum Enum {
21 | X2_0 = 0;
22 | X2_1 = 1;
23 | X2_2 = 2;
24 | }
25 |
26 | repeated int32 x_int32 = 1;
27 | repeated int64 x_int64 = 2;
28 | repeated uint32 x_uint32 = 3;
29 | repeated uint64 x_uint64 = 4;
30 | repeated sint32 x_sint32 = 5;
31 | repeated sint64 x_sint64 = 6;
32 | repeated fixed32 x_fixed32 = 7;
33 | repeated fixed64 x_fixed64 = 8;
34 | repeated sfixed32 x_sfixed32 = 9;
35 | repeated sfixed64 x_sfixed64 = 10;
36 | repeated float x_float = 11;
37 | repeated double x_double = 12;
38 | repeated bool x_bool = 13;
39 | repeated Enum enum1 = 14;
40 | }
41 |
42 | // Same as above but packed
43 | message RepeatedPacked {
44 | enum Enum {
45 | X2_0 = 0;
46 | X2_1 = 1;
47 | X2_2 = 2;
48 | }
49 |
50 | repeated Enum enum1 = 1 [packed = true];
51 | repeated int64 x_int64 = 2 [packed = true];
52 | repeated uint32 x_uint32 = 3 [packed = true];
53 | repeated uint64 x_uint64 = 4 [packed = true];
54 | repeated sint32 x_sint32 = 5 [packed = true];
55 | repeated sint64 x_sint64 = 6 [packed = true];
56 | repeated fixed32 x_fixed32 = 7 [packed = true];
57 | repeated fixed64 x_fixed64 = 8 [packed = true];
58 | repeated sfixed32 x_sfixed32 = 9 [packed = true];
59 | repeated sfixed64 x_sfixed64 = 10 [packed = true];
60 | repeated float x_float = 11 [packed = true];
61 | repeated double x_double = 12 [packed = true];
62 | repeated bool x_bool = 13 [packed = true];
63 | repeated int32 x_int32 = 14 [packed = true];
64 | }
65 |
--------------------------------------------------------------------------------
/tests/src/main/proto/required.proto:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright 2020 Splunk Inc.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | syntax = "proto2";
17 | package com.github.splunk.lightproto.tests;
18 |
19 | message R {
20 | required int32 a = 1;
21 | optional int32 b = 2;
22 | optional int32 c = 3 [default = 5];
23 | }
24 |
25 | // Same as above but with no required field.
26 | message NR {
27 | optional int32 a = 1;
28 | optional int32 b = 2;
29 | optional int32 c = 3 [default = 5];
30 | }
31 |
32 | // Same as above, but with additional field
33 | message RExt {
34 | required int32 a = 1;
35 | optional int32 b = 2;
36 | optional int32 c = 3 [default = 5];
37 |
38 | optional int32 ext_d = 4;
39 | optional fixed32 ext_e = 5;
40 | optional fixed64 ext_f = 6;
41 | optional string ext_g = 7;
42 | }
43 |
--------------------------------------------------------------------------------
/tests/src/main/proto/strings.proto:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright 2020 Splunk Inc.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | syntax = "proto2";
17 | package com.github.splunk.lightproto.tests;
18 |
19 | message S {
20 | optional string id = 1;
21 | repeated string names = 2;
22 | }
23 |
24 |
--------------------------------------------------------------------------------
/tests/src/test/java/com/github/splunk/lightproto/tests/AddressBookTest.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright 2020 Splunk Inc.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.github.splunk.lightproto.tests;
17 |
18 | import com.google.protobuf.CodedOutputStream;
19 | import io.netty.buffer.ByteBuf;
20 | import io.netty.buffer.Unpooled;
21 | import org.junit.jupiter.api.BeforeEach;
22 | import org.junit.jupiter.api.Test;
23 |
24 | import java.util.Arrays;
25 |
26 | import static org.junit.jupiter.api.Assertions.assertArrayEquals;
27 | import static org.junit.jupiter.api.Assertions.assertEquals;
28 |
29 | public class AddressBookTest {
30 |
31 | private byte[] b1 = new byte[4096];
32 | private ByteBuf bb1 = Unpooled.wrappedBuffer(b1);
33 |
34 | private byte[] b2 = new byte[4096];
35 |
36 | @BeforeEach
37 | public void setup() {
38 | bb1.clear();
39 | Arrays.fill(b1, (byte) 0);
40 | Arrays.fill(b2, (byte) 0);
41 | }
42 |
43 | @Test
44 | public void testAddressBook() throws Exception {
45 | AddressBook ab = new AddressBook();
46 | Person p1 = ab.addPerson()
47 | .setName("name 1")
48 | .setEmail("name1@example.com")
49 | .setId(5);
50 | p1.addPhone()
51 | .setNumber("xxx-zzz-1111")
52 | .setType(Person.PhoneType.HOME);
53 | p1.addPhone()
54 | .setNumber("xxx-zzz-2222")
55 | .setType(Person.PhoneType.MOBILE);
56 |
57 | Person p2 = ab.addPerson()
58 | .setName("name 2")
59 | .setEmail("name2@example.com")
60 | .setId(6);
61 | p2.addPhone()
62 | .setNumber("xxx-zzz-2222")
63 | .setType(Person.PhoneType.HOME);
64 |
65 | assertEquals(2, ab.getPersonsCount());
66 | assertEquals("name 1", ab.getPersonAt(0).getName());
67 | assertEquals("name1@example.com", ab.getPersonAt(0).getEmail());
68 | assertEquals(5, ab.getPersonAt(0).getId());
69 | assertEquals("xxx-zzz-1111", ab.getPersonAt(0).getPhoneAt(0).getNumber());
70 | assertEquals(Person.PhoneType.HOME, ab.getPersonAt(0).getPhoneAt(0).getType());
71 | assertEquals("name 2", ab.getPersonAt(1).getName());
72 | assertEquals("name2@example.com", ab.getPersonAt(1).getEmail());
73 | assertEquals(6, ab.getPersonAt(1).getId());
74 | assertEquals("xxx-zzz-2222", ab.getPersonAt(1).getPhoneAt(0).getNumber());
75 | assertEquals(Person.PhoneType.HOME, ab.getPersonAt(0).getPhoneAt(0).getType());
76 |
77 | AddressBookProtos.AddressBook.Builder pbab = AddressBookProtos.AddressBook.newBuilder();
78 | AddressBookProtos.Person.Builder pb_p1 = AddressBookProtos.Person.newBuilder();
79 | pb_p1.setName("name 1");
80 | pb_p1.setEmail("name1@example.com");
81 | pb_p1.setId(5);
82 | AddressBookProtos.Person.PhoneNumber.Builder pb1_pn1 = AddressBookProtos.Person.PhoneNumber.newBuilder();
83 | pb1_pn1.setNumber("xxx-zzz-1111");
84 | pb1_pn1.setType(AddressBookProtos.Person.PhoneType.HOME);
85 |
86 | AddressBookProtos.Person.PhoneNumber.Builder pb1_pn2 = AddressBookProtos.Person.PhoneNumber.newBuilder();
87 | pb1_pn2.setNumber("xxx-zzz-2222");
88 | pb1_pn2.setType(AddressBookProtos.Person.PhoneType.MOBILE);
89 |
90 | pb_p1.addPhone(pb1_pn1);
91 | pb_p1.addPhone(pb1_pn2);
92 |
93 | AddressBookProtos.Person.Builder pb_p2 = AddressBookProtos.Person.newBuilder();
94 | pb_p2.setName("name 2");
95 | pb_p2.setEmail("name2@example.com");
96 | pb_p2.setId(6);
97 |
98 | AddressBookProtos.Person.PhoneNumber.Builder pb2_pn1 = AddressBookProtos.Person.PhoneNumber.newBuilder();
99 | pb2_pn1.setNumber("xxx-zzz-2222");
100 | pb2_pn1.setType(AddressBookProtos.Person.PhoneType.HOME);
101 |
102 | pb_p2.addPhone(pb2_pn1);
103 |
104 | pbab.addPerson(pb_p1);
105 | pbab.addPerson(pb_p2);
106 |
107 | assertEquals(pbab.build().getSerializedSize(), ab.getSerializedSize());
108 |
109 | ab.writeTo(bb1);
110 | assertEquals(ab.getSerializedSize(), bb1.readableBytes());
111 |
112 | pbab.build().writeTo(CodedOutputStream.newInstance(b2));
113 |
114 | assertArrayEquals(b1, b2);
115 |
116 | AddressBook parsed = new AddressBook();
117 | parsed.parseFrom(bb1, bb1.readableBytes());
118 |
119 | assertEquals(2, parsed.getPersonsCount());
120 | assertEquals("name 1", parsed.getPersonAt(0).getName());
121 | assertEquals("name1@example.com", parsed.getPersonAt(0).getEmail());
122 | assertEquals(5, parsed.getPersonAt(0).getId());
123 | assertEquals("xxx-zzz-1111", parsed.getPersonAt(0).getPhoneAt(0).getNumber());
124 | assertEquals(Person.PhoneType.HOME, parsed.getPersonAt(0).getPhoneAt(0).getType());
125 | assertEquals("name 2", parsed.getPersonAt(1).getName());
126 | assertEquals("name2@example.com", parsed.getPersonAt(1).getEmail());
127 | assertEquals(6, parsed.getPersonAt(1).getId());
128 | assertEquals("xxx-zzz-2222", parsed.getPersonAt(1).getPhoneAt(0).getNumber());
129 | assertEquals(Person.PhoneType.HOME, parsed.getPersonAt(1).getPhoneAt(0).getType());
130 | }
131 | }
132 |
--------------------------------------------------------------------------------
/tests/src/test/java/com/github/splunk/lightproto/tests/BytesTest.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright 2020 Splunk Inc.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.github.splunk.lightproto.tests;
17 |
18 | import com.google.protobuf.ByteString;
19 | import com.google.protobuf.CodedOutputStream;
20 | import io.netty.buffer.ByteBuf;
21 | import io.netty.buffer.Unpooled;
22 | import org.junit.jupiter.api.BeforeEach;
23 | import org.junit.jupiter.api.Test;
24 |
25 | import java.util.Arrays;
26 |
27 | import static org.junit.jupiter.api.Assertions.*;
28 |
29 | public class BytesTest {
30 |
31 | private byte[] b1 = new byte[4096];
32 | private ByteBuf bb1 = Unpooled.wrappedBuffer(b1);
33 |
34 | private byte[] b2 = new byte[4096];
35 |
36 | @BeforeEach
37 | public void setup() {
38 | bb1.clear();
39 | Arrays.fill(b1, (byte) 0);
40 | Arrays.fill(b2, (byte) 0);
41 | }
42 |
43 | @Test
44 | public void testBytes() throws Exception {
45 | B lpb = new B()
46 | .setPayload(new byte[]{1, 2, 3});
47 |
48 | assertTrue(lpb.hasPayload());
49 | assertEquals(3, lpb.getPayloadSize());
50 | assertArrayEquals(new byte[]{1, 2, 3}, lpb.getPayload());
51 |
52 | Bytes.B pbb = Bytes.B.newBuilder()
53 | .setPayload(ByteString.copyFrom(new byte[]{1, 2, 3}))
54 | .build();
55 |
56 | assertEquals(pbb.getSerializedSize(), lpb.getSerializedSize());
57 | lpb.writeTo(bb1);
58 | assertEquals(lpb.getSerializedSize(), bb1.readableBytes());
59 |
60 | pbb.writeTo(CodedOutputStream.newInstance(b2));
61 |
62 | assertArrayEquals(b1, b2);
63 |
64 | B parsed = new B();
65 | parsed.parseFrom(bb1, bb1.readableBytes());
66 |
67 | assertTrue(parsed.hasPayload());
68 | assertEquals(3, parsed.getPayloadSize());
69 | assertArrayEquals(new byte[]{1, 2, 3}, parsed.getPayload());
70 | }
71 |
72 | @Test
73 | public void testBytesBuf() throws Exception {
74 | B lpb = new B();
75 | ByteBuf b = Unpooled.directBuffer(3);
76 | b.writeBytes(new byte[]{1, 2, 3});
77 | lpb.setPayload(b);
78 |
79 | assertTrue(lpb.hasPayload());
80 | assertEquals(3, lpb.getPayloadSize());
81 | assertArrayEquals(new byte[]{1, 2, 3}, lpb.getPayload());
82 | assertEquals(Unpooled.wrappedBuffer(new byte[]{1, 2, 3}), lpb.getPayloadSlice());
83 |
84 | Bytes.B pbb = Bytes.B.newBuilder()
85 | .setPayload(ByteString.copyFrom(new byte[]{1, 2, 3}))
86 | .build();
87 |
88 | assertEquals(pbb.getSerializedSize(), lpb.getSerializedSize());
89 | lpb.writeTo(bb1);
90 | assertEquals(lpb.getSerializedSize(), bb1.readableBytes());
91 |
92 | pbb.writeTo(CodedOutputStream.newInstance(b2));
93 |
94 | assertArrayEquals(b1, b2);
95 |
96 | B parsed = new B();
97 | parsed.parseFrom(bb1, bb1.readableBytes());
98 |
99 | assertTrue(parsed.hasPayload());
100 | assertEquals(3, parsed.getPayloadSize());
101 | assertEquals(Unpooled.wrappedBuffer(new byte[]{1, 2, 3}), parsed.getPayloadSlice());
102 | assertArrayEquals(new byte[]{1, 2, 3}, parsed.getPayload());
103 |
104 | bb1.clear();
105 | parsed.writeTo(bb1);
106 |
107 | assertEquals(lpb.getSerializedSize(), bb1.readableBytes());
108 | assertArrayEquals(b1, b2);
109 | }
110 |
111 | @Test
112 | public void testRepeatedBytes() throws Exception {
113 | B lpb = new B();
114 | lpb.addExtraItem(new byte[]{1, 2, 3});
115 | lpb.addExtraItem(new byte[]{4, 5, 6, 7});
116 |
117 | assertEquals(2, lpb.getExtraItemsCount());
118 | assertEquals(3, lpb.getExtraItemSizeAt(0));
119 | assertEquals(4, lpb.getExtraItemSizeAt(1));
120 | assertArrayEquals(new byte[]{1, 2, 3}, lpb.getExtraItemAt(0));
121 | assertArrayEquals(new byte[]{4, 5, 6, 7}, lpb.getExtraItemAt(1));
122 |
123 | Bytes.B pbb = Bytes.B.newBuilder()
124 | .addExtraItems(ByteString.copyFrom(new byte[]{1, 2, 3}))
125 | .addExtraItems(ByteString.copyFrom(new byte[]{4, 5, 6, 7}))
126 | .build();
127 |
128 | assertEquals(pbb.getSerializedSize(), lpb.getSerializedSize());
129 | lpb.writeTo(bb1);
130 | assertEquals(lpb.getSerializedSize(), bb1.readableBytes());
131 |
132 | pbb.writeTo(CodedOutputStream.newInstance(b2));
133 |
134 | assertArrayEquals(b1, b2);
135 |
136 | B parsed = new B();
137 | parsed.parseFrom(bb1, bb1.readableBytes());
138 |
139 | assertEquals(2, parsed.getExtraItemsCount());
140 | assertEquals(3, parsed.getExtraItemSizeAt(0));
141 | assertEquals(4, parsed.getExtraItemSizeAt(1));
142 | assertArrayEquals(new byte[]{1, 2, 3}, parsed.getExtraItemAt(0));
143 | assertArrayEquals(new byte[]{4, 5, 6, 7}, parsed.getExtraItemAt(1));
144 | }
145 | }
146 |
--------------------------------------------------------------------------------
/tests/src/test/java/com/github/splunk/lightproto/tests/EnumsTest.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright 2020 Splunk Inc.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.github.splunk.lightproto.tests;
17 |
18 | import com.google.protobuf.CodedOutputStream;
19 | import io.netty.buffer.ByteBuf;
20 | import io.netty.buffer.Unpooled;
21 | import org.junit.jupiter.api.BeforeEach;
22 | import org.junit.jupiter.api.Test;
23 |
24 | import java.util.Arrays;
25 |
26 | import static org.junit.jupiter.api.Assertions.*;
27 |
28 | public class EnumsTest {
29 |
30 | private byte[] b1 = new byte[4096];
31 | private ByteBuf bb1 = Unpooled.wrappedBuffer(b1);
32 |
33 | private byte[] b2 = new byte[4096];
34 |
35 | @BeforeEach
36 | public void setup() {
37 | bb1.clear();
38 | Arrays.fill(b1, (byte) 0);
39 | Arrays.fill(b2, (byte) 0);
40 | }
41 |
42 | @Test
43 | public void testUnknownRequiredEnum() throws Exception {
44 | EnumTest2 lpet2 = new EnumTest2()
45 | .setE(E2.D2);
46 |
47 | assertEquals(E2.D2, lpet2.getE());
48 |
49 | Enums.EnumTest2 pbet2 = Enums.EnumTest2.newBuilder()
50 | .setE(Enums.E2.D2)
51 | .build();
52 |
53 | assertEquals(pbet2.getSerializedSize(), lpet2.getSerializedSize());
54 |
55 | lpet2.writeTo(bb1);
56 | assertEquals(lpet2.getSerializedSize(), bb1.readableBytes());
57 |
58 | pbet2.writeTo(CodedOutputStream.newInstance(b2));
59 |
60 | assertArrayEquals(b1, b2);
61 |
62 | EnumTest1 parsed = new EnumTest1();
63 | try {
64 | parsed.parseFrom(bb1, bb1.readableBytes());
65 | fail("Should have failed");
66 | } catch (IllegalStateException e) {
67 | assertTrue(e.getMessage().contains("Some required fields are missing"));
68 | }
69 | }
70 |
71 | @Test
72 | public void testUnknownOptionalEnum() throws Exception {
73 | EnumTest2 lpet2 = new EnumTest2()
74 | .setE(E2.D2);
75 |
76 | assertEquals(E2.D2, lpet2.getE());
77 |
78 | Enums.EnumTest2 pbet2 = Enums.EnumTest2.newBuilder()
79 | .setE(Enums.E2.D2)
80 | .build();
81 |
82 | assertEquals(pbet2.getSerializedSize(), lpet2.getSerializedSize());
83 |
84 | lpet2.writeTo(bb1);
85 | assertEquals(lpet2.getSerializedSize(), bb1.readableBytes());
86 |
87 | pbet2.writeTo(CodedOutputStream.newInstance(b2));
88 |
89 | assertArrayEquals(b1, b2);
90 |
91 | EnumTest1Optional parsed = new EnumTest1Optional();
92 | parsed.parseFrom(bb1, bb1.readableBytes());
93 | assertFalse(parsed.hasE());
94 | }
95 |
96 | @Test
97 | public void testUnknownRepeatedEnum() throws Exception {
98 | EnumTest2Repeated lpet2 = new EnumTest2Repeated();
99 | lpet2.addE(E2.A2);
100 | lpet2.addE(E2.B2);
101 | lpet2.addE(E2.C2);
102 | lpet2.addE(E2.D2);
103 |
104 | assertEquals(4, lpet2.getEsCount());
105 |
106 | Enums.EnumTest2Repeated pbet2 = Enums.EnumTest2Repeated.newBuilder()
107 | .addE(Enums.E2.A2)
108 | .addE(Enums.E2.B2)
109 | .addE(Enums.E2.C2)
110 | .addE(Enums.E2.D2)
111 | .build();
112 |
113 | assertEquals(pbet2.getSerializedSize(), lpet2.getSerializedSize());
114 |
115 | lpet2.writeTo(bb1);
116 | assertEquals(lpet2.getSerializedSize(), bb1.readableBytes());
117 |
118 | pbet2.writeTo(CodedOutputStream.newInstance(b2));
119 |
120 | assertArrayEquals(b1, b2);
121 |
122 | EnumTest1Repeated parsed = new EnumTest1Repeated();
123 | parsed.parseFrom(bb1, bb1.readableBytes());
124 | assertEquals(3, parsed.getEsCount());
125 | assertEquals(E1.A1, parsed.getEAt(0));
126 | assertEquals(E1.B1, parsed.getEAt(1));
127 | assertEquals(E1.C1, parsed.getEAt(2));
128 | }
129 |
130 | @Test
131 | public void testUnknownRepeatedPackedEnum() throws Exception {
132 | EnumTest2Packed lpet2 = new EnumTest2Packed();
133 | lpet2.addE(E2.A2);
134 | lpet2.addE(E2.B2);
135 | lpet2.addE(E2.C2);
136 | lpet2.addE(E2.D2);
137 |
138 | assertEquals(4, lpet2.getEsCount());
139 |
140 | Enums.EnumTest2Packed pbet2 = Enums.EnumTest2Packed.newBuilder()
141 | .addE(Enums.E2.A2)
142 | .addE(Enums.E2.B2)
143 | .addE(Enums.E2.C2)
144 | .addE(Enums.E2.D2)
145 | .build();
146 |
147 | assertEquals(pbet2.getSerializedSize(), lpet2.getSerializedSize());
148 |
149 | lpet2.writeTo(bb1);
150 | assertEquals(lpet2.getSerializedSize(), bb1.readableBytes());
151 |
152 | pbet2.writeTo(CodedOutputStream.newInstance(b2));
153 |
154 | assertArrayEquals(b1, b2);
155 |
156 | EnumTest1Packed parsed = new EnumTest1Packed();
157 | parsed.parseFrom(bb1, bb1.readableBytes());
158 | assertEquals(3, parsed.getEsCount());
159 | assertEquals(E1.A1, parsed.getEAt(0));
160 | assertEquals(E1.B1, parsed.getEAt(1));
161 | assertEquals(E1.C1, parsed.getEAt(2));
162 | }
163 | }
164 |
--------------------------------------------------------------------------------
/tests/src/test/java/com/github/splunk/lightproto/tests/LightProtoCodecTest.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright 2020 Splunk Inc.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.github.splunk.lightproto.tests;
17 |
18 | import com.google.protobuf.CodedInputStream;
19 | import com.google.protobuf.CodedOutputStream;
20 | import io.netty.buffer.ByteBuf;
21 | import io.netty.buffer.Unpooled;
22 | import org.junit.jupiter.api.BeforeEach;
23 | import org.junit.jupiter.params.ParameterizedTest;
24 | import org.junit.jupiter.params.provider.ValueSource;
25 |
26 | import java.nio.charset.StandardCharsets;
27 | import java.util.Arrays;
28 |
29 | import static org.junit.jupiter.api.Assertions.assertEquals;
30 |
31 | public class LightProtoCodecTest {
32 |
33 | private byte[] b = new byte[4096];
34 | private ByteBuf bb = Unpooled.wrappedBuffer(b);
35 |
36 | @BeforeEach
37 | public void setup() {
38 | bb.clear();
39 | Arrays.fill(b, (byte) 0);
40 | }
41 |
42 | @ParameterizedTest
43 | @ValueSource(ints = {Integer.MIN_VALUE, -1000, -100, -2, -1, 0, 1, 10, 100, 1000, (int) 1e4, (int) 1e5, (int) 1e7, Integer.MAX_VALUE})
44 | public void testVarInt(int i) throws Exception {
45 | LightProtoCodec.writeVarInt(bb, i);
46 |
47 | CodedInputStream is = CodedInputStream.newInstance(b);
48 | int res = is.readRawVarint32();
49 | assertEquals(i, res);
50 |
51 | res = LightProtoCodec.readVarInt(bb);
52 | assertEquals(i, res);
53 |
54 | assertEquals(CodedOutputStream.computeInt32SizeNoTag(i), LightProtoCodec.computeVarIntSize(i));
55 | }
56 |
57 | @ParameterizedTest
58 | @ValueSource(longs = {Long.MIN_VALUE, -10000000, -100, -2, -1, 0, 1, 10, 100, 10000000, (long) 2e18, (long) 2e32, (long) 2e43, (long) 2e57, Long.MAX_VALUE})
59 | public void testVarInt64(long i) throws Exception {
60 | LightProtoCodec.writeVarInt64(bb, i);
61 |
62 | CodedInputStream is = CodedInputStream.newInstance(b);
63 | long res = is.readRawVarint64();
64 | assertEquals(i, res);
65 |
66 | res = LightProtoCodec.readVarInt64(bb);
67 | assertEquals(i, res);
68 |
69 | assertEquals(CodedOutputStream.computeInt64SizeNoTag(i), LightProtoCodec.computeVarInt64Size(i));
70 | }
71 |
72 | @ParameterizedTest
73 | @ValueSource(ints = {Integer.MIN_VALUE, -1000, -100, -2, -1, 0, 1, 10, 100, 1000, Integer.MAX_VALUE})
74 | public void testSignedVarInt(int i) throws Exception {
75 | LightProtoCodec.writeSignedVarInt(bb, i);
76 |
77 | CodedInputStream is = CodedInputStream.newInstance(b);
78 | int res = is.readSInt32();
79 | assertEquals(i, res);
80 |
81 | res = LightProtoCodec.readSignedVarInt(bb);
82 | assertEquals(i, res);
83 |
84 | assertEquals(CodedOutputStream.computeSInt32SizeNoTag(i), LightProtoCodec.computeSignedVarIntSize(i));
85 | }
86 |
87 | @ParameterizedTest
88 | @ValueSource(longs = {Long.MIN_VALUE, -10000000, -100, -2, -1, 0, 1, 10, 100, 10000000, Long.MAX_VALUE})
89 | public void testSignedVarInt64(long i) throws Exception {
90 | LightProtoCodec.writeSignedVarInt64(bb, i);
91 |
92 | CodedInputStream is = CodedInputStream.newInstance(b);
93 | long res = is.readSInt64();
94 | assertEquals(i, res);
95 |
96 | res = LightProtoCodec.readSignedVarInt64(bb);
97 | assertEquals(i, res);
98 |
99 | assertEquals(CodedOutputStream.computeSInt64SizeNoTag(i), LightProtoCodec.computeSignedVarInt64Size(i));
100 | }
101 |
102 | @ParameterizedTest
103 | @ValueSource(ints = {Integer.MIN_VALUE, -1000, -100, -2, -1, 0, 1, 10, 100, 1000, Integer.MAX_VALUE})
104 | public void testFixedInt32(int i) throws Exception {
105 | LightProtoCodec.writeFixedInt32(bb, i);
106 |
107 | CodedInputStream is = CodedInputStream.newInstance(b);
108 | int res = is.readFixed32();
109 | assertEquals(i, res);
110 |
111 | res = LightProtoCodec.readFixedInt32(bb);
112 | assertEquals(i, res);
113 | }
114 |
115 | @ParameterizedTest
116 | @ValueSource(longs = {Long.MIN_VALUE, -10000000, -100, -2, -1, 0, 1, 10, 100, 10000000, Long.MAX_VALUE})
117 | public void testFixedInt64(long i) throws Exception {
118 | LightProtoCodec.writeFixedInt64(bb, i);
119 |
120 | CodedInputStream is = CodedInputStream.newInstance(b);
121 | long res = is.readFixed64();
122 | assertEquals(i, res);
123 |
124 | res = LightProtoCodec.readFixedInt64(bb);
125 | assertEquals(i, res);
126 | }
127 |
128 | @ParameterizedTest
129 | @ValueSource(floats = {Float.MIN_VALUE, -1000.0f, -100.0f, -2.f, -1.f, 0f, 1f, 10f, 100f, 1000f, Float.MAX_VALUE})
130 | public void testFloat(float i) throws Exception {
131 | LightProtoCodec.writeFloat(bb, i);
132 |
133 | CodedInputStream is = CodedInputStream.newInstance(b);
134 | float res = is.readFloat();
135 | assertEquals(i, res);
136 |
137 | res = LightProtoCodec.readFloat(bb);
138 | assertEquals(i, res);
139 | }
140 |
141 | @ParameterizedTest
142 | @ValueSource(doubles = {Double.MIN_VALUE, -10000000.0, -100.0, -2.0, -1.0, 0.0, 1.0, 10.0, 100.0, 10000000.0, Double.MAX_VALUE})
143 | public void testDouble(double i) throws Exception {
144 | LightProtoCodec.writeDouble(bb, i);
145 |
146 | CodedInputStream is = CodedInputStream.newInstance(b);
147 | double res = is.readDouble();
148 | assertEquals(i, res);
149 |
150 | res = LightProtoCodec.readDouble(bb);
151 | assertEquals(i, res);
152 | }
153 |
154 | @ParameterizedTest
155 | @ValueSource(strings = {"hello", "UTF16 Ελληνικά Русский 日本語", "Neque porro quisquam est qui dolorem ipsum"})
156 | public void testString(String s) throws Exception {
157 | byte[] sb = s.getBytes(StandardCharsets.UTF_8);
158 | assertEquals(sb.length, LightProtoCodec.computeStringUTF8Size(s));
159 |
160 | LightProtoCodec.writeVarInt(bb, sb.length);
161 | int idx = bb.writerIndex();
162 | LightProtoCodec.writeString(bb, s, sb.length);
163 |
164 | CodedInputStream is = CodedInputStream.newInstance(b);
165 | assertEquals(s, is.readString());
166 |
167 | assertEquals(sb.length, LightProtoCodec.readVarInt(bb));
168 | assertEquals(s, LightProtoCodec.readString(bb, idx, sb.length));
169 |
170 | assertEquals(CodedOutputStream.computeStringSizeNoTag(s), LightProtoCodec.computeVarIntSize(sb.length) + LightProtoCodec.computeStringUTF8Size(s));
171 | }
172 | }
173 |
--------------------------------------------------------------------------------
/tests/src/test/java/com/github/splunk/lightproto/tests/MessagesTest.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright 2020 Splunk Inc.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.github.splunk.lightproto.tests;
17 |
18 | import com.google.protobuf.CodedOutputStream;
19 | import io.netty.buffer.ByteBuf;
20 | import io.netty.buffer.Unpooled;
21 | import org.junit.jupiter.api.BeforeEach;
22 | import org.junit.jupiter.api.Test;
23 |
24 | import java.util.*;
25 |
26 | import static org.junit.jupiter.api.Assertions.*;
27 |
28 | public class MessagesTest {
29 |
30 | private byte[] b1 = new byte[4096];
31 | private ByteBuf bb1 = Unpooled.wrappedBuffer(b1);
32 |
33 | private byte[] b2 = new byte[4096];
34 |
35 | @BeforeEach
36 | public void setup() {
37 | bb1.clear();
38 | Arrays.fill(b1, (byte) 0);
39 | Arrays.fill(b2, (byte) 0);
40 | }
41 |
42 | @Test
43 | public void testMessages() throws Exception {
44 | M lpm = new M();
45 | lpm.setX()
46 | .setA("a")
47 | .setB("b");
48 |
49 | assertEquals(Collections.emptyList(), lpm.getItemsList());
50 |
51 | lpm.addItem()
52 | .setK("k1")
53 | .setV("v1");
54 |
55 | lpm.addItem()
56 | .setK("k2")
57 | .setV("v2")
58 | .setXx().setN(5);
59 |
60 | assertTrue(lpm.hasX());
61 | assertTrue(lpm.getX().hasA());
62 | assertTrue(lpm.getX().hasB());
63 | assertEquals(2, lpm.getItemsCount());
64 |
65 | assertEquals("k1", lpm.getItemAt(0).getK());
66 | assertEquals("v1", lpm.getItemAt(0).getV());
67 | assertEquals("k2", lpm.getItemAt(1).getK());
68 | assertEquals("v2", lpm.getItemAt(1).getV());
69 | assertEquals(5, lpm.getItemAt(1).getXx().getN());
70 | assertEquals("a", lpm.getX().getA());
71 | assertEquals("b", lpm.getX().getB());
72 |
73 | List itemsList = lpm.getItemsList();
74 | assertEquals(2, itemsList.size());
75 | assertEquals("k1", itemsList.get(0).getK());
76 | assertEquals("v1", itemsList.get(0).getV());
77 | assertEquals("k2", itemsList.get(1).getK());
78 | assertEquals("v2", itemsList.get(1).getV());
79 | assertEquals(5, itemsList.get(1).getXx().getN());
80 |
81 |
82 | Messages.X pbmx = Messages.X.newBuilder()
83 | .setA("a")
84 | .setB("b")
85 | .build();
86 |
87 | Messages.M.KV.XX pbm_xx = Messages.M.KV.XX.newBuilder()
88 | .setN(5)
89 | .build();
90 | Messages.M.KV pbm_kv1 = Messages.M.KV.newBuilder()
91 | .setK("k1")
92 | .setV("v1")
93 | .build();
94 | Messages.M.KV pbm_kv2 = Messages.M.KV.newBuilder()
95 | .setK("k2")
96 | .setV("v2")
97 | .setXx(pbm_xx)
98 | .build();
99 |
100 | Messages.M pbm = Messages.M.newBuilder()
101 | .setX(pbmx)
102 | .addItems(pbm_kv1)
103 | .addItems(pbm_kv2)
104 | .build();
105 |
106 | assertEquals(pbm.getSerializedSize(), lpm.getSerializedSize());
107 |
108 | lpm.writeTo(bb1);
109 | assertEquals(lpm.getSerializedSize(), bb1.readableBytes());
110 |
111 | pbm.writeTo(CodedOutputStream.newInstance(b2));
112 |
113 | assertArrayEquals(b1, b2);
114 |
115 | M parsed = new M();
116 | parsed.parseFrom(bb1, bb1.readableBytes());
117 |
118 | assertTrue(parsed.hasX());
119 | assertTrue(parsed.getX().hasA());
120 | assertTrue(parsed.getX().hasB());
121 | assertEquals(2, parsed.getItemsCount());
122 |
123 | assertEquals("k1", parsed.getItemAt(0).getK());
124 | assertEquals("v1", parsed.getItemAt(0).getV());
125 | assertEquals("k2", parsed.getItemAt(1).getK());
126 | assertEquals("v2", parsed.getItemAt(1).getV());
127 | assertEquals(5, parsed.getItemAt(1).getXx().getN());
128 | assertEquals("a", parsed.getX().getA());
129 | assertEquals("b", parsed.getX().getB());
130 | }
131 |
132 | @Test
133 | public void testCopyFrom() throws Exception {
134 | M lp1 = new M();
135 | lp1.setX()
136 | .setA("a")
137 | .setB("b");
138 |
139 | M lp2 = new M();
140 | lp2.copyFrom(lp1);
141 |
142 | assertTrue(lp2.hasX());
143 | assertTrue(lp2.getX().hasA());
144 | assertTrue(lp2.getX().hasB());
145 | assertEquals("a", lp2.getX().getA());
146 | assertEquals("b", lp2.getX().getB());
147 | }
148 |
149 | @Test
150 | public void testAddAll() throws Exception {
151 | List kvs = new ArrayList<>();
152 | kvs.add(new M.KV().setK("k1").setV("v1"));
153 | kvs.add(new M.KV().setK("k2").setV("v2"));
154 | kvs.add(new M.KV().setK("k3").setV("v3"));
155 |
156 | M lp = new M()
157 | .addAllItems(kvs);
158 |
159 | assertEquals(3, lp.getItemsCount());
160 | assertEquals("k1", lp.getItemAt(0).getK());
161 | assertEquals("v1", lp.getItemAt(0).getV());
162 | assertEquals("k2", lp.getItemAt(1).getK());
163 | assertEquals("v2", lp.getItemAt(1).getV());
164 | assertEquals("k3", lp.getItemAt(2).getK());
165 | assertEquals("v3", lp.getItemAt(2).getV());
166 | }
167 |
168 | @Test
169 | public void testClearNestedMessage() throws Exception {
170 | M m = new M();
171 | m.setX()
172 | .setA("a")
173 | .setB("b");
174 |
175 | m.clear();
176 | assertFalse(m.hasX());
177 |
178 | m.setX();
179 | assertTrue(m.hasX());
180 | assertFalse(m.getX().hasA());
181 | assertFalse(m.getX().hasB());
182 | }
183 |
184 | @Test
185 | public void testByteArrays() throws Exception {
186 | M lp1 = new M();
187 | lp1.setX()
188 | .setA("a")
189 | .setB("b");
190 |
191 | byte[] a1 = lp1.toByteArray();
192 | assertEquals(lp1.getSerializedSize(), a1.length);
193 |
194 | lp1.writeTo(bb1);
195 | assertEquals(bb1, Unpooled.wrappedBuffer(a1));
196 |
197 | M parsed = new M();
198 | parsed.parseFrom(a1);
199 | assertTrue(parsed.hasX());
200 | assertTrue(parsed.getX().hasB());
201 | assertEquals("a", parsed.getX().getA());
202 | assertEquals("b", parsed.getX().getB());
203 | }
204 | }
205 |
--------------------------------------------------------------------------------
/tests/src/test/java/com/github/splunk/lightproto/tests/NumbersTest.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright 2020 Splunk Inc.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.github.splunk.lightproto.tests;
17 |
18 | import com.google.protobuf.CodedOutputStream;
19 | import io.netty.buffer.ByteBuf;
20 | import io.netty.buffer.Unpooled;
21 | import org.junit.jupiter.api.BeforeEach;
22 | import org.junit.jupiter.api.Test;
23 |
24 | import java.util.Arrays;
25 |
26 | import static org.junit.jupiter.api.Assertions.*;
27 |
28 | public class NumbersTest {
29 |
30 | private byte[] b1 = new byte[4096];
31 | private ByteBuf bb1 = Unpooled.wrappedBuffer(b1);
32 |
33 | private byte[] b2 = new byte[4096];
34 | private ByteBuf bb2 = Unpooled.wrappedBuffer(b2);
35 |
36 | private static void assertException(Runnable r) {
37 | try {
38 | r.run();
39 | fail("Should raise exception");
40 | } catch (IllegalStateException e) {
41 | // Expected
42 | }
43 | }
44 |
45 | @BeforeEach
46 | public void setup() {
47 | bb1.clear();
48 | Arrays.fill(b1, (byte) 0);
49 |
50 | bb2.clear();
51 | Arrays.fill(b2, (byte) 0);
52 | }
53 |
54 | @Test
55 | public void testEnumValue() throws Exception {
56 | assertEquals(Enum1.X1_0_VALUE, Enum1.X1_0.getValue());
57 | assertEquals(Enum1.X1_1_VALUE, Enum1.X1_1.getValue());
58 | assertEquals(Enum1.X1_2_VALUE, Enum1.X1_2.getValue());
59 | }
60 |
61 | @Test
62 | public void testEmpty() throws Exception {
63 | Numbers lpn = new Numbers();
64 | NumbersOuterClass.Numbers pbn = NumbersOuterClass.Numbers.newBuilder().build();
65 | verify(lpn, pbn);
66 | }
67 |
68 | private void verify(Numbers lpn, NumbersOuterClass.Numbers pbn) throws Exception {
69 | assertEquals(pbn.getSerializedSize(), lpn.getSerializedSize());
70 |
71 | lpn.writeTo(bb1);
72 | assertEquals(lpn.getSerializedSize(), bb1.readableBytes());
73 |
74 | pbn.writeTo(CodedOutputStream.newInstance(b2));
75 |
76 | assertArrayEquals(b1, b2);
77 |
78 | Numbers parsed = new Numbers();
79 | parsed.parseFrom(bb1, bb1.readableBytes());
80 |
81 | assertEquals(pbn.hasEnum1(), parsed.hasEnum1());
82 | assertEquals(pbn.hasEnum2(), parsed.hasEnum2());
83 | assertEquals(pbn.hasXBool(), parsed.hasXBool());
84 | assertEquals(pbn.hasXDouble(), parsed.hasXDouble());
85 | assertEquals(pbn.hasXFixed32(), parsed.hasXFixed32());
86 | assertEquals(pbn.hasXFixed64(), parsed.hasXFixed64());
87 | assertEquals(pbn.hasXFixed32(), parsed.hasXSfixed32());
88 | assertEquals(pbn.hasXSfixed64(), parsed.hasXSfixed64());
89 | assertEquals(pbn.hasXFloat(), parsed.hasXFloat());
90 | assertEquals(pbn.hasXInt32(), parsed.hasXInt32());
91 | assertEquals(pbn.hasXInt64(), parsed.hasXInt64());
92 | assertEquals(pbn.hasXSint32(), parsed.hasXSint32());
93 | assertEquals(pbn.hasXSint64(), parsed.hasXSint64());
94 |
95 | if (parsed.hasEnum1()) {
96 | assertEquals(pbn.getEnum1().getNumber(), parsed.getEnum1().getValue());
97 | }
98 | if (parsed.hasEnum2()) {
99 | assertEquals(pbn.getEnum2().getNumber(), parsed.getEnum2().getValue());
100 | }
101 | if (parsed.hasXBool()) {
102 | assertEquals(pbn.getXBool(), parsed.isXBool());
103 | }
104 | if (parsed.hasXDouble()) {
105 | assertEquals(pbn.getXDouble(), parsed.getXDouble());
106 | }
107 | if (parsed.hasXFixed32()) {
108 | assertEquals(pbn.getXFixed32(), parsed.getXFixed32());
109 | }
110 | if (parsed.hasXFixed64()) {
111 | assertEquals(pbn.getXFixed64(), parsed.getXFixed64());
112 | }
113 | if (parsed.hasXSfixed32()) {
114 | assertEquals(pbn.getXSfixed32(), parsed.getXSfixed32());
115 | }
116 | if (parsed.hasXSfixed64()) {
117 | assertEquals(pbn.getXSfixed64(), parsed.getXSfixed64());
118 | }
119 | if (parsed.hasXFloat()) {
120 | assertEquals(pbn.getXFloat(), parsed.getXFloat());
121 | }
122 | if (parsed.hasXInt32()) {
123 | assertEquals(pbn.getXInt32(), parsed.getXInt32());
124 | }
125 | if (parsed.hasXInt64()) {
126 | assertEquals(pbn.getXInt64(), parsed.getXInt64());
127 | }
128 | if (parsed.hasXSint32()) {
129 | assertEquals(pbn.getXSint32(), parsed.getXSint32());
130 | }
131 | if (parsed.hasXSint64()) {
132 | assertEquals(pbn.getXSint64(), parsed.getXSint64());
133 | }
134 | }
135 |
136 | @Test
137 | public void testNumberFields() throws Exception {
138 | Numbers lpn = new Numbers();
139 | NumbersOuterClass.Numbers.Builder pbn = NumbersOuterClass.Numbers.newBuilder();
140 |
141 | assertFalse(lpn.hasEnum1());
142 | assertFalse(lpn.hasEnum2());
143 | assertFalse(lpn.hasXBool());
144 | assertFalse(lpn.hasXDouble());
145 | assertFalse(lpn.hasXFixed32());
146 | assertFalse(lpn.hasXFixed64());
147 | assertFalse(lpn.hasXSfixed32());
148 | assertFalse(lpn.hasXSfixed64());
149 | assertFalse(lpn.hasXFloat());
150 | assertFalse(lpn.hasXInt32());
151 | assertFalse(lpn.hasXInt64());
152 | assertFalse(lpn.hasXInt32());
153 | assertFalse(lpn.hasXUint64());
154 | assertFalse(lpn.hasXUint32());
155 | assertFalse(lpn.hasXSint32());
156 | assertFalse(lpn.hasXSint64());
157 |
158 | assertException(() -> lpn.getEnum1());
159 | assertException(() -> lpn.getEnum2());
160 | assertException(() -> lpn.isXBool());
161 | assertException(() -> lpn.getXDouble());
162 | assertException(() -> lpn.getXFixed32());
163 | assertException(() -> lpn.getXFixed64());
164 | assertException(() -> lpn.getXSfixed32());
165 | assertException(() -> lpn.getXSfixed64());
166 | assertException(() -> lpn.getXFloat());
167 | assertException(() -> lpn.getXInt32());
168 | assertException(() -> lpn.getXInt64());
169 | assertException(() -> lpn.getXInt32());
170 | assertException(() -> lpn.getXUint64());
171 | assertException(() -> lpn.getXUint32());
172 | assertException(() -> lpn.getXSint32());
173 | assertException(() -> lpn.getXSint64());
174 |
175 |
176 | lpn.setEnum1(Enum1.X1_1);
177 | lpn.setEnum2(Numbers.Enum2.X2_1);
178 | lpn.setXBool(true);
179 | lpn.setXDouble(1.0);
180 | lpn.setXFixed32(2);
181 | lpn.setXFixed64(12345L);
182 | lpn.setXSfixed32(-2);
183 | lpn.setXSfixed64(-12345L);
184 | lpn.setXFloat(1.2f);
185 | lpn.setXInt32(4);
186 | lpn.setXInt64(126L);
187 | lpn.setXUint32(40);
188 | lpn.setXUint64(1260L);
189 | lpn.setXSint32(-11);
190 | lpn.setXSint64(-12L);
191 |
192 | pbn.setEnum1(NumbersOuterClass.Enum1.X1_1);
193 | pbn.setEnum2(NumbersOuterClass.Numbers.Enum2.X2_1);
194 | pbn.setXBool(true);
195 | pbn.setXDouble(1.0);
196 | pbn.setXFixed32(2);
197 | pbn.setXFixed64(12345L);
198 | pbn.setXSfixed32(-2);
199 | pbn.setXSfixed64(-12345L);
200 | pbn.setXFloat(1.2f);
201 | pbn.setXInt32(4);
202 | pbn.setXInt64(126L);
203 | pbn.setXUint32(40);
204 | pbn.setXUint64(1260L);
205 | pbn.setXSint32(-11);
206 | pbn.setXSint64(-12L);
207 |
208 | assertTrue(lpn.hasEnum1());
209 | assertTrue(lpn.hasEnum2());
210 | assertTrue(lpn.hasXBool());
211 | assertTrue(lpn.hasXDouble());
212 | assertTrue(lpn.hasXFixed32());
213 | assertTrue(lpn.hasXFixed64());
214 | assertTrue(lpn.hasXSfixed32());
215 | assertTrue(lpn.hasXSfixed64());
216 | assertTrue(lpn.hasXFloat());
217 | assertTrue(lpn.hasXInt32());
218 | assertTrue(lpn.hasXInt64());
219 | assertTrue(lpn.hasXSint32());
220 | assertTrue(lpn.hasXSint64());
221 |
222 | assertEquals(Enum1.X1_1, lpn.getEnum1());
223 | assertEquals(Numbers.Enum2.X2_1, lpn.getEnum2());
224 | assertEquals(true, lpn.isXBool());
225 | assertEquals(1.0, lpn.getXDouble());
226 | assertEquals(2, lpn.getXFixed32());
227 | assertEquals(12345L, lpn.getXFixed64());
228 | assertEquals(-2, lpn.getXSfixed32());
229 | assertEquals(-12345L, lpn.getXSfixed64());
230 | assertEquals(1.2f, lpn.getXFloat());
231 | assertEquals(4, lpn.getXInt32());
232 | assertEquals(126L, lpn.getXInt64());
233 | assertEquals(40, lpn.getXUint32());
234 | assertEquals(1260L, lpn.getXUint64());
235 | assertEquals(-11, lpn.getXSint32());
236 | assertEquals(-12L, lpn.getXSint64());
237 |
238 | verify(lpn, pbn.build());
239 | }
240 | }
241 |
--------------------------------------------------------------------------------
/tests/src/test/java/com/github/splunk/lightproto/tests/RequiredTest.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright 2020 Splunk Inc.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.github.splunk.lightproto.tests;
17 |
18 | import com.google.protobuf.CodedOutputStream;
19 | import io.netty.buffer.ByteBuf;
20 | import io.netty.buffer.Unpooled;
21 | import org.junit.jupiter.api.BeforeEach;
22 | import org.junit.jupiter.api.Test;
23 |
24 | import java.util.Arrays;
25 |
26 | import static org.junit.jupiter.api.Assertions.*;
27 |
28 | public class RequiredTest {
29 |
30 | private byte[] b1 = new byte[4096];
31 | private ByteBuf bb1 = Unpooled.wrappedBuffer(b1);
32 |
33 | private byte[] b2 = new byte[4096];
34 |
35 | @BeforeEach
36 | public void setup() {
37 | bb1.clear();
38 | Arrays.fill(b1, (byte) 0);
39 | Arrays.fill(b2, (byte) 0);
40 | }
41 |
42 | @Test
43 | public void testMissingFields() throws Exception {
44 | R lpr = new R();
45 | try {
46 | lpr.writeTo(bb1);
47 | fail("Should fail to serialize");
48 | } catch (IllegalStateException e) {
49 | // Expected
50 | }
51 |
52 | assertFalse(lpr.hasA());
53 | assertFalse(lpr.hasB());
54 | assertFalse(lpr.hasC());
55 |
56 | assertEquals(5, lpr.getC()); // Default is set
57 |
58 | lpr.setA(1);
59 | assertTrue(lpr.hasA());
60 | lpr.clearA();
61 | assertFalse(lpr.hasA());
62 | lpr.setA(2);
63 |
64 | Required.R pbr = Required.R.newBuilder()
65 | .setA(2)
66 | .build();
67 |
68 | verify(lpr, pbr);
69 | }
70 |
71 | @Test
72 | public void testDeserializeWithMissingFields() throws Exception {
73 | NR lpnr = new NR()
74 | .setB(3);
75 |
76 | lpnr.writeTo(bb1);
77 |
78 | R lpr = new R();
79 | try {
80 | lpr.parseFrom(bb1, bb1.readableBytes());
81 | fail("Should fail to de-serialize");
82 | } catch (IllegalStateException e) {
83 | // Expected
84 | }
85 | }
86 |
87 | @Test
88 | public void testIgnoreUnknownFields() throws Exception {
89 | RExt lprext = new RExt()
90 | .setA(1)
91 | .setB(3)
92 | .setExtD(10)
93 | .setExtE(11)
94 | .setExtF(111L)
95 | .setExtG("hello");
96 | int s1 = lprext.getSerializedSize();
97 |
98 | lprext.writeTo(bb1);
99 |
100 | R lpr = new R();
101 | lpr.parseFrom(bb1, bb1.readableBytes());
102 |
103 | assertEquals(1, lpr.getA());
104 | assertEquals(3, lpr.getB());
105 | assertTrue(lpr.getSerializedSize() < s1);
106 | }
107 |
108 | private void verify(R lpr, Required.R pbr) throws Exception {
109 | assertEquals(pbr.getSerializedSize(), lpr.getSerializedSize());
110 |
111 | lpr.writeTo(bb1);
112 | assertEquals(lpr.getSerializedSize(), bb1.readableBytes());
113 |
114 | pbr.writeTo(CodedOutputStream.newInstance(b2));
115 |
116 | assertArrayEquals(b1, b2);
117 |
118 | R parsed = new R();
119 | parsed.parseFrom(bb1, bb1.readableBytes());
120 |
121 | assertEquals(pbr.hasA(), parsed.hasA());
122 | assertEquals(pbr.hasB(), parsed.hasB());
123 | assertEquals(pbr.hasC(), parsed.hasC());
124 |
125 | if (parsed.hasA()) {
126 | assertEquals(pbr.getA(), parsed.getA());
127 | }
128 | if (parsed.hasB()) {
129 | assertEquals(pbr.getB(), parsed.getB());
130 | }
131 | if (parsed.hasC()) {
132 | assertEquals(pbr.getC(), parsed.getC());
133 | }
134 | }
135 | }
136 |
--------------------------------------------------------------------------------
/tests/src/test/java/com/github/splunk/lightproto/tests/StringsTest.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright 2020 Splunk Inc.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.github.splunk.lightproto.tests;
17 |
18 | import com.google.protobuf.CodedOutputStream;
19 | import io.netty.buffer.ByteBuf;
20 | import io.netty.buffer.Unpooled;
21 | import org.junit.jupiter.api.BeforeEach;
22 | import org.junit.jupiter.api.Test;
23 |
24 | import java.util.ArrayList;
25 | import java.util.Arrays;
26 | import java.util.Set;
27 | import java.util.TreeSet;
28 |
29 | import static org.junit.jupiter.api.Assertions.*;
30 |
31 | public class StringsTest {
32 |
33 | private byte[] b1 = new byte[4096];
34 | private ByteBuf bb1 = Unpooled.wrappedBuffer(b1);
35 |
36 | private byte[] b2 = new byte[4096];
37 |
38 | @BeforeEach
39 | public void setup() {
40 | bb1.clear();
41 | Arrays.fill(b1, (byte) 0);
42 | Arrays.fill(b2, (byte) 0);
43 | }
44 |
45 | @Test
46 | public void testStrings() throws Exception {
47 | S lps = new S()
48 | .setId("id");
49 | lps.addName("a");
50 | lps.addName("b");
51 | lps.addName("c");
52 |
53 | assertEquals("id", lps.getId());
54 | assertEquals(3, lps.getNamesCount());
55 | assertEquals("a", lps.getNameAt(0));
56 | assertEquals("b", lps.getNameAt(1));
57 | assertEquals("c", lps.getNameAt(2));
58 |
59 | Strings.S pbs = Strings.S.newBuilder()
60 | .setId("id")
61 | .addNames("a")
62 | .addNames("b")
63 | .addNames("c")
64 | .build();
65 |
66 | assertEquals(pbs.getSerializedSize(), lps.getSerializedSize());
67 |
68 | lps.writeTo(bb1);
69 | assertEquals(lps.getSerializedSize(), bb1.readableBytes());
70 |
71 | pbs.writeTo(CodedOutputStream.newInstance(b2));
72 |
73 | assertArrayEquals(b1, b2);
74 |
75 | S parsed = new S();
76 | parsed.parseFrom(bb1, bb1.readableBytes());
77 |
78 | assertEquals("id", parsed.getId());
79 | assertEquals(3, parsed.getNamesCount());
80 | assertEquals("a", parsed.getNameAt(0));
81 | assertEquals("b", parsed.getNameAt(1));
82 | assertEquals("c", parsed.getNameAt(2));
83 | }
84 |
85 | @Test
86 | public void testAddAllStrings() throws Exception {
87 | Set strings = new TreeSet<>();
88 | strings.add("a");
89 | strings.add("b");
90 | strings.add("c");
91 |
92 | S lps = new S()
93 | .setId("id")
94 | .addAllNames(strings);
95 |
96 | assertEquals("id", lps.getId());
97 | assertEquals(3, lps.getNamesCount());
98 | assertEquals("a", lps.getNameAt(0));
99 | assertEquals("b", lps.getNameAt(1));
100 | assertEquals("c", lps.getNameAt(2));
101 | assertEquals(new ArrayList<>(strings), lps.getNamesList());
102 | }
103 |
104 | @Test
105 | public void testClearStrings() throws Exception {
106 | S lps = new S();
107 | lps.addName("a");
108 | lps.addName("b");
109 | lps.addName("c");
110 |
111 | lps.clear();
112 | lps.addName("d");
113 | lps.addName("e");
114 | assertEquals(2, lps.getNamesCount());
115 | assertEquals("d", lps.getNameAt(0));
116 | assertEquals("e", lps.getNameAt(1));
117 | }
118 | }
119 |
--------------------------------------------------------------------------------