vendor/google.golang.org/protobuf/internal/encoding/tag/tag.go
changeset 260 445e01aede7e
parent 256 6d9efbef00a9
equal deleted inserted replaced
259:db4911b0c721 260:445e01aede7e
     9 import (
     9 import (
    10 	"reflect"
    10 	"reflect"
    11 	"strconv"
    11 	"strconv"
    12 	"strings"
    12 	"strings"
    13 
    13 
    14 	defval "google.golang.org/protobuf/internal/encoding/defval"
    14 	"google.golang.org/protobuf/internal/encoding/defval"
    15 	fdesc "google.golang.org/protobuf/internal/filedesc"
    15 	"google.golang.org/protobuf/internal/filedesc"
    16 	"google.golang.org/protobuf/internal/strs"
    16 	"google.golang.org/protobuf/internal/strs"
    17 	pref "google.golang.org/protobuf/reflect/protoreflect"
    17 	"google.golang.org/protobuf/reflect/protoreflect"
    18 )
    18 )
    19 
    19 
    20 var byteType = reflect.TypeOf(byte(0))
    20 var byteType = reflect.TypeOf(byte(0))
    21 
    21 
    22 // Unmarshal decodes the tag into a prototype.Field.
    22 // Unmarshal decodes the tag into a prototype.Field.
    27 // represented by []T, but the Go type passed in is just T).
    27 // represented by []T, but the Go type passed in is just T).
    28 // A list of enum value descriptors must be provided for enum fields.
    28 // A list of enum value descriptors must be provided for enum fields.
    29 // This does not populate the Enum or Message (except for weak message).
    29 // This does not populate the Enum or Message (except for weak message).
    30 //
    30 //
    31 // This function is a best effort attempt; parsing errors are ignored.
    31 // This function is a best effort attempt; parsing errors are ignored.
    32 func Unmarshal(tag string, goType reflect.Type, evs pref.EnumValueDescriptors) pref.FieldDescriptor {
    32 func Unmarshal(tag string, goType reflect.Type, evs protoreflect.EnumValueDescriptors) protoreflect.FieldDescriptor {
    33 	f := new(fdesc.Field)
    33 	f := new(filedesc.Field)
    34 	f.L0.ParentFile = fdesc.SurrogateProto2
    34 	f.L0.ParentFile = filedesc.SurrogateProto2
    35 	for len(tag) > 0 {
    35 	for len(tag) > 0 {
    36 		i := strings.IndexByte(tag, ',')
    36 		i := strings.IndexByte(tag, ',')
    37 		if i < 0 {
    37 		if i < 0 {
    38 			i = len(tag)
    38 			i = len(tag)
    39 		}
    39 		}
    40 		switch s := tag[:i]; {
    40 		switch s := tag[:i]; {
    41 		case strings.HasPrefix(s, "name="):
    41 		case strings.HasPrefix(s, "name="):
    42 			f.L0.FullName = pref.FullName(s[len("name="):])
    42 			f.L0.FullName = protoreflect.FullName(s[len("name="):])
    43 		case strings.Trim(s, "0123456789") == "":
    43 		case strings.Trim(s, "0123456789") == "":
    44 			n, _ := strconv.ParseUint(s, 10, 32)
    44 			n, _ := strconv.ParseUint(s, 10, 32)
    45 			f.L1.Number = pref.FieldNumber(n)
    45 			f.L1.Number = protoreflect.FieldNumber(n)
    46 		case s == "opt":
    46 		case s == "opt":
    47 			f.L1.Cardinality = pref.Optional
    47 			f.L1.Cardinality = protoreflect.Optional
    48 		case s == "req":
    48 		case s == "req":
    49 			f.L1.Cardinality = pref.Required
    49 			f.L1.Cardinality = protoreflect.Required
    50 		case s == "rep":
    50 		case s == "rep":
    51 			f.L1.Cardinality = pref.Repeated
    51 			f.L1.Cardinality = protoreflect.Repeated
    52 		case s == "varint":
    52 		case s == "varint":
    53 			switch goType.Kind() {
    53 			switch goType.Kind() {
    54 			case reflect.Bool:
    54 			case reflect.Bool:
    55 				f.L1.Kind = pref.BoolKind
    55 				f.L1.Kind = protoreflect.BoolKind
    56 			case reflect.Int32:
    56 			case reflect.Int32:
    57 				f.L1.Kind = pref.Int32Kind
    57 				f.L1.Kind = protoreflect.Int32Kind
    58 			case reflect.Int64:
    58 			case reflect.Int64:
    59 				f.L1.Kind = pref.Int64Kind
    59 				f.L1.Kind = protoreflect.Int64Kind
    60 			case reflect.Uint32:
    60 			case reflect.Uint32:
    61 				f.L1.Kind = pref.Uint32Kind
    61 				f.L1.Kind = protoreflect.Uint32Kind
    62 			case reflect.Uint64:
    62 			case reflect.Uint64:
    63 				f.L1.Kind = pref.Uint64Kind
    63 				f.L1.Kind = protoreflect.Uint64Kind
    64 			}
    64 			}
    65 		case s == "zigzag32":
    65 		case s == "zigzag32":
    66 			if goType.Kind() == reflect.Int32 {
    66 			if goType.Kind() == reflect.Int32 {
    67 				f.L1.Kind = pref.Sint32Kind
    67 				f.L1.Kind = protoreflect.Sint32Kind
    68 			}
    68 			}
    69 		case s == "zigzag64":
    69 		case s == "zigzag64":
    70 			if goType.Kind() == reflect.Int64 {
    70 			if goType.Kind() == reflect.Int64 {
    71 				f.L1.Kind = pref.Sint64Kind
    71 				f.L1.Kind = protoreflect.Sint64Kind
    72 			}
    72 			}
    73 		case s == "fixed32":
    73 		case s == "fixed32":
    74 			switch goType.Kind() {
    74 			switch goType.Kind() {
    75 			case reflect.Int32:
    75 			case reflect.Int32:
    76 				f.L1.Kind = pref.Sfixed32Kind
    76 				f.L1.Kind = protoreflect.Sfixed32Kind
    77 			case reflect.Uint32:
    77 			case reflect.Uint32:
    78 				f.L1.Kind = pref.Fixed32Kind
    78 				f.L1.Kind = protoreflect.Fixed32Kind
    79 			case reflect.Float32:
    79 			case reflect.Float32:
    80 				f.L1.Kind = pref.FloatKind
    80 				f.L1.Kind = protoreflect.FloatKind
    81 			}
    81 			}
    82 		case s == "fixed64":
    82 		case s == "fixed64":
    83 			switch goType.Kind() {
    83 			switch goType.Kind() {
    84 			case reflect.Int64:
    84 			case reflect.Int64:
    85 				f.L1.Kind = pref.Sfixed64Kind
    85 				f.L1.Kind = protoreflect.Sfixed64Kind
    86 			case reflect.Uint64:
    86 			case reflect.Uint64:
    87 				f.L1.Kind = pref.Fixed64Kind
    87 				f.L1.Kind = protoreflect.Fixed64Kind
    88 			case reflect.Float64:
    88 			case reflect.Float64:
    89 				f.L1.Kind = pref.DoubleKind
    89 				f.L1.Kind = protoreflect.DoubleKind
    90 			}
    90 			}
    91 		case s == "bytes":
    91 		case s == "bytes":
    92 			switch {
    92 			switch {
    93 			case goType.Kind() == reflect.String:
    93 			case goType.Kind() == reflect.String:
    94 				f.L1.Kind = pref.StringKind
    94 				f.L1.Kind = protoreflect.StringKind
    95 			case goType.Kind() == reflect.Slice && goType.Elem() == byteType:
    95 			case goType.Kind() == reflect.Slice && goType.Elem() == byteType:
    96 				f.L1.Kind = pref.BytesKind
    96 				f.L1.Kind = protoreflect.BytesKind
    97 			default:
    97 			default:
    98 				f.L1.Kind = pref.MessageKind
    98 				f.L1.Kind = protoreflect.MessageKind
    99 			}
    99 			}
   100 		case s == "group":
   100 		case s == "group":
   101 			f.L1.Kind = pref.GroupKind
   101 			f.L1.Kind = protoreflect.GroupKind
   102 		case strings.HasPrefix(s, "enum="):
   102 		case strings.HasPrefix(s, "enum="):
   103 			f.L1.Kind = pref.EnumKind
   103 			f.L1.Kind = protoreflect.EnumKind
   104 		case strings.HasPrefix(s, "json="):
   104 		case strings.HasPrefix(s, "json="):
   105 			jsonName := s[len("json="):]
   105 			jsonName := s[len("json="):]
   106 			if jsonName != strs.JSONCamelCase(string(f.L0.FullName.Name())) {
   106 			if jsonName != strs.JSONCamelCase(string(f.L0.FullName.Name())) {
   107 				f.L1.StringName.InitJSON(jsonName)
   107 				f.L1.StringName.InitJSON(jsonName)
   108 			}
   108 			}
   109 		case s == "packed":
   109 		case s == "packed":
   110 			f.L1.HasPacked = true
   110 			f.L1.HasPacked = true
   111 			f.L1.IsPacked = true
   111 			f.L1.IsPacked = true
   112 		case strings.HasPrefix(s, "weak="):
   112 		case strings.HasPrefix(s, "weak="):
   113 			f.L1.IsWeak = true
   113 			f.L1.IsWeak = true
   114 			f.L1.Message = fdesc.PlaceholderMessage(pref.FullName(s[len("weak="):]))
   114 			f.L1.Message = filedesc.PlaceholderMessage(protoreflect.FullName(s[len("weak="):]))
   115 		case strings.HasPrefix(s, "def="):
   115 		case strings.HasPrefix(s, "def="):
   116 			// The default tag is special in that everything afterwards is the
   116 			// The default tag is special in that everything afterwards is the
   117 			// default regardless of the presence of commas.
   117 			// default regardless of the presence of commas.
   118 			s, i = tag[len("def="):], len(tag)
   118 			s, i = tag[len("def="):], len(tag)
   119 			v, ev, _ := defval.Unmarshal(s, f.L1.Kind, evs, defval.GoTag)
   119 			v, ev, _ := defval.Unmarshal(s, f.L1.Kind, evs, defval.GoTag)
   120 			f.L1.Default = fdesc.DefaultValue(v, ev)
   120 			f.L1.Default = filedesc.DefaultValue(v, ev)
   121 		case s == "proto3":
   121 		case s == "proto3":
   122 			f.L0.ParentFile = fdesc.SurrogateProto3
   122 			f.L0.ParentFile = filedesc.SurrogateProto3
   123 		}
   123 		}
   124 		tag = strings.TrimPrefix(tag[i:], ",")
   124 		tag = strings.TrimPrefix(tag[i:], ",")
   125 	}
   125 	}
   126 
   126 
   127 	// The generator uses the group message name instead of the field name.
   127 	// The generator uses the group message name instead of the field name.
   128 	// We obtain the real field name by lowercasing the group name.
   128 	// We obtain the real field name by lowercasing the group name.
   129 	if f.L1.Kind == pref.GroupKind {
   129 	if f.L1.Kind == protoreflect.GroupKind {
   130 		f.L0.FullName = pref.FullName(strings.ToLower(string(f.L0.FullName)))
   130 		f.L0.FullName = protoreflect.FullName(strings.ToLower(string(f.L0.FullName)))
   131 	}
   131 	}
   132 	return f
   132 	return f
   133 }
   133 }
   134 
   134 
   135 // Marshal encodes the protoreflect.FieldDescriptor as a tag.
   135 // Marshal encodes the protoreflect.FieldDescriptor as a tag.
   138 // Historically, the formulation of the enum "name" was the proto package
   138 // Historically, the formulation of the enum "name" was the proto package
   139 // dot-concatenated with the generated Go identifier for the enum type.
   139 // dot-concatenated with the generated Go identifier for the enum type.
   140 // Depending on the context on how Marshal is called, there are different ways
   140 // Depending on the context on how Marshal is called, there are different ways
   141 // through which that information is determined. As such it is the caller's
   141 // through which that information is determined. As such it is the caller's
   142 // responsibility to provide a function to obtain that information.
   142 // responsibility to provide a function to obtain that information.
   143 func Marshal(fd pref.FieldDescriptor, enumName string) string {
   143 func Marshal(fd protoreflect.FieldDescriptor, enumName string) string {
   144 	var tag []string
   144 	var tag []string
   145 	switch fd.Kind() {
   145 	switch fd.Kind() {
   146 	case pref.BoolKind, pref.EnumKind, pref.Int32Kind, pref.Uint32Kind, pref.Int64Kind, pref.Uint64Kind:
   146 	case protoreflect.BoolKind, protoreflect.EnumKind, protoreflect.Int32Kind, protoreflect.Uint32Kind, protoreflect.Int64Kind, protoreflect.Uint64Kind:
   147 		tag = append(tag, "varint")
   147 		tag = append(tag, "varint")
   148 	case pref.Sint32Kind:
   148 	case protoreflect.Sint32Kind:
   149 		tag = append(tag, "zigzag32")
   149 		tag = append(tag, "zigzag32")
   150 	case pref.Sint64Kind:
   150 	case protoreflect.Sint64Kind:
   151 		tag = append(tag, "zigzag64")
   151 		tag = append(tag, "zigzag64")
   152 	case pref.Sfixed32Kind, pref.Fixed32Kind, pref.FloatKind:
   152 	case protoreflect.Sfixed32Kind, protoreflect.Fixed32Kind, protoreflect.FloatKind:
   153 		tag = append(tag, "fixed32")
   153 		tag = append(tag, "fixed32")
   154 	case pref.Sfixed64Kind, pref.Fixed64Kind, pref.DoubleKind:
   154 	case protoreflect.Sfixed64Kind, protoreflect.Fixed64Kind, protoreflect.DoubleKind:
   155 		tag = append(tag, "fixed64")
   155 		tag = append(tag, "fixed64")
   156 	case pref.StringKind, pref.BytesKind, pref.MessageKind:
   156 	case protoreflect.StringKind, protoreflect.BytesKind, protoreflect.MessageKind:
   157 		tag = append(tag, "bytes")
   157 		tag = append(tag, "bytes")
   158 	case pref.GroupKind:
   158 	case protoreflect.GroupKind:
   159 		tag = append(tag, "group")
   159 		tag = append(tag, "group")
   160 	}
   160 	}
   161 	tag = append(tag, strconv.Itoa(int(fd.Number())))
   161 	tag = append(tag, strconv.Itoa(int(fd.Number())))
   162 	switch fd.Cardinality() {
   162 	switch fd.Cardinality() {
   163 	case pref.Optional:
   163 	case protoreflect.Optional:
   164 		tag = append(tag, "opt")
   164 		tag = append(tag, "opt")
   165 	case pref.Required:
   165 	case protoreflect.Required:
   166 		tag = append(tag, "req")
   166 		tag = append(tag, "req")
   167 	case pref.Repeated:
   167 	case protoreflect.Repeated:
   168 		tag = append(tag, "rep")
   168 		tag = append(tag, "rep")
   169 	}
   169 	}
   170 	if fd.IsPacked() {
   170 	if fd.IsPacked() {
   171 		tag = append(tag, "packed")
   171 		tag = append(tag, "packed")
   172 	}
   172 	}
   173 	name := string(fd.Name())
   173 	name := string(fd.Name())
   174 	if fd.Kind() == pref.GroupKind {
   174 	if fd.Kind() == protoreflect.GroupKind {
   175 		// The name of the FieldDescriptor for a group field is
   175 		// The name of the FieldDescriptor for a group field is
   176 		// lowercased. To find the original capitalization, we
   176 		// lowercased. To find the original capitalization, we
   177 		// look in the field's MessageType.
   177 		// look in the field's MessageType.
   178 		name = string(fd.Message().Name())
   178 		name = string(fd.Message().Name())
   179 	}
   179 	}
   187 		tag = append(tag, "weak="+string(fd.Message().FullName()))
   187 		tag = append(tag, "weak="+string(fd.Message().FullName()))
   188 	}
   188 	}
   189 	// The previous implementation does not tag extension fields as proto3,
   189 	// The previous implementation does not tag extension fields as proto3,
   190 	// even when the field is defined in a proto3 file. Match that behavior
   190 	// even when the field is defined in a proto3 file. Match that behavior
   191 	// for consistency.
   191 	// for consistency.
   192 	if fd.Syntax() == pref.Proto3 && !fd.IsExtension() {
   192 	if fd.Syntax() == protoreflect.Proto3 && !fd.IsExtension() {
   193 		tag = append(tag, "proto3")
   193 		tag = append(tag, "proto3")
   194 	}
   194 	}
   195 	if fd.Kind() == pref.EnumKind && enumName != "" {
   195 	if fd.Kind() == protoreflect.EnumKind && enumName != "" {
   196 		tag = append(tag, "enum="+enumName)
   196 		tag = append(tag, "enum="+enumName)
   197 	}
   197 	}
   198 	if fd.ContainingOneof() != nil {
   198 	if fd.ContainingOneof() != nil {
   199 		tag = append(tag, "oneof")
   199 		tag = append(tag, "oneof")
   200 	}
   200 	}