Prechádzať zdrojové kódy

fix(proto): fix encode/decode problem for repeated field

Signed-off-by: Jiyong Huang <huangjy@emqx.io>
Jiyong Huang 2 rokov pred
rodič
commit
2832dc4661

+ 2 - 1
internal/converter/protobuf/converter_test.go

@@ -37,7 +37,7 @@ func TestEncode(t *testing.T) {
 				"id":   1,
 				"id":   1,
 				"age":  1,
 				"age":  1,
 			},
 			},
-			e: "field email not found",
+			r: []byte{0x0a, 0x04, 0x74, 0x65, 0x73, 0x74, 0x10, 0x01, 0x1a, 0x00},
 		}, {
 		}, {
 			m: map[string]interface{}{
 			m: map[string]interface{}{
 				"name":  "test",
 				"name":  "test",
@@ -73,6 +73,7 @@ func TestDecode(t *testing.T) {
 				"name":  "test",
 				"name":  "test",
 				"id":    int64(1),
 				"id":    int64(1),
 				"email": "Dddd",
 				"email": "Dddd",
+				"code":  []interface{}{},
 			},
 			},
 			r: []byte{0x0a, 0x04, 0x74, 0x65, 0x73, 0x74, 0x10, 0x01, 0x1a, 0x04, 0x44, 0x64, 0x64, 0x64},
 			r: []byte{0x0a, 0x04, 0x74, 0x65, 0x73, 0x74, 0x10, 0x01, 0x1a, 0x04, 0x44, 0x64, 0x64, 0x64},
 		},
 		},

+ 5 - 1
internal/converter/protobuf/fieldConverterSingleton.go

@@ -66,7 +66,11 @@ func (fc *FieldConverter) encodeMap(im *desc.MessageDescriptor, i interface{}) (
 		for _, field := range fields {
 		for _, field := range fields {
 			v, ok := m[field.GetName()]
 			v, ok := m[field.GetName()]
 			if !ok {
 			if !ok {
-				return nil, fmt.Errorf("field %s not found", field.GetName())
+				if field.IsRequired() {
+					return nil, fmt.Errorf("field %s not found", field.GetName())
+				} else {
+					v = field.GetDefaultValue()
+				}
 			}
 			}
 			fv, err := fc.EncodeField(field, v)
 			fv, err := fc.EncodeField(field, v)
 			if err != nil {
 			if err != nil {

+ 1 - 1
internal/schema/registry_test.go

@@ -78,7 +78,7 @@ func TestRegistry(t *testing.T) {
 	expectedSchema := &Info{
 	expectedSchema := &Info{
 		Type:     "protobuf",
 		Type:     "protobuf",
 		Name:     "test1",
 		Name:     "test1",
-		Content:  "syntax = \"proto3\";message Person {string name = 1;int32 id = 2;string email = 3;}",
+		Content:  "syntax = \"proto2\";message Person {required string name = 1;optional int32 id = 2;optional string email = 3;repeated ListOfDoubles code = 4;}message ListOfDoubles {repeated double doubles=1;}",
 		FilePath: filepath.Join(etcDir, "test1.proto"),
 		FilePath: filepath.Join(etcDir, "test1.proto"),
 	}
 	}
 	gottenSchema, err := GetSchema("protobuf", "test1")
 	gottenSchema, err := GetSchema("protobuf", "test1")

+ 1 - 1
internal/schema/test/test1.proto

@@ -1 +1 @@
-syntax = "proto3";message Person {string name = 1;int32 id = 2;string email = 3;}
+syntax = "proto2";message Person {required string name = 1;optional int32 id = 2;optional string email = 3;repeated ListOfDoubles code = 4;}message ListOfDoubles {repeated double doubles=1;}

+ 4 - 0
pkg/cast/cast.go

@@ -828,6 +828,10 @@ func ToTypedSlice(input interface{}, conv func(interface{}, Strictness) (interfa
 	if s.Kind() != reflect.Slice {
 	if s.Kind() != reflect.Slice {
 		return nil, fmt.Errorf("cannot convert %[1]T(%[1]v) to %s slice)", input, eleType)
 		return nil, fmt.Errorf("cannot convert %[1]T(%[1]v) to %s slice)", input, eleType)
 	}
 	}
+	if s.Len() == 0 {
+		result := reflect.MakeSlice(reflect.TypeOf([]interface{}{}), s.Len(), s.Len())
+		return result.Interface(), nil
+	}
 	ele, err := conv(s.Index(0).Interface(), sn)
 	ele, err := conv(s.Index(0).Interface(), sn)
 	et := reflect.TypeOf(ele)
 	et := reflect.TypeOf(ele)
 	if err != nil || et == nil {
 	if err != nil || et == nil {