diff options
Diffstat (limited to 'vendor/github.com/grpc-ecosystem/grpc-gateway/v2/runtime/fieldmask.go')
-rw-r--r-- | vendor/github.com/grpc-ecosystem/grpc-gateway/v2/runtime/fieldmask.go | 168 |
1 files changed, 0 insertions, 168 deletions
diff --git a/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/runtime/fieldmask.go b/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/runtime/fieldmask.go deleted file mode 100644 index 2fcd7af3c..000000000 --- a/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/runtime/fieldmask.go +++ /dev/null @@ -1,168 +0,0 @@ -package runtime - -import ( - "encoding/json" - "errors" - "fmt" - "io" - "sort" - - "google.golang.org/protobuf/proto" - "google.golang.org/protobuf/reflect/protoreflect" - field_mask "google.golang.org/protobuf/types/known/fieldmaskpb" -) - -func getFieldByName(fields protoreflect.FieldDescriptors, name string) protoreflect.FieldDescriptor { - fd := fields.ByName(protoreflect.Name(name)) - if fd != nil { - return fd - } - - return fields.ByJSONName(name) -} - -// FieldMaskFromRequestBody creates a FieldMask printing all complete paths from the JSON body. -func FieldMaskFromRequestBody(r io.Reader, msg proto.Message) (*field_mask.FieldMask, error) { - fm := &field_mask.FieldMask{} - var root interface{} - - if err := json.NewDecoder(r).Decode(&root); err != nil { - if errors.Is(err, io.EOF) { - return fm, nil - } - return nil, err - } - - queue := []fieldMaskPathItem{{node: root, msg: msg.ProtoReflect()}} - for len(queue) > 0 { - // dequeue an item - item := queue[0] - queue = queue[1:] - - m, ok := item.node.(map[string]interface{}) - switch { - case ok && len(m) > 0: - // if the item is an object, then enqueue all of its children - for k, v := range m { - if item.msg == nil { - return nil, errors.New("JSON structure did not match request type") - } - - fd := getFieldByName(item.msg.Descriptor().Fields(), k) - if fd == nil { - return nil, fmt.Errorf("could not find field %q in %q", k, item.msg.Descriptor().FullName()) - } - - if isDynamicProtoMessage(fd.Message()) { - for _, p := range buildPathsBlindly(string(fd.FullName().Name()), v) { - newPath := p - if item.path != "" { - newPath = item.path + "." + newPath - } - queue = append(queue, fieldMaskPathItem{path: newPath}) - } - continue - } - - if isProtobufAnyMessage(fd.Message()) && !fd.IsList() { - _, hasTypeField := v.(map[string]interface{})["@type"] - if hasTypeField { - queue = append(queue, fieldMaskPathItem{path: k}) - continue - } else { - return nil, fmt.Errorf("could not find field @type in %q in message %q", k, item.msg.Descriptor().FullName()) - } - - } - - child := fieldMaskPathItem{ - node: v, - } - if item.path == "" { - child.path = string(fd.FullName().Name()) - } else { - child.path = item.path + "." + string(fd.FullName().Name()) - } - - switch { - case fd.IsList(), fd.IsMap(): - // As per: https://github.com/protocolbuffers/protobuf/blob/master/src/google/protobuf/field_mask.proto#L85-L86 - // Do not recurse into repeated fields. The repeated field goes on the end of the path and we stop. - fm.Paths = append(fm.Paths, child.path) - case fd.Message() != nil: - child.msg = item.msg.Get(fd).Message() - fallthrough - default: - queue = append(queue, child) - } - } - case ok && len(m) == 0: - fallthrough - case len(item.path) > 0: - // otherwise, it's a leaf node so print its path - fm.Paths = append(fm.Paths, item.path) - } - } - - // Sort for deterministic output in the presence - // of repeated fields. - sort.Strings(fm.Paths) - - return fm, nil -} - -func isProtobufAnyMessage(md protoreflect.MessageDescriptor) bool { - return md != nil && (md.FullName() == "google.protobuf.Any") -} - -func isDynamicProtoMessage(md protoreflect.MessageDescriptor) bool { - return md != nil && (md.FullName() == "google.protobuf.Struct" || md.FullName() == "google.protobuf.Value") -} - -// buildPathsBlindly does not attempt to match proto field names to the -// json value keys. Instead it relies completely on the structure of -// the unmarshalled json contained within in. -// Returns a slice containing all subpaths with the root at the -// passed in name and json value. -func buildPathsBlindly(name string, in interface{}) []string { - m, ok := in.(map[string]interface{}) - if !ok { - return []string{name} - } - - var paths []string - queue := []fieldMaskPathItem{{path: name, node: m}} - for len(queue) > 0 { - cur := queue[0] - queue = queue[1:] - - m, ok := cur.node.(map[string]interface{}) - if !ok { - // This should never happen since we should always check that we only add - // nodes of type map[string]interface{} to the queue. - continue - } - for k, v := range m { - if mi, ok := v.(map[string]interface{}); ok { - queue = append(queue, fieldMaskPathItem{path: cur.path + "." + k, node: mi}) - } else { - // This is not a struct, so there are no more levels to descend. - curPath := cur.path + "." + k - paths = append(paths, curPath) - } - } - } - return paths -} - -// fieldMaskPathItem stores an in-progress deconstruction of a path for a fieldmask -type fieldMaskPathItem struct { - // the list of prior fields leading up to node connected by dots - path string - - // a generic decoded json object the current item to inspect for further path extraction - node interface{} - - // parent message - msg protoreflect.Message -} |