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 descfmt provides functionality to format descriptors.
package descfmt

import (
	
	
	
	
	

	
	
	pref 
)

type list interface {
	Len() int
	pragma.DoNotImplement
}

func ( fmt.State,  rune,  list) {
	io.WriteString(, formatListOpt(, true,  == 'v' && (.Flag('+') || .Flag('#'))))
}
func ( list, ,  bool) string {
	,  := "[", "]"
	if  {
		var  string
		switch .(type) {
		case pref.Names:
			 = "Names"
		case pref.FieldNumbers:
			 = "FieldNumbers"
		case pref.FieldRanges:
			 = "FieldRanges"
		case pref.EnumRanges:
			 = "EnumRanges"
		case pref.FileImports:
			 = "FileImports"
		case pref.Descriptor:
			 = reflect.ValueOf().MethodByName("Get").Type().Out(0).Name() + "s"
		}
		,  = +"{", "}"
	}

	var  []string
	switch vs := .(type) {
	case pref.Names:
		for  := 0;  < .Len(); ++ {
			 = append(, fmt.Sprint(.Get()))
		}
		return  + joinStrings(, false) + 
	case pref.FieldNumbers:
		for  := 0;  < .Len(); ++ {
			 = append(, fmt.Sprint(.Get()))
		}
		return  + joinStrings(, false) + 
	case pref.FieldRanges:
		for  := 0;  < .Len(); ++ {
			 := .Get()
			if [0]+1 == [1] {
				 = append(, fmt.Sprintf("%d", [0]))
			} else {
				 = append(, fmt.Sprintf("%d:%d", [0], [1])) // enum ranges are end exclusive
			}
		}
		return  + joinStrings(, false) + 
	case pref.EnumRanges:
		for  := 0;  < .Len(); ++ {
			 := .Get()
			if [0] == [1] {
				 = append(, fmt.Sprintf("%d", [0]))
			} else {
				 = append(, fmt.Sprintf("%d:%d", [0], int64([1])+1)) // enum ranges are end inclusive
			}
		}
		return  + joinStrings(, false) + 
	case pref.FileImports:
		for  := 0;  < .Len(); ++ {
			var  records
			.Append(reflect.ValueOf(.Get()), "Path", "Package", "IsPublic", "IsWeak")
			 = append(, "{"+.Join()+"}")
		}
		return  + joinStrings(, ) + 
	default:
		,  := .(pref.EnumValueDescriptors)
		for  := 0;  < .Len(); ++ {
			 := reflect.ValueOf().MethodByName("Get")
			 := .Call([]reflect.Value{reflect.ValueOf()})[0].Interface()
			 = append(, formatDescOpt(.(pref.Descriptor), false,  && !))
		}
		return  + joinStrings(,  && ) + 
	}
}
descriptorAccessors is a list of accessors to print for each descriptor. Do not print all accessors since some contain redundant information, while others are pointers that we do not want to follow since the descriptor is actually a cyclic graph. Using a list allows us to print the accessors in a sensible order.
var descriptorAccessors = map[reflect.Type][]string{
	reflect.TypeOf((*pref.FileDescriptor)(nil)).Elem():      {"Path", "Package", "Imports", "Messages", "Enums", "Extensions", "Services"},
	reflect.TypeOf((*pref.MessageDescriptor)(nil)).Elem():   {"IsMapEntry", "Fields", "Oneofs", "ReservedNames", "ReservedRanges", "RequiredNumbers", "ExtensionRanges", "Messages", "Enums", "Extensions"},
	reflect.TypeOf((*pref.FieldDescriptor)(nil)).Elem():     {"Number", "Cardinality", "Kind", "HasJSONName", "JSONName", "HasPresence", "IsExtension", "IsPacked", "IsWeak", "IsList", "IsMap", "MapKey", "MapValue", "HasDefault", "Default", "ContainingOneof", "ContainingMessage", "Message", "Enum"},
	reflect.TypeOf((*pref.OneofDescriptor)(nil)).Elem():     {"Fields"}, // not directly used; must keep in sync with formatDescOpt
	reflect.TypeOf((*pref.EnumDescriptor)(nil)).Elem():      {"Values", "ReservedNames", "ReservedRanges"},
	reflect.TypeOf((*pref.EnumValueDescriptor)(nil)).Elem(): {"Number"},
	reflect.TypeOf((*pref.ServiceDescriptor)(nil)).Elem():   {"Methods"},
	reflect.TypeOf((*pref.MethodDescriptor)(nil)).Elem():    {"Input", "Output", "IsStreamingClient", "IsStreamingServer"},
}

func ( fmt.State,  rune,  pref.Descriptor) {
	io.WriteString(, formatDescOpt(, true,  == 'v' && (.Flag('+') || .Flag('#'))))
}
func ( pref.Descriptor, ,  bool) string {
	 := reflect.ValueOf()
	 := .MethodByName("ProtoType").Type().In(0)

	,  := "{", "}"
	if  {
		 = .Name() + "{"
	}

	,  := .(pref.FileDescriptor)
	 := records{allowMulti: }
	if .IsPlaceholder() {
		if  {
			.Append(, "Path", "Package", "IsPlaceholder")
		} else {
			.Append(, "FullName", "IsPlaceholder")
		}
	} else {
		switch {
		case :
			.Append(, "Syntax")
		case :
			.Append(, "Syntax", "FullName")
		default:
			.Append(, "Name")
		}
		switch t := .(type) {
		case pref.FieldDescriptor:
			for ,  := range descriptorAccessors[] {
				switch  {
				case "MapKey":
					if  := .MapKey();  != nil {
						.recs = append(.recs, [2]string{"MapKey", .Kind().String()})
					}
				case "MapValue":
					if  := .MapValue();  != nil {
						switch .Kind() {
						case pref.EnumKind:
							.recs = append(.recs, [2]string{"MapValue", string(.Enum().FullName())})
						case pref.MessageKind, pref.GroupKind:
							.recs = append(.recs, [2]string{"MapValue", string(.Message().FullName())})
						default:
							.recs = append(.recs, [2]string{"MapValue", .Kind().String()})
						}
					}
				case "ContainingOneof":
					if  := .ContainingOneof();  != nil {
						.recs = append(.recs, [2]string{"Oneof", string(.Name())})
					}
				case "ContainingMessage":
					if .IsExtension() {
						.recs = append(.recs, [2]string{"Extendee", string(.ContainingMessage().FullName())})
					}
				case "Message":
					if !.IsMap() {
						.Append(, )
					}
				default:
					.Append(, )
				}
			}
		case pref.OneofDescriptor:
			var  []string
			 := .Fields()
			for  := 0;  < .Len(); ++ {
				 = append(, string(.Get().Name()))
			}
			if len() > 0 {
				.recs = append(.recs, [2]string{"Fields", "[" + joinStrings(, false) + "]"})
			}
		default:
			.Append(, descriptorAccessors[]...)
		}
		if .MethodByName("GoType").IsValid() {
			.Append(, "GoType")
		}
	}
	return  + .Join() + 
}

type records struct {
	recs       [][2]string
	allowMulti bool
}

func ( *records) ( reflect.Value,  ...string) {
	for ,  := range  {
		var  reflect.Value
		if  := .MethodByName(); .IsValid() {
			 = .Call(nil)[0]
		}
		if .Kind() == reflect.Struct && !.IsValid() {
			 = .FieldByName()
		}
		if !.IsValid() {
			panic(fmt.Sprintf("unknown accessor: %v.%s", .Type(), ))
		}
		if ,  := .Interface().(pref.Value);  {
			 = .MethodByName("Interface").Call(nil)[0]
			if !.IsNil() {
				 = .Elem()
			}
		}
Ignore zero values.
		var  bool
		switch .Kind() {
		case reflect.Interface, reflect.Slice:
			 = .IsNil()
		case reflect.Bool:
			 = .Bool() == false
		case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
			 = .Int() == 0
		case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
			 = .Uint() == 0
		case reflect.String:
			 = .String() == ""
		}
		if ,  := .Interface().(list);  {
			 = .Len() == 0
		}
		if  {
			continue
		}
Format the value.
		var  string
		 := .Interface()
		switch v := .(type) {
		case list:
			 = formatListOpt(, false, .allowMulti)
		case pref.FieldDescriptor, pref.OneofDescriptor, pref.EnumValueDescriptor, pref.MethodDescriptor:
			 = string(.(pref.Descriptor).Name())
		case pref.Descriptor:
			 = string(.FullName())
		case string:
			 = strconv.Quote()
		case []byte:
			 = fmt.Sprintf("%q", )
		default:
			 = fmt.Sprint()
		}
		.recs = append(.recs, [2]string{, })
	}
}

func ( *records) () string {
	var  []string
In single line mode, simply join all records with commas.
	if !.allowMulti {
		for ,  := range .recs {
			 = append(, [0]+formatColon(0)+[1])
		}
		return joinStrings(, false)
	}
In allowMulti line mode, align single line records for more readable output.
	var  int
	 := func( int) {
		for ,  := range .recs[len():] {
			 = append(, [0]+formatColon(-len([0]))+[1])
		}
		 = 0
	}
	for ,  := range .recs {
		if  := strings.Contains([1], "\n");  {
			()
			 = append(, [0]+formatColon(0)+strings.Join(strings.Split([1], "\n"), "\n\t"))
		} else if  < len([0]) {
			 = len([0])
		}
	}
	(len(.recs))
	return joinStrings(, true)
}

Deliberately introduce instability into the debug output to discourage users from performing string comparisons. This provides us flexibility to change the output in the future.
	if detrand.Bool() {
		return ":" + strings.Repeat(" ", 1+) // use non-breaking spaces (U+00a0)
	} else {
		return ":" + strings.Repeat(" ", 1+) // use regular spaces (U+0020)
	}
}

func ( []string,  bool) string {
	if len() == 0 {
		return ""
	}
	if  {
		return "\n\t" + strings.Join(, "\n\t") + "\n"
	}
	return strings.Join(, ", ")