feat[protobuf]: not support enum and extend in protobuf

This commit is contained in:
godotg
2023-12-02 22:31:33 +08:00
parent 6bc9eeaa10
commit 46dbac01ab
10 changed files with 41 additions and 642 deletions
@@ -112,17 +112,12 @@ public class JavaBuilder {
}
}
public String getAnnotationType(Field field, Proto proto, Map<String, ProtoEnum> protoEnums) {
public String getAnnotationType(Field field) {
String type = field.getTypeString();
if (BASE_TYPES.contains(type.toLowerCase(Locale.ENGLISH))) {
return "Type." + Type.valueOf(type.toUpperCase(Locale.ENGLISH));
} else {
String name = getJavaPackage(proto) + "." + type;
if (protoEnums.containsKey(name)) {
return "Type." + Type.ENUM;
} else {
return "Type." + Type.MESSAGE;
}
return "Type." + Type.MESSAGE;
}
}
@@ -134,14 +129,6 @@ public class JavaBuilder {
tmp.add(e);
});
}
List<Oneof> oneofs = msg.getOneofs();
if (oneofs != null) {
oneofs.forEach(o -> {
if (o.getFields() != null) {
o.getFields().forEach(tmp::add);
}
});
}
for (int i = 0; i < tmp.size(); i++) {
if (tmp.get(i) instanceof MapField) {
@@ -162,33 +149,6 @@ public class JavaBuilder {
cb.t(level).c(" */").ln();
}
private Map<String, ProtoEnum> getAllProtoEnum(Proto proto, Map<String, Proto> protos) {
Map<String, ProtoEnum> allEnums = new HashMap<>();
List<ProtoEnum> protoEnums = proto.getEnums();
if (protoEnums != null && !protoEnums.isEmpty()) {
for (ProtoEnum protoEnum : protoEnums) {
String packName = proto.getProtoPackage();
String javaPack = getJavaPackage(proto);
if (javaPack != null && javaPack.trim().length() > 0) {
packName = javaPack;
}
allEnums.put(packName + "." + protoEnum.getName(), protoEnum);
}
}
List<String> impProtos = proto.getImports();
if (impProtos == null || impProtos.isEmpty()) {
return allEnums;
}
for (String protoName : impProtos) {
Proto impProto = protos.get(protoName);
if (impProto == null) {
continue;
}
allEnums.putAll(getAllProtoEnum(impProto, protos));
}
return allEnums;
}
private String getJavaPackage(Proto proto) {
if (CollectionUtils.isEmpty(proto.getOptions())) {
return StringUtils.EMPTY;
@@ -202,7 +162,6 @@ public class JavaBuilder {
}
public String buildMessage(Proto proto, ProtoMessage msg, int indent, Map<String, String> defineMsgs, PbBuildOption buildOps, Map<String, Proto> protos) {
Map<String, ProtoEnum> protoEnums = getAllProtoEnum(proto, protos);
int level = Math.max(indent, 1);
final CodeBuilder cb = new CodeBuilder();
List<Field> tmp = new ArrayList<>();
@@ -235,7 +194,7 @@ public class JavaBuilder {
getCode = new CodeBuilder();
setCode = new CodeBuilder();
String typeName = getAnnotationType(f, proto, protoEnums);
String typeName = getAnnotationType(f);
if (msg.getName().equals("Type")) {
typeName = Proto.class.getPackage().getName() + ".wire.Field." + typeName;
}
@@ -65,17 +65,6 @@ public class IfaceGenerator {
JavaBuilder builder = new JavaBuilder();
Map<String, String> msgComments = new HashMap<>();
List<ProtoEnum> enums = proto.getEnums();
if (CollectionUtils.isNotEmpty(enums)) {
String enumPath = srcPath + File.separator;
enums.stream().sorted(Comparator.comparing(ProtoEnum::getName))
.forEach(it -> {
var code = builder.buildEnum(it, 1, buildOps);
var filePath = enumPath + File.separator + it.getName() + ".java";
FileUtils.writeStringToFile(new File(filePath), code, false);
}
);
}
List<ProtoMessage> msgs = proto.getMessages();
if (CollectionUtils.isNotEmpty(msgs)) {
@@ -1,67 +0,0 @@
/*
* Copyright 2021 The edap Project
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and limitations under the License.
*/
package com.zfoo.protocol.serializer.protobuf.wire;
import java.util.ArrayList;
import java.util.List;
/**
* protocol buffer扩展信息的定义
*/
public class Extend {
private Comment comment;
private String name;
private List<Field> fields;
public Extend setName(String name) {
this.name = name;
return this;
}
public String getName() {
return name;
}
public Extend setComment(Comment comment) {
this.comment = comment;
return this;
}
public Comment getComment() {
return comment;
}
public Extend addField(Field field) {
if (field == null) {
return this;
}
getFields().add(field);
return this;
}
public List<Field> getFields() {
if (fields == null) {
fields = new ArrayList<>();
}
return fields;
}
public void setFields(List<Field> fields) {
if (fields instanceof ArrayList) {
this.fields = fields;
} else {
getFields().addAll(fields);
}
}
}
@@ -1,84 +0,0 @@
/*
* Copyright 2021 The edap Project
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and limitations under the License.
*/
package com.zfoo.protocol.serializer.protobuf.wire;
import com.zfoo.protocol.serializer.protobuf.wire.parser.ProtoParser;
/**
* protocol buffer 扩展tag的结构定义
*/
public class Extensions {
/**
* 扩展开始的Tag编号
*/
private int startTag;
/**
* 扩展结束的Tag编号
*/
private int endTag;
public Extensions setEndTag(int endTag) {
this.endTag = endTag;
return this;
}
public int getEndTag() {
return endTag;
}
public Extensions setStartTag(int startTag) {
this.startTag = startTag;
return this;
}
public int getStartTag() {
return startTag;
}
public static Extensions parseExtensions(String expression) {
String exp = expression.trim();
if (exp.isEmpty()) {
throw new RuntimeException("extensions expression is empty");
}
int index = exp.indexOf("to");
if (index < 0) {
throw new RuntimeException("extensions expression must be start to end");
}
String sstart = exp.substring(0, index).trim();
if (sstart.isEmpty()) {
throw new RuntimeException("extensions expression start empty");
}
int start = ProtoParser.parseInt(sstart);
if (start < 1) {
throw new RuntimeException("extensions expression start cann't be " + start);
}
String sEnd = exp.substring(index + 2).trim();
if (sEnd.isEmpty()) {
throw new RuntimeException("extensions expression end empty");
}
int end;
if ("max".equalsIgnoreCase(sEnd)) {
end = WireFormat.MAX_TAG_VALUE;
} else {
end = ProtoParser.parseInt(sEnd);
}
if (end <= start) {
throw new RuntimeException("extensions start tag <= end tag");
}
Extensions ext = new Extensions();
ext.setStartTag(start).setEndTag(end);
return ext;
}
}
@@ -1,78 +0,0 @@
/*
* Copyright 2021 The edap Project
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and limitations under the License.
*/
package com.zfoo.protocol.serializer.protobuf.wire;
import java.util.ArrayList;
import java.util.List;
/**
* Oneof结构体定义,oneof定义几个属性必须有一个赋值的功能
*/
public class Oneof {
/**
* Oneof标示的名称
*/
private String name;
/**
* Oneof包含的属性列表
*/
private List<Field> fields;
/**
* Oneof的注释
*/
private Comment comment;
public Oneof setName(String name) {
this.name = name;
return this;
}
public String getName() {
return name;
}
public Oneof setComment(Comment comment) {
this.comment = comment;
return this;
}
public Comment getComment() {
return comment;
}
public void addField(Field field) {
if (getFields() == null) {
setFields(new ArrayList<>());
}
getFields().add(field);
}
/**
* Oneof包含的属性列表
*
* @return the fields
*/
public List<Field> getFields() {
return fields;
}
/**
* Oneof包含的属性列表
*
* @param fields the fields to set
*/
public void setFields(List<Field> fields) {
this.fields = fields;
}
}
@@ -36,23 +36,11 @@ public class ProtoMessage {
* 保留字段的设置
*/
private List<Reserved> reserveds;
/**
* 消息内嵌的扩展的消息列表
*/
private List<Extend> protoExtends;
/**
* 消息包含的扩展的列表
*/
private List<Extensions> extensionses;
/**
* 消息内置的枚举类型
*/
private List<ProtoEnum> enums;
/**
* 消息包含的Oneof的列表
*/
private List<Oneof> oneofs;
/**
* 消息的备注信息
*/
@@ -82,14 +70,6 @@ public class ProtoMessage {
return this;
}
public ProtoMessage addExtensions(Extensions extensions) {
if (extensions == null) {
return this;
}
getExtensionses().add(extensions);
return this;
}
public ProtoMessage addReserved(Reserved reserved) {
if (reserved == null) {
return this;
@@ -98,14 +78,6 @@ public class ProtoMessage {
return this;
}
public ProtoMessage addOneof(Oneof oneof) {
if (oneof == null) {
return this;
}
getOneofs().add(oneof);
return this;
}
/**
* 消息的名称
*
@@ -206,62 +178,6 @@ public class ProtoMessage {
return this;
}
/**
* 消息内嵌的扩展的消息列表
*
* @return the protoExtends
*/
public List<Extend> getProtoExtends() {
if (protoExtends == null) {
protoExtends = new ArrayList<>();
}
return protoExtends;
}
public ProtoMessage addProtoExtends(Extend extend) {
if (extend == null) {
return this;
}
getProtoExtends().add(extend);
return this;
}
/**
* 消息内嵌的扩展的消息列表
*
* @param protoExtends the protoExtends to set
*/
public ProtoMessage setProtoExtends(List<Extend> protoExtends) {
this.protoExtends = protoExtends;
return this;
}
/**
* 消息包含的扩展的列表
*
* @return the extensionses
*/
public List<Extensions> getExtensionses() {
if (extensionses == null) {
extensionses = new ArrayList<>();
}
return extensionses;
}
/**
* 消息包含的扩展的列表
*
* @param extensionses the extensionses to set
*/
public ProtoMessage setExtensionses(List<Extensions> extensionses) {
if (extensionses instanceof ArrayList) {
this.extensionses = extensionses;
} else {
this.extensionses = new ArrayList<>();
this.extensionses.addAll(extensionses);
}
return this;
}
/**
* 消息内置的枚举类型
@@ -289,32 +205,6 @@ public class ProtoMessage {
return this;
}
/**
* 消息包含的Oneof的列表
*
* @return the oneofs
*/
public List<Oneof> getOneofs() {
if (oneofs == null) {
oneofs = new ArrayList<>();
}
return oneofs;
}
/**
* 消息包含的Oneof的列表
*
* @param oneofs the oneofs to set
*/
public ProtoMessage setOneofs(List<Oneof> oneofs) {
if (oneofs instanceof ArrayList) {
this.oneofs = oneofs;
} else {
getOneofs().addAll(oneofs);
}
return this;
}
/**
* 消息的备注信息
*
@@ -53,14 +53,6 @@ public class Proto {
* 文档的注释
*/
private String comment;
/**
* 消息内置的枚举类型
*/
private List<ProtoEnum> enums = new ArrayList<>();
/**
* 消息内嵌的扩展的消息列表
*/
private List<Extend> protoExtends = new ArrayList<>();
/**
* proto文件的单行注释列表
*/
@@ -90,19 +82,6 @@ public class Proto {
return this;
}
public Proto addEnum(ProtoEnum protoEnum) {
getEnums().add(protoEnum);
return this;
}
public Proto addExtend(Extend extend) {
if (extend == null) {
return this;
}
getProtoExtends().add(extend);
return this;
}
/**
* Proto描述文件的名称
*
@@ -199,24 +178,6 @@ public class Proto {
return this;
}
/**
* 消息内置的枚举类型
*
* @return the enums
*/
public List<ProtoEnum> getEnums() {
return enums;
}
/**
* 消息内嵌的扩展的消息列表
*
* @return the protoExtends
*/
public List<Extend> getProtoExtends() {
return protoExtends;
}
/**
* proto文件的单行注释列表
*
@@ -18,7 +18,7 @@ import com.zfoo.protocol.serializer.protobuf.wire.*;
import com.zfoo.protocol.serializer.protobuf.wire.Comment.CommentType;
import com.zfoo.protocol.serializer.protobuf.wire.Field.Cardinality;
import com.zfoo.protocol.serializer.protobuf.wire.Field.Type;
import com.zfoo.protocol.serializer.protobuf.wire.ProtoEnum.EnumEntry;
import com.zfoo.protocol.util.StringUtils;
import java.util.*;
@@ -181,15 +181,10 @@ public class ProtoParser {
comments.clear();
break;
case "enum":
addCommentsToProto(proto);
ProtoEnum protoEnum = parseEnum();
proto.addEnum(protoEnum);
comments.clear();
notSupportEnum();
break;
case "extend":
addCommentsToProto(proto);
proto.addExtend(parseExtend());
comments.clear();
notSupportExtend();
break;
default:
break;
@@ -205,6 +200,21 @@ public class ProtoParser {
return proto;
}
private void notSupportEnum() {
var name = readToken();
throw new RuntimeException(StringUtils.format("zfoo not support enum definition in message:[{}]", name));
}
private void notSupportExtend() {
var name = readToken();
throw new RuntimeException(StringUtils.format("zfoo not support extend syntax in message:[{}]", name));
}
private void notSupportOneof() {
var name = readToken();
throw new RuntimeException(StringUtils.format("zfoo not support oneof field in message:[{}]", name));
}
private void addCommentsToProto(Proto proto) {
if (CollectionUtils.isEmpty(comments)) {
return;
@@ -228,56 +238,6 @@ public class ProtoParser {
+ (pos - rowsPos.get(row)) + "] not \"" + separatorChar + "\"");
}
public int enumValue(String number) {
int v = parseInt(number);
if (v < 0) {
throw new RuntimeException("Enum value can't is [" + v + "]");
}
return v;
}
public Extend parseExtend() throws RuntimeException {
trim();
String name = readToken();
if (name.length() == 0) {
throw new RuntimeException(ROW_MSG + row + "] extend name not set");
}
Extend ext = new Extend();
if (!comments.isEmpty()) {
ext.setComment(comments.get(comments.size() - 1));
comments.clear();
}
ext.setName(name);
System.out.println("extend " + name + START_MSG);
blockStarted("extend");
String token = readToken();
while (token.length() > 0) {
if ("//".equals(token)) {
String comment = readSingleLineComment();
addCommentLines(CommentType.INLINE, Arrays.asList(comment));
nextLine();
} else if (fieldCardinalities.contains(token)) {
Field field = parseField(
Cardinality.valueOf(token.toUpperCase(Locale.ENGLISH)),
null);
ext.addField(field);
} else {
Field field = parseField(Cardinality.OPTIONAL, token);
ext.addField(field);
}
boolean isEnd = blockEnd();
if (isEnd) {
fieldEnd();
return ext;
}
trim();
trimLines();
token = readToken();
}
throw new RuntimeException(ROW_MSG + row + "] extend not end");
}
public static int parseInt(String number) throws RuntimeException {
StringBuilder tagv = new StringBuilder();
for (int i = 0; i < number.length(); i++) {
@@ -330,9 +290,9 @@ public class ProtoParser {
* @throws RuntimeException
*/
private String readToken() throws RuntimeException {
trim();
StringBuilder token = new StringBuilder();
char c;
trim();
while (pos < data.length) {
c = data[pos];
if (c == '/' && token.length() == 0) {
@@ -426,86 +386,6 @@ public class ProtoParser {
|| (c == ')');
}
private ProtoEnum parseEnum() throws RuntimeException {
trim();
String name = readToken();
if (name.length() == 0) {
throw new RuntimeException(ROW_MSG + row + "] Enum name not set");
}
ProtoEnum protoEnum = new ProtoEnum();
protoEnum.setName(name);
System.out.println("Enum " + name + START_MSG);
blockStarted("enum");
nextLine();
trim();
List<EnumEntry> entries = new ArrayList<>();
String token = readToken();
while (token.length() > 0) {
if ("//".equals(token)) {
addCommentLine(CommentType.INLINE, readSingleLineComment());
nextLine();
} else if ("option".equals(token)) {
trim();
String optionLabel = readToken();
readValueSeparator('=');
ProtoValue pv = readValue();
String optionValue = pv.getValue();
Option option = new Option();
option.setName(optionLabel).setValue(optionValue);
protoEnum.setOptions(Arrays.asList(option));
} else {
EnumEntry entry = new EnumEntry();
entry.setLabel(token);
trim();
parseEnumItemValue(entry);
entries.add(entry);
}
boolean isEnd = blockEnd();
if (isEnd) {
fieldEnd();
System.out.println("Enum " + name + " end");
protoEnum.setEntries(entries);
return protoEnum;
}
trim();
token = readToken();
}
throw new RuntimeException("Enum has't end with '}'");
}
private void parseEnumItemValue(EnumEntry entry) throws RuntimeException {
try {
readValueSeparator('=');
} catch (Exception e) {
throw new RuntimeException("EnumEntry has't char '='", e);
}
String token;
ProtoValue pv = readValue();
int value = enumValue(pv.getValue());
entry.setValue(value);
if (pv.getOptions() != null) {
entry.setOptions(pv.getOptions());
}
trim();
String comment = "";
token = readToken();
if ("//".equals(token)) {
comment = readSingleLineComment();
}
nextLine();
if (comment != null && comment.length() > 0) {
List<String> cs = new ArrayList<>();
cs.add(comment);
addCommentLines(CommentType.INLINE, cs);
}
Comment cmt = null;
if (!comments.isEmpty()) {
cmt = comments.get(comments.size() - 1);
}
entry.setComment(cmt);
comments.clear();
}
private ProtoMessage parseMessage() throws RuntimeException {
ProtoMessage msg = new ProtoMessage();
trim();
@@ -531,19 +411,16 @@ public class ProtoParser {
null);
msg.addField(field);
} else if ("enum".equals(token)) {
ProtoEnum protoEnum = parseEnum();
msg.addEnum(protoEnum);
notSupportEnum();
} else if ("extend".equals(token)) {
notSupportExtend();
} else if ("oneof".equals(token)) {
notSupportOneof();
} else if ("message".equals(token)) {
msg.addMessage(parseMessage());
} else if ("extensions".equals(token)) {
String sextensions = parseExtensions();
Extensions extensions = Extensions.parseExtensions(sextensions);
msg.addExtensions(extensions);
} else if ("reserved".equals(token)) {
String reserved = parseReserved();
msg.addReserved(Reserved.parseReserved(reserved, comments));
} else if ("oneof".equals(token)) {
msg.addOneof(parseOneof());
} else {
Field field = parseField(Cardinality.OPTIONAL, token);
msg.addField(field);
@@ -569,48 +446,6 @@ public class ProtoParser {
}
}
private Oneof parseOneof() throws RuntimeException {
trim();
String name = readToken();
if (name.length() == 0) {
throw new RuntimeException(ROW_MSG + row + "] oneof name not set");
}
Oneof oneof = new Oneof();
if (!comments.isEmpty()) {
oneof.setComment(comments.get(comments.size() - 1));
comments.clear();
}
oneof.setName(name);
System.out.println(ONEOF_MSG + name + START_MSG);
blockStarted("oneof");
String token = readToken();
while (token.length() > 0) {
if ("//".equals(token)) {
String comment = readSingleLineComment();
addCommentLines(CommentType.INLINE, Arrays.asList(comment));
nextLine();
} else if (fieldCardinalities.contains(token)) {
Field field = parseField(
Cardinality.valueOf(token.toUpperCase(Locale.ENGLISH)),
null);
oneof.addField(field);
} else {
Field field = parseField(Cardinality.OPTIONAL, token);
oneof.addField(field);
}
boolean isEnd = blockEnd();
if (isEnd) {
System.out.println(ONEOF_MSG + name + " end");
fieldEnd();
return oneof;
}
trim();
token = readToken();
}
throw new RuntimeException("oneof not end");
}
private String parseReserved() throws RuntimeException {
return readExpression();
}
@@ -638,10 +473,6 @@ public class ProtoParser {
"] expression not end with char ';'");
}
private String parseExtensions() throws RuntimeException {
return readExpression();
}
private Field parseField(Cardinality cardinality, String fieldType) throws RuntimeException {
trim();
if (fieldType == null) {
@@ -3,7 +3,6 @@ syntax = "proto3";
package test.message;
import "one_enum.proto";
import "one_map.proto";
import "one_message.proto";
option java_package = "io.edap.protobuf.test.message.v3";
@@ -13,7 +12,6 @@ message AllType {
bool field1 = 1;
bytes field2 = 2;
double field3 = 3;
Corpus field4 = 4;
fixed32 field5 = 5;
fixed64 field6 = 6;
float field7 = 7;
@@ -5,17 +5,17 @@ package test.message;
option java_package = "io.edap.protobuf.test.message.v3";
message OneEnum {
Corpus corpus = 1;
}
enum Corpus {
UNIVERSAL = 0;
WEB = 1;
IMAGES = 2;
LOCAL = 3;
NEWS = 4;
PRODUCTS = 5;
VIDEO = 6;
}
//message OneEnum {
// Corpus corpus = 1;
//}
//
//
//enum Corpus {
// UNIVERSAL = 0;
// WEB = 1;
// IMAGES = 2;
// LOCAL = 3;
// NEWS = 4;
// PRODUCTS = 5;
// VIDEO = 6;
//}