in lib/proto/proto.go [435:545]
func toProto(fdesc protoreflect.FieldDescriptor, v starlark.Value) (protoreflect.Value, error) {
switch fdesc.Kind() {
case protoreflect.BoolKind:
// To avoid mistakes, we require v be exactly a bool.
if v, ok := v.(starlark.Bool); ok {
return protoreflect.ValueOfBool(bool(v)), nil
}
case protoreflect.Fixed32Kind,
protoreflect.Uint32Kind:
// uint32
if i, ok := v.(starlark.Int); ok {
if u, ok := i.Uint64(); ok && uint64(uint32(u)) == u {
return protoreflect.ValueOfUint32(uint32(u)), nil
}
return noValue, fmt.Errorf("invalid %s: %v", typeString(fdesc), i)
}
case protoreflect.Int32Kind,
protoreflect.Sfixed32Kind,
protoreflect.Sint32Kind:
// int32
if i, ok := v.(starlark.Int); ok {
if i, ok := i.Int64(); ok && int64(int32(i)) == i {
return protoreflect.ValueOfInt32(int32(i)), nil
}
return noValue, fmt.Errorf("invalid %s: %v", typeString(fdesc), i)
}
case protoreflect.Uint64Kind,
protoreflect.Fixed64Kind:
// uint64
if i, ok := v.(starlark.Int); ok {
if u, ok := i.Uint64(); ok {
return protoreflect.ValueOfUint64(u), nil
}
return noValue, fmt.Errorf("invalid %s: %v", typeString(fdesc), i)
}
case protoreflect.Int64Kind,
protoreflect.Sfixed64Kind,
protoreflect.Sint64Kind:
// int64
if i, ok := v.(starlark.Int); ok {
if i, ok := i.Int64(); ok {
return protoreflect.ValueOfInt64(i), nil
}
return noValue, fmt.Errorf("invalid %s: %v", typeString(fdesc), i)
}
case protoreflect.StringKind:
if s, ok := starlark.AsString(v); ok {
return protoreflect.ValueOfString(s), nil
} else if b, ok := v.(starlark.Bytes); ok {
// TODO(adonovan): allow bytes for string? Not friendly to a Java port.
return protoreflect.ValueOfBytes([]byte(b)), nil
}
case protoreflect.BytesKind:
if s, ok := starlark.AsString(v); ok {
// TODO(adonovan): don't allow string for bytes: it's hostile to a Java port.
// Instead provide b"..." literals in the core
// and a bytes(str) conversion.
return protoreflect.ValueOfBytes([]byte(s)), nil
} else if b, ok := v.(starlark.Bytes); ok {
return protoreflect.ValueOfBytes([]byte(b)), nil
}
case protoreflect.DoubleKind:
switch v := v.(type) {
case starlark.Float:
return protoreflect.ValueOfFloat64(float64(v)), nil
case starlark.Int:
return protoreflect.ValueOfFloat64(float64(v.Float())), nil
}
case protoreflect.FloatKind:
switch v := v.(type) {
case starlark.Float:
return protoreflect.ValueOfFloat32(float32(v)), nil
case starlark.Int:
return protoreflect.ValueOfFloat32(float32(v.Float())), nil
}
case protoreflect.GroupKind,
protoreflect.MessageKind:
// Keep consistent with MessageDescriptor.CallInternal!
desc := fdesc.Message()
switch v := v.(type) {
case *Message:
if desc != v.desc() {
return noValue, fmt.Errorf("got %s, want %s", v.desc().FullName(), desc.FullName())
}
return protoreflect.ValueOfMessage(v.msg), nil // alias it directly
case *starlark.Dict:
dest := newMessage(desc)
err := setFields(dest, v.Items())
return protoreflect.ValueOfMessage(dest), err
}
case protoreflect.EnumKind:
enumval, err := enumValueOf(fdesc.Enum(), v)
if err != nil {
return noValue, err
}
return protoreflect.ValueOfEnum(enumval.Number()), nil
}
return noValue, fmt.Errorf("got %s, want %s", v.Type(), typeString(fdesc))
}