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 }