github.com/jhump/protoreflect@v1.16.0/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, mapCache{}) 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, mapCache{}) 69 } 70 71 func wrapFile(d protoreflect.FileDescriptor, cache descriptorCache) (*FileDescriptor, error) { 72 if res := cache.get(d); res != nil { 73 return res.(*FileDescriptor), nil 74 } 75 fdp := protoutil.ProtoFromFileDescriptor(d) 76 return convertFile(d, fdp, cache) 77 } 78 79 // WrapMessage wraps the given message descriptor, returning a *desc.MessageDescriptor 80 // value that represents the same message. 81 func WrapMessage(d protoreflect.MessageDescriptor) (*MessageDescriptor, error) { 82 return wrapMessage(d, mapCache{}) 83 } 84 85 func wrapMessage(d protoreflect.MessageDescriptor, cache descriptorCache) (*MessageDescriptor, error) { 86 parent, err := wrapDescriptor(d.Parent(), cache) 87 if err != nil { 88 return nil, err 89 } 90 switch p := parent.(type) { 91 case *FileDescriptor: 92 return p.messages[d.Index()], nil 93 case *MessageDescriptor: 94 return p.nested[d.Index()], nil 95 default: 96 return nil, fmt.Errorf("message has unexpected parent type: %T", parent) 97 } 98 } 99 100 // WrapField wraps the given field descriptor, returning a *desc.FieldDescriptor 101 // value that represents the same field. 102 func WrapField(d protoreflect.FieldDescriptor) (*FieldDescriptor, error) { 103 return wrapField(d, mapCache{}) 104 } 105 106 func wrapField(d protoreflect.FieldDescriptor, cache descriptorCache) (*FieldDescriptor, error) { 107 parent, err := wrapDescriptor(d.Parent(), cache) 108 if err != nil { 109 return nil, err 110 } 111 switch p := parent.(type) { 112 case *FileDescriptor: 113 return p.extensions[d.Index()], nil 114 case *MessageDescriptor: 115 if d.IsExtension() { 116 return p.extensions[d.Index()], nil 117 } 118 return p.fields[d.Index()], nil 119 default: 120 return nil, fmt.Errorf("field has unexpected parent type: %T", parent) 121 } 122 } 123 124 // WrapOneOf wraps the given oneof descriptor, returning a *desc.OneOfDescriptor 125 // value that represents the same oneof. 126 func WrapOneOf(d protoreflect.OneofDescriptor) (*OneOfDescriptor, error) { 127 return wrapOneOf(d, mapCache{}) 128 } 129 130 func wrapOneOf(d protoreflect.OneofDescriptor, cache descriptorCache) (*OneOfDescriptor, error) { 131 parent, err := wrapDescriptor(d.Parent(), cache) 132 if err != nil { 133 return nil, err 134 } 135 if p, ok := parent.(*MessageDescriptor); ok { 136 return p.oneOfs[d.Index()], nil 137 } 138 return nil, fmt.Errorf("oneof has unexpected parent type: %T", parent) 139 } 140 141 // WrapEnum wraps the given enum descriptor, returning a *desc.EnumDescriptor 142 // value that represents the same enum. 143 func WrapEnum(d protoreflect.EnumDescriptor) (*EnumDescriptor, error) { 144 return wrapEnum(d, mapCache{}) 145 } 146 147 func wrapEnum(d protoreflect.EnumDescriptor, cache descriptorCache) (*EnumDescriptor, error) { 148 parent, err := wrapDescriptor(d.Parent(), cache) 149 if err != nil { 150 return nil, err 151 } 152 switch p := parent.(type) { 153 case *FileDescriptor: 154 return p.enums[d.Index()], nil 155 case *MessageDescriptor: 156 return p.enums[d.Index()], nil 157 default: 158 return nil, fmt.Errorf("enum has unexpected parent type: %T", parent) 159 } 160 } 161 162 // WrapEnumValue wraps the given enum value descriptor, returning a *desc.EnumValueDescriptor 163 // value that represents the same enum value. 164 func WrapEnumValue(d protoreflect.EnumValueDescriptor) (*EnumValueDescriptor, error) { 165 return wrapEnumValue(d, mapCache{}) 166 } 167 168 func wrapEnumValue(d protoreflect.EnumValueDescriptor, cache descriptorCache) (*EnumValueDescriptor, error) { 169 parent, err := wrapDescriptor(d.Parent(), cache) 170 if err != nil { 171 return nil, err 172 } 173 if p, ok := parent.(*EnumDescriptor); ok { 174 return p.values[d.Index()], nil 175 } 176 return nil, fmt.Errorf("enum value has unexpected parent type: %T", parent) 177 } 178 179 // WrapService wraps the given service descriptor, returning a *desc.ServiceDescriptor 180 // value that represents the same service. 181 func WrapService(d protoreflect.ServiceDescriptor) (*ServiceDescriptor, error) { 182 return wrapService(d, mapCache{}) 183 } 184 185 func wrapService(d protoreflect.ServiceDescriptor, cache descriptorCache) (*ServiceDescriptor, error) { 186 parent, err := wrapDescriptor(d.Parent(), cache) 187 if err != nil { 188 return nil, err 189 } 190 if p, ok := parent.(*FileDescriptor); ok { 191 return p.services[d.Index()], nil 192 } 193 return nil, fmt.Errorf("service has unexpected parent type: %T", parent) 194 } 195 196 // WrapMethod wraps the given method descriptor, returning a *desc.MethodDescriptor 197 // value that represents the same method. 198 func WrapMethod(d protoreflect.MethodDescriptor) (*MethodDescriptor, error) { 199 return wrapMethod(d, mapCache{}) 200 } 201 202 func wrapMethod(d protoreflect.MethodDescriptor, cache descriptorCache) (*MethodDescriptor, error) { 203 parent, err := wrapDescriptor(d.Parent(), cache) 204 if err != nil { 205 return nil, err 206 } 207 if p, ok := parent.(*ServiceDescriptor); ok { 208 return p.methods[d.Index()], nil 209 } 210 return nil, fmt.Errorf("method has unexpected parent type: %T", parent) 211 }