func new(rootPackage string, rootMessage string, descSet *descriptor.FileDescriptorSet, path string) (*fdesc, error) { fieldpaths := strings.Split(path, ".") keys := make([]uint64, len(fieldpaths)) fields := make([]*descriptor.FieldDescriptorProto, len(fieldpaths)) curPackage := rootPackage curMessage := rootMessage last := len(fieldpaths) - 1 var fieldDesc *descriptor.FieldDescriptorProto for i, f := range fieldpaths { fieldName := f fieldDesc = descSet.GetField(curPackage, curMessage, fieldName) if fieldDesc == nil { curPackage, fieldDesc = descSet.FindExtension(curPackage, curMessage, fieldName) if fieldDesc == nil { return nil, &errChild{fieldName: fieldName, pkg: curPackage, msg: curMessage} } typeNames := strings.Split(fieldDesc.GetTypeName(), ".") curMessage = fieldDesc.GetTypeName() if len(typeNames) > 1 { curPackage = typeNames[1] curMessage = typeNames[2] } fieldKey := fieldDesc.GetKeyUint64() keys[i] = fieldKey fields[i] = fieldDesc } else { fieldKey := fieldDesc.GetKeyUint64() if fieldDesc.IsMessage() { curPackage, curMessage = descSet.FindMessage(curPackage, curMessage, fieldName) } else if i != last { return nil, &errMessage{fieldName} } keys[i] = fieldKey fields[i] = fieldDesc } } fd := &fdesc{curPackage, curMessage, fields, fieldDesc, keys, 0} if fieldDesc.GetType() == descriptor.FieldDescriptorProto_TYPE_ENUM { typeNames := strings.Split(fieldDesc.GetTypeName(), ".") enumMessage := fieldDesc.GetTypeName() enumPackage := curPackage if len(typeNames) > 1 { enumPackage = typeNames[1] enumMessage = typeNames[2] } enum := descSet.GetEnum(enumPackage, enumMessage) if enum == nil { return nil, &errChild{fieldName: fieldDesc.GetName(), pkg: enumPackage, msg: enumMessage} } for _, v := range enum.GetValue() { if v.GetNumber() < fd.firstEnumValue { fd.firstEnumValue = v.GetNumber() } } } return fd, nil }
//Collapses a proto fieldpath into a go fieldpath. They are different if some of the fields in the fieldpath have been embedded. func Collapse(rootPkg string, rootMsg string, path string, descriptorSet *descriptor.FileDescriptorSet) (string, error) { msg := descriptorSet.GetMessage(rootPkg, rootMsg) if msg == nil { return "", &errUndefined{rootPkg, rootMsg, path} } paths := strings.Split(path, ".") if len(paths) == 0 { return "", &errUndefined{rootPkg, rootMsg, path} } if len(paths) == 1 { return path, nil } for _, f := range msg.GetField() { if f.GetName() != paths[0] { continue } if f.IsMessage() { newRootPkg, newRootMsg := descriptorSet.FindMessage(rootPkg, rootMsg, f.GetName()) if len(newRootPkg) == 0 || len(newRootMsg) == 0 { return "", &errUndefined{rootPkg, rootMsg, path} } newPath, err := Collapse(newRootPkg, newRootMsg, strings.Join(paths[1:], "."), descriptorSet) if err != nil { return "", err } if gogoproto.IsEmbed(f) { return newPath, nil } else { return paths[0] + "." + newPath, nil } } } if msg.IsExtendable() { newRootPkg, f := descriptorSet.FindExtension(rootPkg, rootMsg, paths[0]) if f == nil { return "", &errUndefined{rootPkg, rootMsg, path} } typeName := f.GetTypeName() typeNames := strings.Split(typeName, ".") newRootMsg := typeName if len(typeNames) > 1 { newRootMsg = typeNames[len(typeNames)-1] } newPath, err := Collapse(newRootPkg, newRootMsg, strings.Join(paths[1:], "."), descriptorSet) if err != nil { return "", err } if gogoproto.IsEmbed(f) { return newPath, nil } else { return paths[0] + "." + newPath, nil } } return "", nil }