func (w *jsonWriter) marshalField(fd protoreflect.FieldDescriptor, v protoreflect.Value, indent string) error {
	if w.Indent != "" {
		w.write(indent)
		w.write(w.Indent)
	}
	w.write(`"`)
	switch {
	case fd.IsExtension():
		// For message set, use the fname of the message as the extension name.
		name := string(fd.FullName())
		if isMessageSet(fd.ContainingMessage()) {
			name = strings.TrimSuffix(name, ".message_set_extension")
		}
		w.write("[" + name + "]")
	case w.OrigName:
		name := string(fd.Name())
		if fd.Kind() == protoreflect.GroupKind {
			name = string(fd.Message().Name())
		}
		w.write(name)
	default:
		w.write(string(fd.JSONName()))
	}
	w.write(`":`)
	if w.Indent != "" {
		w.write(" ")
	}
	return w.marshalValue(fd, v, indent)
}
marshalField writes field description and value to the Writer.
package jsonpb
import (
	"encoding/json"
	"errors"
	"fmt"
	"io"
	"math"
	"reflect"
	"sort"
	"strconv"
	"strings"
	"time"
	"github.com/golang/protobuf/proto"
	"google.golang.org/protobuf/encoding/protojson"
	protoV2 "google.golang.org/protobuf/proto"
	"google.golang.org/protobuf/reflect/protoreflect"
	"google.golang.org/protobuf/reflect/protoregistry"
)
const wrapJSONMarshalV2 = false
type Marshaler struct {
	OrigName bool
	EnumsAsInts bool
	EmitDefaults bool
	Indent string
	AnyResolver AnyResolver
}
type JSONPBMarshaler interface {
	MarshalJSONPB(*Marshaler) ([]byte, error)
}
func (jm *Marshaler) Marshal(w io.Writer, m proto.Message) error {
	b, err := jm.marshal(m)
	if len(b) > 0 {
		if _, err := w.Write(b); err != nil {
			return err
		}
	}
	return err
}
func (jm *Marshaler) MarshalToString(m proto.Message) (string, error) {
	b, err := jm.marshal(m)
	if err != nil {
		return "", err
	}
	return string(b), nil
}
func (jm *Marshaler) marshal(m proto.Message) ([]byte, error) {
	v := reflect.ValueOf(m)
	if m == nil || (v.Kind() == reflect.Ptr && v.IsNil()) {
		return nil, errors.New("Marshal called with nil")
	}
	if jsm, ok := m.(JSONPBMarshaler); ok {
		return jsm.MarshalJSONPB(jm)
	}
	if wrapJSONMarshalV2 {
		opts := protojson.MarshalOptions{
			UseProtoNames:   jm.OrigName,
			UseEnumNumbers:  jm.EnumsAsInts,
			EmitUnpopulated: jm.EmitDefaults,
			Indent:          jm.Indent,
		}
		if jm.AnyResolver != nil {
			opts.Resolver = anyResolver{jm.AnyResolver}
		}
		return opts.Marshal(proto.MessageReflect(m).Interface())
	} else {
		m2 := proto.MessageReflect(m)
		if err := protoV2.CheckInitialized(m2.Interface()); err != nil {
			return nil, err
		}
		w := jsonWriter{Marshaler: jm}
		err := w.marshalMessage(m2, "", "")
		return w.buf, err
	}
}
type jsonWriter struct {
	*Marshaler
	buf []byte
}
func (w *jsonWriter) write(s string) {
	w.buf = append(w.buf, s...)
}
func (w *jsonWriter) marshalMessage(m protoreflect.Message, indent, typeURL string) error {
	if jsm, ok := proto.MessageV1(m.Interface()).(JSONPBMarshaler); ok {
		b, err := jsm.MarshalJSONPB(w.Marshaler)
		if err != nil {
			return err
		}
		if typeURL != "" {
			var js map[string]*json.RawMessage
			if err = json.Unmarshal(b, &js); err != nil {
				return fmt.Errorf("type %T produced invalid JSON: %v", m.Interface(), err)
			}
			turl, err := json.Marshal(typeURL)
			if err != nil {
				return fmt.Errorf("failed to marshal type URL %q to JSON: %v", typeURL, err)
			}
			js["@type"] = (*json.RawMessage)(&turl)
			if b, err = json.Marshal(js); err != nil {
				return err
			}
		}
		w.write(string(b))
		return nil
	}
	md := m.Descriptor()
	fds := md.Fields()
	const secondInNanos = int64(time.Second / time.Nanosecond)
	switch wellKnownType(md.FullName()) {
	case "Any":
		return w.marshalAny(m, indent)
	case "BoolValue", "BytesValue", "StringValue",
		"Int32Value", "UInt32Value", "FloatValue",
		"Int64Value", "UInt64Value", "DoubleValue":
		fd := fds.ByNumber(1)
		return w.marshalValue(fd, m.Get(fd), indent)
	case "Duration":
		const maxSecondsInDuration = 315576000000
		s := m.Get(fds.ByNumber(1)).Int()
		ns := m.Get(fds.ByNumber(2)).Int()
		if s < -maxSecondsInDuration || s > maxSecondsInDuration {
			return fmt.Errorf("seconds out of range %v", s)
		}
		if ns <= -secondInNanos || ns >= secondInNanos {
			return fmt.Errorf("ns out of range (%v, %v)", -secondInNanos, secondInNanos)
		}
		if (s > 0 && ns < 0) || (s < 0 && ns > 0) {
			return errors.New("signs of seconds and nanos do not match")
		}
		var sign string
		if s < 0 || ns < 0 {
			sign, s, ns = "-", -1*s, -1*ns
		}
		x := fmt.Sprintf("%s%d.%09d", sign, s, ns)
		x = strings.TrimSuffix(x, "000")
		x = strings.TrimSuffix(x, "000")
		x = strings.TrimSuffix(x, ".000")
		w.write(fmt.Sprintf(`"%vs"`, x))
		return nil
	case "Timestamp":
		s := m.Get(fds.ByNumber(1)).Int()
		ns := m.Get(fds.ByNumber(2)).Int()
		if ns < 0 || ns >= secondInNanos {
			return fmt.Errorf("ns out of range [0, %v)", secondInNanos)
		}
		t := time.Unix(s, ns).UTC()
		x := t.Format("2006-01-02T15:04:05.000000000")
		x = strings.TrimSuffix(x, "000")
		x = strings.TrimSuffix(x, "000")
		x = strings.TrimSuffix(x, ".000")
		w.write(fmt.Sprintf(`"%vZ"`, x))
		return nil
	case "Value":
		od := md.Oneofs().Get(0)
		fd := m.WhichOneof(od)
		if fd == nil {
			return errors.New("nil Value")
		}
		return w.marshalValue(fd, m.Get(fd), indent)
	case "Struct", "ListValue":
		fd := fds.ByNumber(1)
		return w.marshalValue(fd, m.Get(fd), indent)
	}
	w.write("{")
	if w.Indent != "" {
		w.write("\n")
	}
	firstField := true
	if typeURL != "" {
		if err := w.marshalTypeURL(indent, typeURL); err != nil {
			return err
		}
		firstField = false
	}
	for i := 0; i < fds.Len(); {
		fd := fds.Get(i)
		if od := fd.ContainingOneof(); od != nil {
			fd = m.WhichOneof(od)
			i += od.Fields().Len()
			if fd == nil {
				continue
			}
		} else {
			i++
		}
		v := m.Get(fd)
		if !m.Has(fd) {
			if !w.EmitDefaults || fd.ContainingOneof() != nil {
				continue
			}
			if fd.Cardinality() != protoreflect.Repeated && (fd.Message() != nil || fd.Syntax() == protoreflect.Proto2) {
				v = protoreflect.Value{}  
			}
		}
		if !firstField {
			w.writeComma()
		}
		if err := w.marshalField(fd, v, indent); err != nil {
			return err
		}
		firstField = false
	}
	if md.ExtensionRanges().Len() > 0 {
		type ext struct {
			desc protoreflect.FieldDescriptor
			val  protoreflect.Value
		}
		var exts []ext
		m.Range(func(fd protoreflect.FieldDescriptor, v protoreflect.Value) bool {
			if fd.IsExtension() {
				exts = append(exts, ext{fd, v})
			}
			return true
		})
		sort.Slice(exts, func(i, j int) bool {
			return exts[i].desc.Number() < exts[j].desc.Number()
		})
		for _, ext := range exts {
			if !firstField {
				w.writeComma()
			}
			if err := w.marshalField(ext.desc, ext.val, indent); err != nil {
				return err
			}
			firstField = false
		}
	}
	if w.Indent != "" {
		w.write("\n")
		w.write(indent)
	}
	w.write("}")
	return nil
}
func (w *jsonWriter) writeComma() {
	if w.Indent != "" {
		w.write(",\n")
	} else {
		w.write(",")
	}
}
func (w *jsonWriter) marshalAny(m protoreflect.Message, indent string) error {
	md := m.Descriptor()
	typeURL := m.Get(md.Fields().ByNumber(1)).String()
	rawVal := m.Get(md.Fields().ByNumber(2)).Bytes()
	var m2 protoreflect.Message
	if w.AnyResolver != nil {
		mi, err := w.AnyResolver.Resolve(typeURL)
		if err != nil {
			return err
		}
		m2 = proto.MessageReflect(mi)
	} else {
		mt, err := protoregistry.GlobalTypes.FindMessageByURL(typeURL)
		if err != nil {
			return err
		}
		m2 = mt.New()
	}
	if err := protoV2.Unmarshal(rawVal, m2.Interface()); err != nil {
		return err
	}
	if wellKnownType(m2.Descriptor().FullName()) == "" {
		return w.marshalMessage(m2, indent, typeURL)
	}
	w.write("{")
	if w.Indent != "" {
		w.write("\n")
	}
	if err := w.marshalTypeURL(indent, typeURL); err != nil {
		return err
	}
	w.writeComma()
	if w.Indent != "" {
		w.write(indent)
		w.write(w.Indent)
		w.write(`"value": `)
	} else {
		w.write(`"value":`)
	}
	if err := w.marshalMessage(m2, indent+w.Indent, ""); err != nil {
		return err
	}
	if w.Indent != "" {
		w.write("\n")
		w.write(indent)
	}
	w.write("}")
	return nil
}
func (w *jsonWriter) marshalTypeURL(indent, typeURL string) error {
	if w.Indent != "" {
		w.write(indent)
		w.write(w.Indent)
	}
	w.write(`"@type":`)
	if w.Indent != "" {
		w.write(" ")
	}
	b, err := json.Marshal(typeURL)
	if err != nil {
		return err
	}
	w.write(string(b))
	return nil
}