github.com/Big-big-orange/protoreflect@v0.0.0-20240408141420-285cedfdf6a4/desc/wrap.go (about)

     1  package desc
     2  
     3  import (
     4  	"fmt"
     5  
     6  	"github.com/bufbuild/protocompile/protoutil"
     7  	"google.golang.org/protobuf/reflect/protoreflect"
     8  )
     9  
    10  // DescriptorWrapper wraps a protoreflect.Descriptor. All of the Descriptor
    11  // implementations in this package implement this interface. This can be
    12  // used to recover the underlying descriptor. Each descriptor type in this
    13  // package also provides a strongly-typed form of this method, such as the
    14  // following method for *FileDescriptor:
    15  //
    16  //	UnwrapFile() protoreflect.FileDescriptor
    17  type DescriptorWrapper interface {
    18  	Unwrap() protoreflect.Descriptor
    19  }
    20  
    21  // WrapDescriptor wraps the given descriptor, returning a desc.Descriptor
    22  // value that represents the same element.
    23  func WrapDescriptor(d protoreflect.Descriptor) (Descriptor, error) {
    24  	return wrapDescriptor(d, noopCache{})
    25  }
    26  
    27  func wrapDescriptor(d protoreflect.Descriptor, cache descriptorCache) (Descriptor, error) {
    28  	switch d := d.(type) {
    29  	case protoreflect.FileDescriptor:
    30  		return wrapFile(d, cache)
    31  	case protoreflect.MessageDescriptor:
    32  		return wrapMessage(d, cache)
    33  	case protoreflect.FieldDescriptor:
    34  		return wrapField(d, cache)
    35  	case protoreflect.OneofDescriptor:
    36  		return wrapOneOf(d, cache)
    37  	case protoreflect.EnumDescriptor:
    38  		return wrapEnum(d, cache)
    39  	case protoreflect.EnumValueDescriptor:
    40  		return wrapEnumValue(d, cache)
    41  	case protoreflect.ServiceDescriptor:
    42  		return wrapService(d, cache)
    43  	case protoreflect.MethodDescriptor:
    44  		return wrapMethod(d, cache)
    45  	default:
    46  		return nil, fmt.Errorf("unknown descriptor type: %T", d)
    47  	}
    48  }
    49  
    50  // WrapFiles wraps the given file descriptors, returning a slice of *desc.FileDescriptor
    51  // values that represent the same files.
    52  func WrapFiles(d []protoreflect.FileDescriptor) ([]*FileDescriptor, error) {
    53  	cache := mapCache{}
    54  	results := make([]*FileDescriptor, len(d))
    55  	for i := range d {
    56  		var err error
    57  		results[i], err = wrapFile(d[i], cache)
    58  		if err != nil {
    59  			return nil, err
    60  		}
    61  	}
    62  	return results, nil
    63  }
    64  
    65  // WrapFile wraps the given file descriptor, returning a *desc.FileDescriptor
    66  // value that represents the same file.
    67  func WrapFile(d protoreflect.FileDescriptor) (*FileDescriptor, error) {
    68  	return wrapFile(d, noopCache{})
    69  }
    70  
    71  func wrapFile(d protoreflect.FileDescriptor, cache descriptorCache) (*FileDescriptor, error) {
    72  	fdp := protoutil.ProtoFromFileDescriptor(d)
    73  	return convertFile(d, fdp, cache)
    74  }
    75  
    76  // WrapMessage wraps the given message descriptor, returning a *desc.MessageDescriptor
    77  // value that represents the same message.
    78  func WrapMessage(d protoreflect.MessageDescriptor) (*MessageDescriptor, error) {
    79  	return wrapMessage(d, noopCache{})
    80  }
    81  
    82  func wrapMessage(d protoreflect.MessageDescriptor, cache descriptorCache) (*MessageDescriptor, error) {
    83  	parent, err := wrapDescriptor(d.Parent(), cache)
    84  	if err != nil {
    85  		return nil, err
    86  	}
    87  	switch p := parent.(type) {
    88  	case *FileDescriptor:
    89  		return p.messages[d.Index()], nil
    90  	case *MessageDescriptor:
    91  		return p.nested[d.Index()], nil
    92  	default:
    93  		return nil, fmt.Errorf("message has unexpected parent type: %T", parent)
    94  	}
    95  }
    96  
    97  // WrapField wraps the given field descriptor, returning a *desc.FieldDescriptor
    98  // value that represents the same field.
    99  func WrapField(d protoreflect.FieldDescriptor) (*FieldDescriptor, error) {
   100  	return wrapField(d, noopCache{})
   101  }
   102  
   103  func wrapField(d protoreflect.FieldDescriptor, cache descriptorCache) (*FieldDescriptor, error) {
   104  	parent, err := wrapDescriptor(d.Parent(), cache)
   105  	if err != nil {
   106  		return nil, err
   107  	}
   108  	switch p := parent.(type) {
   109  	case *FileDescriptor:
   110  		return p.extensions[d.Index()], nil
   111  	case *MessageDescriptor:
   112  		if d.IsExtension() {
   113  			return p.extensions[d.Index()], nil
   114  		}
   115  		return p.fields[d.Index()], nil
   116  	default:
   117  		return nil, fmt.Errorf("field has unexpected parent type: %T", parent)
   118  	}
   119  }
   120  
   121  // WrapOneOf wraps the given oneof descriptor, returning a *desc.OneOfDescriptor
   122  // value that represents the same oneof.
   123  func WrapOneOf(d protoreflect.OneofDescriptor) (*OneOfDescriptor, error) {
   124  	return wrapOneOf(d, noopCache{})
   125  }
   126  
   127  func wrapOneOf(d protoreflect.OneofDescriptor, cache descriptorCache) (*OneOfDescriptor, error) {
   128  	parent, err := wrapDescriptor(d.Parent(), cache)
   129  	if err != nil {
   130  		return nil, err
   131  	}
   132  	if p, ok := parent.(*MessageDescriptor); ok {
   133  		return p.oneOfs[d.Index()], nil
   134  	}
   135  	return nil, fmt.Errorf("oneof has unexpected parent type: %T", parent)
   136  }
   137  
   138  // WrapEnum wraps the given enum descriptor, returning a *desc.EnumDescriptor
   139  // value that represents the same enum.
   140  func WrapEnum(d protoreflect.EnumDescriptor) (*EnumDescriptor, error) {
   141  	return wrapEnum(d, noopCache{})
   142  }
   143  
   144  func wrapEnum(d protoreflect.EnumDescriptor, cache descriptorCache) (*EnumDescriptor, error) {
   145  	parent, err := wrapDescriptor(d.Parent(), cache)
   146  	if err != nil {
   147  		return nil, err
   148  	}
   149  	switch p := parent.(type) {
   150  	case *FileDescriptor:
   151  		return p.enums[d.Index()], nil
   152  	case *MessageDescriptor:
   153  		return p.enums[d.Index()], nil
   154  	default:
   155  		return nil, fmt.Errorf("enum has unexpected parent type: %T", parent)
   156  	}
   157  }
   158  
   159  // WrapEnumValue wraps the given enum value descriptor, returning a *desc.EnumValueDescriptor
   160  // value that represents the same enum value.
   161  func WrapEnumValue(d protoreflect.EnumValueDescriptor) (*EnumValueDescriptor, error) {
   162  	return wrapEnumValue(d, noopCache{})
   163  }
   164  
   165  func wrapEnumValue(d protoreflect.EnumValueDescriptor, cache descriptorCache) (*EnumValueDescriptor, error) {
   166  	parent, err := wrapDescriptor(d.Parent(), cache)
   167  	if err != nil {
   168  		return nil, err
   169  	}
   170  	if p, ok := parent.(*EnumDescriptor); ok {
   171  		return p.values[d.Index()], nil
   172  	}
   173  	return nil, fmt.Errorf("enum value has unexpected parent type: %T", parent)
   174  }
   175  
   176  // WrapService wraps the given service descriptor, returning a *desc.ServiceDescriptor
   177  // value that represents the same service.
   178  func WrapService(d protoreflect.ServiceDescriptor) (*ServiceDescriptor, error) {
   179  	return wrapService(d, noopCache{})
   180  }
   181  
   182  func wrapService(d protoreflect.ServiceDescriptor, cache descriptorCache) (*ServiceDescriptor, error) {
   183  	parent, err := wrapDescriptor(d.Parent(), cache)
   184  	if err != nil {
   185  		return nil, err
   186  	}
   187  	if p, ok := parent.(*FileDescriptor); ok {
   188  		return p.services[d.Index()], nil
   189  	}
   190  	return nil, fmt.Errorf("service has unexpected parent type: %T", parent)
   191  }
   192  
   193  // WrapMethod wraps the given method descriptor, returning a *desc.MethodDescriptor
   194  // value that represents the same method.
   195  func WrapMethod(d protoreflect.MethodDescriptor) (*MethodDescriptor, error) {
   196  	return wrapMethod(d, noopCache{})
   197  }
   198  
   199  func wrapMethod(d protoreflect.MethodDescriptor, cache descriptorCache) (*MethodDescriptor, error) {
   200  	parent, err := wrapDescriptor(d.Parent(), cache)
   201  	if err != nil {
   202  		return nil, err
   203  	}
   204  	if p, ok := parent.(*ServiceDescriptor); ok {
   205  		return p.methods[d.Index()], nil
   206  	}
   207  	return nil, fmt.Errorf("method has unexpected parent type: %T", parent)
   208  }