func()

in proto/text_decode.go [368:471]


func (p *textParser) unmarshalSingularValue(v protoreflect.Value, fd protoreflect.FieldDescriptor) (protoreflect.Value, error) {
	tok := p.next()
	if tok.err != nil {
		return v, tok.err
	}
	if tok.value == "" {
		return v, p.errorf("unexpected EOF")
	}

	switch fd.Kind() {
	case protoreflect.BoolKind:
		switch tok.value {
		case "true", "1", "t", "True":
			return protoreflect.ValueOfBool(true), nil
		case "false", "0", "f", "False":
			return protoreflect.ValueOfBool(false), nil
		}
	case protoreflect.Int32Kind, protoreflect.Sint32Kind, protoreflect.Sfixed32Kind:
		if x, err := strconv.ParseInt(tok.value, 0, 32); err == nil {
			return protoreflect.ValueOfInt32(int32(x)), nil
		}

		// The C++ parser accepts large positive hex numbers that uses
		// two's complement arithmetic to represent negative numbers.
		// This feature is here for backwards compatibility with C++.
		if strings.HasPrefix(tok.value, "0x") {
			if x, err := strconv.ParseUint(tok.value, 0, 32); err == nil {
				return protoreflect.ValueOfInt32(int32(-(int64(^x) + 1))), nil
			}
		}
	case protoreflect.Int64Kind, protoreflect.Sint64Kind, protoreflect.Sfixed64Kind:
		if x, err := strconv.ParseInt(tok.value, 0, 64); err == nil {
			return protoreflect.ValueOfInt64(int64(x)), nil
		}

		// The C++ parser accepts large positive hex numbers that uses
		// two's complement arithmetic to represent negative numbers.
		// This feature is here for backwards compatibility with C++.
		if strings.HasPrefix(tok.value, "0x") {
			if x, err := strconv.ParseUint(tok.value, 0, 64); err == nil {
				return protoreflect.ValueOfInt64(int64(-(int64(^x) + 1))), nil
			}
		}
	case protoreflect.Uint32Kind, protoreflect.Fixed32Kind:
		if x, err := strconv.ParseUint(tok.value, 0, 32); err == nil {
			return protoreflect.ValueOfUint32(uint32(x)), nil
		}
	case protoreflect.Uint64Kind, protoreflect.Fixed64Kind:
		if x, err := strconv.ParseUint(tok.value, 0, 64); err == nil {
			return protoreflect.ValueOfUint64(uint64(x)), nil
		}
	case protoreflect.FloatKind:
		// Ignore 'f' for compatibility with output generated by C++,
		// but don't remove 'f' when the value is "-inf" or "inf".
		v := tok.value
		if strings.HasSuffix(v, "f") && v != "-inf" && v != "inf" {
			v = v[:len(v)-len("f")]
		}
		if x, err := strconv.ParseFloat(v, 32); err == nil {
			return protoreflect.ValueOfFloat32(float32(x)), nil
		}
	case protoreflect.DoubleKind:
		// Ignore 'f' for compatibility with output generated by C++,
		// but don't remove 'f' when the value is "-inf" or "inf".
		v := tok.value
		if strings.HasSuffix(v, "f") && v != "-inf" && v != "inf" {
			v = v[:len(v)-len("f")]
		}
		if x, err := strconv.ParseFloat(v, 64); err == nil {
			return protoreflect.ValueOfFloat64(float64(x)), nil
		}
	case protoreflect.StringKind:
		if isQuote(tok.value[0]) {
			return protoreflect.ValueOfString(tok.unquoted), nil
		}
	case protoreflect.BytesKind:
		if isQuote(tok.value[0]) {
			return protoreflect.ValueOfBytes([]byte(tok.unquoted)), nil
		}
	case protoreflect.EnumKind:
		if x, err := strconv.ParseInt(tok.value, 0, 32); err == nil {
			return protoreflect.ValueOfEnum(protoreflect.EnumNumber(x)), nil
		}
		vd := fd.Enum().Values().ByName(protoreflect.Name(tok.value))
		if vd != nil {
			return protoreflect.ValueOfEnum(vd.Number()), nil
		}
	case protoreflect.MessageKind, protoreflect.GroupKind:
		var terminator string
		switch tok.value {
		case "{":
			terminator = "}"
		case "<":
			terminator = ">"
		default:
			return v, p.errorf("expected '{' or '<', found %q", tok.value)
		}
		err := p.unmarshalMessage(v.Message(), terminator)
		return v, err
	default:
		panic(fmt.Sprintf("invalid kind %v", fd.Kind()))
	}
	return v, p.errorf("invalid %v: %v", fd.Kind(), tok.value)
}