mirror of
				https://gitea.com/Lydanne/buildx.git
				synced 2025-11-04 10:03:42 +08:00 
			
		
		
		
	
		
			
				
	
	
		
			242 lines
		
	
	
		
			6.8 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			242 lines
		
	
	
		
			6.8 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
// Copyright 2020 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 protopath
 | 
						|
 | 
						|
import (
 | 
						|
	"fmt"
 | 
						|
	"strconv"
 | 
						|
	"strings"
 | 
						|
 | 
						|
	"google.golang.org/protobuf/internal/encoding/text"
 | 
						|
	"google.golang.org/protobuf/reflect/protoreflect"
 | 
						|
)
 | 
						|
 | 
						|
// StepKind identifies the kind of step operation.
 | 
						|
// Each kind of step corresponds with some protobuf reflection operation.
 | 
						|
type StepKind int
 | 
						|
 | 
						|
const (
 | 
						|
	invalidStep StepKind = iota
 | 
						|
	// RootStep identifies a step as the Root step operation.
 | 
						|
	RootStep
 | 
						|
	// FieldAccessStep identifies a step as the FieldAccess step operation.
 | 
						|
	FieldAccessStep
 | 
						|
	// UnknownAccessStep identifies a step as the UnknownAccess step operation.
 | 
						|
	UnknownAccessStep
 | 
						|
	// ListIndexStep identifies a step as the ListIndex step operation.
 | 
						|
	ListIndexStep
 | 
						|
	// MapIndexStep identifies a step as the MapIndex step operation.
 | 
						|
	MapIndexStep
 | 
						|
	// AnyExpandStep identifies a step as the AnyExpand step operation.
 | 
						|
	AnyExpandStep
 | 
						|
)
 | 
						|
 | 
						|
func (k StepKind) String() string {
 | 
						|
	switch k {
 | 
						|
	case invalidStep:
 | 
						|
		return "<invalid>"
 | 
						|
	case RootStep:
 | 
						|
		return "Root"
 | 
						|
	case FieldAccessStep:
 | 
						|
		return "FieldAccess"
 | 
						|
	case UnknownAccessStep:
 | 
						|
		return "UnknownAccess"
 | 
						|
	case ListIndexStep:
 | 
						|
		return "ListIndex"
 | 
						|
	case MapIndexStep:
 | 
						|
		return "MapIndex"
 | 
						|
	case AnyExpandStep:
 | 
						|
		return "AnyExpand"
 | 
						|
	default:
 | 
						|
		return fmt.Sprintf("<unknown:%d>", k)
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
// Step is a union where only one step operation may be specified at a time.
 | 
						|
// The different kinds of steps are specified by the constants defined for
 | 
						|
// the StepKind type.
 | 
						|
type Step struct {
 | 
						|
	kind StepKind
 | 
						|
	desc protoreflect.Descriptor
 | 
						|
	key  protoreflect.Value
 | 
						|
}
 | 
						|
 | 
						|
// Root indicates the root message that a path is relative to.
 | 
						|
// It should always (and only ever) be the first step in a path.
 | 
						|
func Root(md protoreflect.MessageDescriptor) Step {
 | 
						|
	if md == nil {
 | 
						|
		panic("nil message descriptor")
 | 
						|
	}
 | 
						|
	return Step{kind: RootStep, desc: md}
 | 
						|
}
 | 
						|
 | 
						|
// FieldAccess describes access of a field within a message.
 | 
						|
// Extension field accesses are also represented using a FieldAccess and
 | 
						|
// must be provided with a protoreflect.FieldDescriptor
 | 
						|
//
 | 
						|
// Within the context of Values,
 | 
						|
// the type of the previous step value is always a message, and
 | 
						|
// the type of the current step value is determined by the field descriptor.
 | 
						|
func FieldAccess(fd protoreflect.FieldDescriptor) Step {
 | 
						|
	if fd == nil {
 | 
						|
		panic("nil field descriptor")
 | 
						|
	} else if _, ok := fd.(protoreflect.ExtensionTypeDescriptor); !ok && fd.IsExtension() {
 | 
						|
		panic(fmt.Sprintf("extension field %q must implement protoreflect.ExtensionTypeDescriptor", fd.FullName()))
 | 
						|
	}
 | 
						|
	return Step{kind: FieldAccessStep, desc: fd}
 | 
						|
}
 | 
						|
 | 
						|
// UnknownAccess describes access to the unknown fields within a message.
 | 
						|
//
 | 
						|
// Within the context of Values,
 | 
						|
// the type of the previous step value is always a message, and
 | 
						|
// the type of the current step value is always a bytes type.
 | 
						|
func UnknownAccess() Step {
 | 
						|
	return Step{kind: UnknownAccessStep}
 | 
						|
}
 | 
						|
 | 
						|
// ListIndex describes index of an element within a list.
 | 
						|
//
 | 
						|
// Within the context of Values,
 | 
						|
// the type of the previous, previous step value is always a message,
 | 
						|
// the type of the previous step value is always a list, and
 | 
						|
// the type of the current step value is determined by the field descriptor.
 | 
						|
func ListIndex(i int) Step {
 | 
						|
	if i < 0 {
 | 
						|
		panic(fmt.Sprintf("invalid list index: %v", i))
 | 
						|
	}
 | 
						|
	return Step{kind: ListIndexStep, key: protoreflect.ValueOfInt64(int64(i))}
 | 
						|
}
 | 
						|
 | 
						|
// MapIndex describes index of an entry within a map.
 | 
						|
// The key type is determined by field descriptor that the map belongs to.
 | 
						|
//
 | 
						|
// Within the context of Values,
 | 
						|
// the type of the previous previous step value is always a message,
 | 
						|
// the type of the previous step value is always a map, and
 | 
						|
// the type of the current step value is determined by the field descriptor.
 | 
						|
func MapIndex(k protoreflect.MapKey) Step {
 | 
						|
	if !k.IsValid() {
 | 
						|
		panic("invalid map index")
 | 
						|
	}
 | 
						|
	return Step{kind: MapIndexStep, key: k.Value()}
 | 
						|
}
 | 
						|
 | 
						|
// AnyExpand describes expansion of a google.protobuf.Any message into
 | 
						|
// a structured representation of the underlying message.
 | 
						|
//
 | 
						|
// Within the context of Values,
 | 
						|
// the type of the previous step value is always a google.protobuf.Any message, and
 | 
						|
// the type of the current step value is always a message.
 | 
						|
func AnyExpand(md protoreflect.MessageDescriptor) Step {
 | 
						|
	if md == nil {
 | 
						|
		panic("nil message descriptor")
 | 
						|
	}
 | 
						|
	return Step{kind: AnyExpandStep, desc: md}
 | 
						|
}
 | 
						|
 | 
						|
// MessageDescriptor returns the message descriptor for Root or AnyExpand steps,
 | 
						|
// otherwise it returns nil.
 | 
						|
func (s Step) MessageDescriptor() protoreflect.MessageDescriptor {
 | 
						|
	switch s.kind {
 | 
						|
	case RootStep, AnyExpandStep:
 | 
						|
		return s.desc.(protoreflect.MessageDescriptor)
 | 
						|
	default:
 | 
						|
		return nil
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
// FieldDescriptor returns the field descriptor for FieldAccess steps,
 | 
						|
// otherwise it returns nil.
 | 
						|
func (s Step) FieldDescriptor() protoreflect.FieldDescriptor {
 | 
						|
	switch s.kind {
 | 
						|
	case FieldAccessStep:
 | 
						|
		return s.desc.(protoreflect.FieldDescriptor)
 | 
						|
	default:
 | 
						|
		return nil
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
// ListIndex returns the list index for ListIndex steps,
 | 
						|
// otherwise it returns 0.
 | 
						|
func (s Step) ListIndex() int {
 | 
						|
	switch s.kind {
 | 
						|
	case ListIndexStep:
 | 
						|
		return int(s.key.Int())
 | 
						|
	default:
 | 
						|
		return 0
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
// MapIndex returns the map key for MapIndex steps,
 | 
						|
// otherwise it returns an invalid map key.
 | 
						|
func (s Step) MapIndex() protoreflect.MapKey {
 | 
						|
	switch s.kind {
 | 
						|
	case MapIndexStep:
 | 
						|
		return s.key.MapKey()
 | 
						|
	default:
 | 
						|
		return protoreflect.MapKey{}
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
// Kind reports which kind of step this is.
 | 
						|
func (s Step) Kind() StepKind {
 | 
						|
	return s.kind
 | 
						|
}
 | 
						|
 | 
						|
func (s Step) String() string {
 | 
						|
	return string(s.appendString(nil))
 | 
						|
}
 | 
						|
 | 
						|
func (s Step) appendString(b []byte) []byte {
 | 
						|
	switch s.kind {
 | 
						|
	case RootStep:
 | 
						|
		b = append(b, '(')
 | 
						|
		b = append(b, s.desc.FullName()...)
 | 
						|
		b = append(b, ')')
 | 
						|
	case FieldAccessStep:
 | 
						|
		b = append(b, '.')
 | 
						|
		if fd := s.desc.(protoreflect.FieldDescriptor); fd.IsExtension() {
 | 
						|
			b = append(b, '(')
 | 
						|
			b = append(b, strings.Trim(fd.TextName(), "[]")...)
 | 
						|
			b = append(b, ')')
 | 
						|
		} else {
 | 
						|
			b = append(b, fd.TextName()...)
 | 
						|
		}
 | 
						|
	case UnknownAccessStep:
 | 
						|
		b = append(b, '.')
 | 
						|
		b = append(b, '?')
 | 
						|
	case ListIndexStep:
 | 
						|
		b = append(b, '[')
 | 
						|
		b = strconv.AppendInt(b, s.key.Int(), 10)
 | 
						|
		b = append(b, ']')
 | 
						|
	case MapIndexStep:
 | 
						|
		b = append(b, '[')
 | 
						|
		switch k := s.key.Interface().(type) {
 | 
						|
		case bool:
 | 
						|
			b = strconv.AppendBool(b, bool(k)) // e.g., "true" or "false"
 | 
						|
		case int32:
 | 
						|
			b = strconv.AppendInt(b, int64(k), 10) // e.g., "-32"
 | 
						|
		case int64:
 | 
						|
			b = strconv.AppendInt(b, int64(k), 10) // e.g., "-64"
 | 
						|
		case uint32:
 | 
						|
			b = strconv.AppendUint(b, uint64(k), 10) // e.g., "32"
 | 
						|
		case uint64:
 | 
						|
			b = strconv.AppendUint(b, uint64(k), 10) // e.g., "64"
 | 
						|
		case string:
 | 
						|
			b = text.AppendString(b, k) // e.g., `"hello, world"`
 | 
						|
		}
 | 
						|
		b = append(b, ']')
 | 
						|
	case AnyExpandStep:
 | 
						|
		b = append(b, '.')
 | 
						|
		b = append(b, '(')
 | 
						|
		b = append(b, s.desc.FullName()...)
 | 
						|
		b = append(b, ')')
 | 
						|
	default:
 | 
						|
		b = append(b, "<invalid>"...)
 | 
						|
	}
 | 
						|
	return b
 | 
						|
}
 |