func (s *serverReflectionServer) allExtensionNumbersForType(st reflect.Type) ([]int32, error) { m, ok := reflect.Zero(reflect.PtrTo(st)).Interface().(proto.Message) if !ok { return nil, fmt.Errorf("failed to create message from type: %v", st) } exts := proto.RegisteredExtensions(m) out := make([]int32, 0, len(exts)) for id := range exts { out = append(out, id) } return out, nil }
func (s *serverReflectionServer) fileDescContainingExtension(st reflect.Type, ext int32) (*dpb.FileDescriptorProto, error) { m, ok := reflect.Zero(reflect.PtrTo(st)).Interface().(proto.Message) if !ok { return nil, fmt.Errorf("failed to create message from type: %v", st) } var extDesc *proto.ExtensionDesc for id, desc := range proto.RegisteredExtensions(m) { if id == ext { extDesc = desc break } } if extDesc == nil { return nil, fmt.Errorf("failed to find registered extension for extension number %v", ext) } extT := reflect.TypeOf(extDesc.ExtensionType).Elem() return s.fileDescForType(extT) }
// marshalObject writes a struct to the Writer. func (m *Marshaler) marshalObject(out *errWriter, v proto.Message, indent string) error { s := reflect.ValueOf(v).Elem() // Handle well-known types. type wkt interface { XXX_WellKnownType() string } if wkt, ok := v.(wkt); ok { switch wkt.XXX_WellKnownType() { case "DoubleValue", "FloatValue", "Int64Value", "UInt64Value", "Int32Value", "UInt32Value", "BoolValue", "StringValue", "BytesValue": // "Wrappers use the same representation in JSON // as the wrapped primitive type, ..." sprop := proto.GetProperties(s.Type()) return m.marshalValue(out, sprop.Prop[0], s.Field(0), indent) case "Duration": // "Generated output always contains 3, 6, or 9 fractional digits, // depending on required precision." s, ns := s.Field(0).Int(), s.Field(1).Int() d := time.Duration(s)*time.Second + time.Duration(ns)*time.Nanosecond x := fmt.Sprintf("%.9f", d.Seconds()) x = strings.TrimSuffix(x, "000") x = strings.TrimSuffix(x, "000") out.write(`"`) out.write(x) out.write(`s"`) return out.err case "Timestamp": // "RFC 3339, where generated output will always be Z-normalized // and uses 3, 6 or 9 fractional digits." s, ns := s.Field(0).Int(), s.Field(1).Int() t := time.Unix(s, ns).UTC() // time.RFC3339Nano isn't exactly right (we need to get 3/6/9 fractional digits). x := t.Format("2006-01-02T15:04:05.000000000") x = strings.TrimSuffix(x, "000") x = strings.TrimSuffix(x, "000") out.write(`"`) out.write(x) out.write(`Z"`) return out.err } } out.write("{") if m.Indent != "" { out.write("\n") } firstField := true for i := 0; i < s.NumField(); i++ { value := s.Field(i) valueField := s.Type().Field(i) if strings.HasPrefix(valueField.Name, "XXX_") { continue } // IsNil will panic on most value kinds. switch value.Kind() { case reflect.Chan, reflect.Func, reflect.Interface, reflect.Map, reflect.Ptr, reflect.Slice: if value.IsNil() { continue } } if !m.EmitDefaults { switch value.Kind() { case reflect.Bool: if !value.Bool() { continue } case reflect.Int32, reflect.Int64: if value.Int() == 0 { continue } case reflect.Uint32, reflect.Uint64: if value.Uint() == 0 { continue } case reflect.Float32, reflect.Float64: if value.Float() == 0 { continue } case reflect.String: if value.Len() == 0 { continue } } } // Oneof fields need special handling. if valueField.Tag.Get("protobuf_oneof") != "" { // value is an interface containing &T{real_value}. sv := value.Elem().Elem() // interface -> *T -> T value = sv.Field(0) valueField = sv.Type().Field(0) } prop := jsonProperties(valueField, m.OrigName) if !firstField { m.writeSep(out) } if err := m.marshalField(out, prop, value, indent); err != nil { return err } firstField = false } // Handle proto2 extensions. if ep, ok := v.(extendableProto); ok { extensions := proto.RegisteredExtensions(v) extensionMap := ep.ExtensionMap() // Sort extensions for stable output. ids := make([]int32, 0, len(extensionMap)) for id := range extensionMap { ids = append(ids, id) } sort.Sort(int32Slice(ids)) for _, id := range ids { desc := extensions[id] if desc == nil { // unknown extension continue } ext, extErr := proto.GetExtension(ep, desc) if extErr != nil { return extErr } value := reflect.ValueOf(ext) var prop proto.Properties prop.Parse(desc.Tag) prop.JSONName = fmt.Sprintf("[%s]", desc.Name) if !firstField { m.writeSep(out) } if err := m.marshalField(out, &prop, value, indent); err != nil { return err } firstField = false } } if m.Indent != "" { out.write("\n") out.write(indent) } out.write("}") return out.err }
// marshalObject writes a struct to the Writer. func (m *Marshaler) marshalObject(out *errWriter, v proto.Message, indent string) error { out.write("{") if m.Indent != "" { out.write("\n") } s := reflect.ValueOf(v).Elem() firstField := true for i := 0; i < s.NumField(); i++ { value := s.Field(i) valueField := s.Type().Field(i) if strings.HasPrefix(valueField.Name, "XXX_") { continue } // TODO: proto3 objects should have default values omitted. // IsNil will panic on most value kinds. switch value.Kind() { case reflect.Chan, reflect.Func, reflect.Interface, reflect.Map, reflect.Ptr, reflect.Slice: if value.IsNil() { continue } } // Oneof fields need special handling. if valueField.Tag.Get("protobuf_oneof") != "" { // value is an interface containing &T{real_value}. sv := value.Elem().Elem() // interface -> *T -> T value = sv.Field(0) valueField = sv.Type().Field(0) } prop := jsonProperties(valueField) if !firstField { m.writeSep(out) } if err := m.marshalField(out, prop, value, indent); err != nil { return err } firstField = false } // Handle proto2 extensions. if ep, ok := v.(extendableProto); ok { extensions := proto.RegisteredExtensions(v) extensionMap := ep.ExtensionMap() // Sort extensions for stable output. ids := make([]int32, 0, len(extensionMap)) for id := range extensionMap { ids = append(ids, id) } sort.Sort(int32Slice(ids)) for _, id := range ids { desc := extensions[id] if desc == nil { // unknown extension continue } ext, extErr := proto.GetExtension(ep, desc) if extErr != nil { return extErr } value := reflect.ValueOf(ext) var prop proto.Properties prop.Parse(desc.Tag) prop.OrigName = fmt.Sprintf("[%s]", desc.Name) if !firstField { m.writeSep(out) } if err := m.marshalField(out, &prop, value, indent); err != nil { return err } firstField = false } } if m.Indent != "" { out.write("\n") out.write(indent) } out.write("}") return out.err }