func valueToProto(defaultAppID, name string, v reflect.Value, multiple bool) (p *pb.Property, errStr string) {
	var (
		pv          pb.PropertyValue
		unsupported bool
	)
	switch v.Kind() {
	case reflect.Invalid:
		// No-op.
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		pv.Int64Value = proto.Int64(v.Int())
	case reflect.Bool:
		pv.BooleanValue = proto.Bool(v.Bool())
	case reflect.String:
		pv.StringValue = proto.String(v.String())
	case reflect.Float32, reflect.Float64:
		pv.DoubleValue = proto.Float64(v.Float())
	case reflect.Ptr:
		if k, ok := v.Interface().(*Key); ok {
			if k != nil {
				pv.Referencevalue = keyToReferenceValue(defaultAppID, k)
			}
		} else {
			unsupported = true
		}
	case reflect.Struct:
		switch t := v.Interface().(type) {
		case time.Time:
			if t.Before(minTime) || t.After(maxTime) {
				return nil, "time value out of range"
			}
			pv.Int64Value = proto.Int64(toUnixMicro(t))
		case appengine.GeoPoint:
			if !t.Valid() {
				return nil, "invalid GeoPoint value"
			}
			// NOTE: Strangely, latitude maps to X, longitude to Y.
			pv.Pointvalue = &pb.PropertyValue_PointValue{X: &t.Lat, Y: &t.Lng}
		default:
			unsupported = true
		}
	case reflect.Slice:
		if b, ok := v.Interface().([]byte); ok {
			pv.StringValue = proto.String(string(b))
		} else {
			// nvToProto should already catch slice values.
			// If we get here, we have a slice of slice values.
			unsupported = true
		}
	default:
		unsupported = true
	}
	if unsupported {
		return nil, "unsupported datastore value type: " + v.Type().String()
	}
	p = &pb.Property{
		Name:     proto.String(name),
		Value:    &pv,
		Multiple: proto.Bool(multiple),
	}
	if v.IsValid() {
		switch v.Interface().(type) {
		case []byte:
			p.Meaning = pb.Property_BLOB.Enum()
		case ByteString:
			p.Meaning = pb.Property_BYTESTRING.Enum()
		case appengine.BlobKey:
			p.Meaning = pb.Property_BLOBKEY.Enum()
		case time.Time:
			p.Meaning = pb.Property_GD_WHEN.Enum()
		case appengine.GeoPoint:
			p.Meaning = pb.Property_GEORSS_POINT.Enum()
		}
	}
	return p, ""
}
func valueToProto(defaultAppID, name string, v reflect.Value, multiple bool) (p *pb.Property, errStr string) {
	var (
		pv          pb.PropertyValue
		unsupported bool
	)
	switch v.Kind() {
	case reflect.Invalid:
		
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		pv.Int64Value = proto.Int64(v.Int())
	case reflect.Bool:
		pv.BooleanValue = proto.Bool(v.Bool())
	case reflect.String:
		pv.StringValue = proto.String(v.String())
	case reflect.Float32, reflect.Float64:
		pv.DoubleValue = proto.Float64(v.Float())
	case reflect.Ptr:
		if k, ok := v.Interface().(*Key); ok {
			if k != nil {
				pv.Referencevalue = keyToReferenceValue(defaultAppID, k)
			}
		} else {
			unsupported = true
		}
	case reflect.Struct:
		switch t := v.Interface().(type) {
		case time.Time:
			if t.Before(minTime) || t.After(maxTime) {
				return nil, "time value out of range"
			}
			pv.Int64Value = proto.Int64(toUnixMicro(t))
		case appengine.GeoPoint:
			if !t.Valid() {
				return nil, "invalid GeoPoint value"
			}
			
			pv.Pointvalue = &pb.PropertyValue_PointValue{X: &t.Lat, Y: &t.Lng}
		default:
			unsupported = true
		}
	case reflect.Slice:
		if b, ok := v.Interface().([]byte); ok {
			pv.StringValue = proto.String(string(b))
		} else {
			
			
			unsupported = true
		}
	default:
		unsupported = true
	}
	if unsupported {
		return nil, "unsupported datastore value type: " + v.Type().String()
	}
	p = &pb.Property{
		Name:     proto.String(name),
		Value:    &pv,
		Multiple: proto.Bool(multiple),
	}
	if v.IsValid() {
		switch v.Interface().(type) {
		case []byte:
			p.Meaning = pb.Property_BLOB.Enum()
		case ByteString:
			p.Meaning = pb.Property_BYTESTRING.Enum()
		case appengine.BlobKey:
			p.Meaning = pb.Property_BLOBKEY.Enum()
		case time.Time:
			p.Meaning = pb.Property_GD_WHEN.Enum()
		case appengine.GeoPoint:
			p.Meaning = pb.Property_GEORSS_POINT.Enum()
		}
	}
	return p, ""
}
func valueToProto ( defaultAppID , name string , v reflect . Value , multiple bool ) ( p * pb . Property , errStr string ) { var ( pv pb . PropertyValue unsupported bool ) switch v . Kind ( ) { case reflect . Invalid : // No-op. case reflect . Int , reflect . Int8 , reflect . Int16 , reflect . Int32 , reflect . Int64 : pv . Int64Value = proto . Int64 ( v . Int ( ) ) case reflect . Bool : pv . BooleanValue = proto . Bool ( v . Bool ( ) ) case reflect . String : pv . StringValue = proto . String ( v . String ( ) ) case reflect . Float32 , reflect . Float64 : pv . DoubleValue = proto . Float64 ( v . Float ( ) ) case reflect . Ptr : if k , ok := v . Interface ( ) . ( * Key ) ; ok { if k != nil { pv . Referencevalue = keyToReferenceValue ( defaultAppID , k ) } } else { unsupported = true } case reflect . Struct : switch t := v . Interface ( ) . ( type ) { case time . Time : if t . Before ( minTime ) || t . After ( maxTime ) { return nil , " " } pv . Int64Value = proto . Int64 ( toUnixMicro ( t ) ) case appengine . GeoPoint : if ! t . Valid ( ) { return nil , " " } // NOTE: Strangely, latitude maps to X, longitude to Y. pv . Pointvalue = & pb . PropertyValue_PointValue { X : & t . Lat , Y : & t . Lng } default : unsupported = true } case reflect . Slice : if b , ok := v . Interface ( ) . ( [ ] byte ) ; ok { pv . StringValue = proto . String ( string ( b ) ) } else { // nvToProto should already catch slice values. // If we get here, we have a slice of slice values. unsupported = true } default : unsupported = true } if unsupported { return nil , " " + v . Type ( ) . String ( ) } p = & pb . Property { Name : proto . String ( name ) , Value : & pv , Multiple : proto . Bool ( multiple ) , } if v . IsValid ( ) { switch v . Interface ( ) . ( type ) { case [ ] byte : p . Meaning = pb . Property_BLOB . Enum ( ) case ByteString : p . Meaning = pb . Property_BYTESTRING . Enum ( ) case appengine . BlobKey : p . Meaning = pb . Property_BLOBKEY . Enum ( ) case time . Time : p . Meaning = pb . Property_GD_WHEN . Enum ( ) case appengine . GeoPoint : p . Meaning = pb . Property_GEORSS_POINT . Enum ( ) } } return p , " " }
// valueToProto converts a named value to a newly allocated Property.
// The returned error string is empty on success.
valueToProto converts a named value to a newly allocated Property . The returned error string is empty on success .