You are an expert in writing code in many different languages. Your goal is to perform code completion for the following code, keeping in mind the rest of the code and the file meta data.
    Metadata details:
    filename: tag.go
    path of file: ./repos/comply/vendor/google.golang.org/protobuf/internal/encoding/tag
    
    the code of the file until where you have to start completion: // Copyright 2018 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Package tag marshals and unmarshals the legacy struct tags as generated
// by historical versions of protoc-gen-go.
package tag

import (
	"reflect"
	"strconv"
	"strings"

	defval "google.golang.org/protobuf/internal/encoding/defval"
	fdesc "google.golang.org/protobuf/internal/filedesc"
	"google.golang.org/protobuf/internal/strs"
	pref "google.golang.org/protobuf/reflect/protoreflect"
)

var byteType = reflect.TypeOf(byte(0))

// Unmarshal decodes the tag into a prototype.Field.
//
// The goType is needed to determine the original protoreflect.Kind since the
// tag does not record sufficient information to determine that.
// The type is the underlying field type (e.g., a repeated field may be
// represented by []T, but the Go type passed in is just T).
// A list of enum value descriptors must be provided for enum fields.
// This does not populate the Enum or Message (except for weak message).
//
//
    
func Unmarshal(tag string, goType reflect.Type, evs pref.EnumValueDescriptors) pref.FieldDescriptor {
	f := new(fdesc.Field)
	f.L0.ParentFile = fdesc.SurrogateProto2
	for len(tag) > 0 {
		i := strings.IndexByte(tag, ',')
		if i < 0 {
			i = len(tag)
		}
		switch s := tag[:i]; {
		case strings.HasPrefix(s, "name="):
			f.L0.FullName = pref.FullName(s[len("name="):])
		case strings.Trim(s, "0123456789") == "":
			n, _ := strconv.ParseUint(s, 10, 32)
			f.L1.Number = pref.FieldNumber(n)
		case s == "opt":
			f.L1.Cardinality = pref.Optional
		case s == "req":
			f.L1.Cardinality = pref.Required
		case s == "rep":
			f.L1.Cardinality = pref.Repeated
		case s == "varint":
			switch goType.Kind() {
			case reflect.Bool:
				f.L1.Kind = pref.BoolKind
			case reflect.Int32:
				f.L1.Kind = pref.Int32Kind
			case reflect.Int64:
				f.L1.Kind = pref.Int64Kind
			case reflect.Uint32:
				f.L1.Kind = pref.Uint32Kind
			case reflect.Uint64:
				f.L1.Kind = pref.Uint64Kind
			}
		case s == "zigzag32":
			if goType.Kind() == reflect.Int32 {
				f.L1.Kind = pref.Sint32Kind
			}
		case s == "zigzag64":
			if goType.Kind() == reflect.Int64 {
				f.L1.Kind = pref.Sint64Kind
			}
		case s == "fixed32":
			switch goType.Kind() {
			case reflect.Int32:
				f.L1.Kind = pref.Sfixed32Kind
			case reflect.Uint32:
				f.L1.Kind = pref.Fixed32Kind
			case reflect.Float32:
				f.L1.Kind = pref.FloatKind
			}
		case s == "fixed64":
			switch goType.Kind() {
			case reflect.Int64:
				f.L1.Kind = pref.Sfixed64Kind
			case reflect.Uint64:
				f.L1.Kind = pref.Fixed64Kind
			case reflect.Float64:
				f.L1.Kind = pref.DoubleKind
			}
		case s == "bytes":
			switch {
			case goType.Kind() == reflect.String:
				f.L1.Kind = pref.StringKind
			case goType.Kind() == reflect.Slice && goType.Elem() == byteType:
				f.L1.Kind = pref.BytesKind
			default:
				f.L1.Kind = pref.MessageKind
			}
		case s == "group":
			f.L1.Kind = pref.GroupKind
		case strings.HasPrefix(s, "enum="):
			f.L1.Kind = pref.EnumKind
		case strings.HasPrefix(s, "json="):
			jsonName := s[len("json="):]
			if jsonName != strs.JSONCamelCase(string(f.L0.FullName.Name())) {
				f.L1.StringName.InitJSON(jsonName)
			}
		case s == "packed":
			f.L1.HasPacked = true
			f.L1.IsPacked = true
		case strings.HasPrefix(s, "weak="):
			f.L1.IsWeak = true
			f.L1.Message = fdesc.PlaceholderMessage(pref.FullName(s[len("weak="):]))
		case strings.HasPrefix(s, "def="):
			// The default tag is special in that everything afterwards is the
			// default regardless of the presence of commas.
			s, i = tag[len("def="):], len(tag)
			v, ev, _ := defval.Unmarshal(s, f.L1.Kind, evs, defval.GoTag)
			f.L1.Default = fdesc.DefaultValue(v, ev)
		case s == "proto3":
			f.L0.ParentFile = fdesc.SurrogateProto3
		}
		tag = strings.TrimPrefix(tag[i:], ",")
	}

	// The generator uses the group message name instead of the field name.
	// We obtain the real field name by lowercasing the group name.
	if f.L1.Kind == pref.GroupKind {
		f.L0.FullName = pref.FullName(strings.ToLower(string(f.L0.FullName)))
	}
	return f
}