Example #1
0
func propertiesToProto(key *Key, props []Property) (*pb.Entity, error) {
	e := &pb.Entity{
		Key: keyToProto(key),
	}
	indexedProps := 0
	prevMultiple := make(map[string]*pb.Property)
	for _, p := range props {
		val, err := interfaceToProto(p.Value)
		if err != "" {
			return nil, fmt.Errorf("datastore: %s for a Property with Name %q", err, p.Name)
		}
		if !p.NoIndex {
			rVal := reflect.ValueOf(p.Value)
			if rVal.Kind() == reflect.Slice && rVal.Type().Elem().Kind() != reflect.Uint8 {
				indexedProps += rVal.Len()
			} else {
				indexedProps++
			}
		}
		if indexedProps > maxIndexedProperties {
			return nil, errors.New("datastore: too many indexed properties")
		}
		switch v := p.Value.(type) {
		case string:
		case []byte:
			if len(v) > 500 && !p.NoIndex {
				return nil, fmt.Errorf("datastore: cannot index a Property with Name %q", p.Name)
			}
		}
		val.Indexed = proto.Bool(!p.NoIndex)
		if p.Multiple {
			x, ok := prevMultiple[p.Name]
			if !ok {
				x = &pb.Property{
					Name:  proto.String(p.Name),
					Value: &pb.Value{},
				}
				prevMultiple[p.Name] = x
				e.Property = append(e.Property, x)
			}
			x.Value.ListValue = append(x.Value.ListValue, val)
		} else {
			e.Property = append(e.Property, &pb.Property{
				Name:  proto.String(p.Name),
				Value: val,
			})
		}
	}
	return e, nil
}
Example #2
0
func interfaceToProto(iv interface{}) (p *pb.Value, errStr string) {
	val := new(pb.Value)
	switch v := iv.(type) {
	case int:
		val.IntegerValue = proto.Int64(int64(v))
	case int32:
		val.IntegerValue = proto.Int64(int64(v))
	case int64:
		val.IntegerValue = proto.Int64(v)
	case bool:
		val.BooleanValue = proto.Bool(v)
	case string:
		val.StringValue = proto.String(v)
	case float32:
		val.DoubleValue = proto.Float64(float64(v))
	case float64:
		val.DoubleValue = proto.Float64(v)
	case *Key:
		if v != nil {
			val.KeyValue = keyToProto(v)
		}
	case time.Time:
		if v.Before(minTime) || v.After(maxTime) {
			return nil, fmt.Sprintf("time value out of range")
		}
		val.TimestampMicrosecondsValue = proto.Int64(toUnixMicro(v))
	case []byte:
		val.BlobValue = v
	default:
		if iv != nil {
			return nil, fmt.Sprintf("invalid Value type %t", iv)
		}
	}
	// TODO(jbd): Support ListValue and EntityValue.
	// TODO(jbd): Support types whose underlying type is one of the types above.
	return val, ""
}