package packngo import ( "bytes" "fmt" "io" "reflect" ) var timestampType = reflect.TypeOf(Timestamp{}) // Stringify creates a string representation of the provided message func Stringify(message interface{}) string { var buf bytes.Buffer v := reflect.ValueOf(message) stringifyValue(&buf, v) return buf.String() } // String allocates a new string value to store v and returns a pointer to it func String(v string) *string { p := new(string) *p = v return p } // Int allocates a new int32 value to store v and returns a pointer to it, but unlike Int32 its argument value is an int. func Int(v int) *int { p := new(int) *p = v return p } // Bool allocates a new bool value to store v and returns a pointer to it. func Bool(v bool) *bool { p := new(bool) *p = v return p } // StreamToString converts a reader to a string func StreamToString(stream io.Reader) string { buf := new(bytes.Buffer) buf.ReadFrom(stream) return buf.String() } // stringifyValue was graciously cargoculted from the goprotubuf library func stringifyValue(w io.Writer, val reflect.Value) { if val.Kind() == reflect.Ptr && val.IsNil() { w.Write([]byte("")) return } v := reflect.Indirect(val) switch v.Kind() { case reflect.String: fmt.Fprintf(w, `"%s"`, v) case reflect.Slice: w.Write([]byte{'['}) for i := 0; i < v.Len(); i++ { if i > 0 { w.Write([]byte{' '}) } stringifyValue(w, v.Index(i)) } w.Write([]byte{']'}) return case reflect.Struct: if v.Type().Name() != "" { w.Write([]byte(v.Type().String())) } // special handling of Timestamp values if v.Type() == timestampType { fmt.Fprintf(w, "{%s}", v.Interface()) return } w.Write([]byte{'{'}) var sep bool for i := 0; i < v.NumField(); i++ { fv := v.Field(i) if fv.Kind() == reflect.Ptr && fv.IsNil() { continue } if fv.Kind() == reflect.Slice && fv.IsNil() { continue } if sep { w.Write([]byte(", ")) } else { sep = true } w.Write([]byte(v.Type().Field(i).Name)) w.Write([]byte{':'}) stringifyValue(w, fv) } w.Write([]byte{'}'}) default: if v.CanInterface() { fmt.Fprint(w, v.Interface()) } } }