package proto
import (
protoV2
)
const wrapTextUnmarshalV2 = false
type ParseError struct {
Message string
Line, Offset int
}
func ( *ParseError) () string {
if wrapTextUnmarshalV2 {
return .Message
}
if .Line == 1 {
return fmt.Sprintf("line 1.%d: %v", .Offset, .Message)
}
return fmt.Sprintf("line %d: %v", .Line, .Message)
}
func ( string, Message) error {
if , := .(encoding.TextUnmarshaler); {
return .UnmarshalText([]byte())
}
.Reset()
:= MessageV2()
if wrapTextUnmarshalV2 {
:= prototext.UnmarshalOptions{
AllowPartial: true,
}.Unmarshal([]byte(), )
if != nil {
return &ParseError{Message: .Error()}
}
return checkRequiredNotSet()
} else {
if := newTextParser().unmarshalMessage(.ProtoReflect(), ""); != nil {
return
}
return checkRequiredNotSet()
}
}
type textParser struct {
s string
done bool
backed bool
offset, line int
cur token
}
type token struct {
value string
err *ParseError
line int
offset int
unquoted string
}
func ( string) *textParser {
:= new(textParser)
.s =
.line = 1
.cur.line = 1
return
}
func ( *textParser) ( protoreflect.Message, string) ( error) {
:= .Descriptor()
:= .Fields()
:= make(map[protoreflect.FieldNumber]bool)
for {
:= .next()
if .err != nil {
return .err
}
if .value == {
break
}
if .value == "[" {
if := .unmarshalExtensionOrAny(, ); != nil {
return
}
continue
}
:= protoreflect.Name(.value)
:= .ByName()
switch {
case == nil:
:= .ByName(protoreflect.Name(strings.ToLower(string())))
if != nil && .Kind() == protoreflect.GroupKind && .Message().Name() == {
=
}
case .Kind() == protoreflect.GroupKind && .Message().Name() != :
= nil
case .IsWeak() && .Message().IsPlaceholder():
= nil
}
if == nil {
:= string(.FullName())
if , := .Interface().(Message); {
:= reflect.TypeOf()
if .Kind() == reflect.Ptr {
= .Elem().String()
}
}
return .errorf("unknown field name %q in %v", , )
}
if := .ContainingOneof(); != nil && .WhichOneof() != nil {
return .errorf("field '%s' would overwrite already parsed oneof '%s'", , .Name())
}
if .Cardinality() != protoreflect.Repeated && [.Number()] {
return .errorf("non-repeated field %q was repeated", .Name())
}
[.Number()] = true
if := .checkForColon(); != nil {
return
}
:= .Get()
if !.Has() && (.IsList() || .IsMap() || .Message() != nil) {
= .Mutable()
}
if , = .unmarshalValue(, ); != nil {
return
}
.Set(, )
if := .consumeOptionalSeparator(); != nil {
return
}
}
return nil
}
func ( *textParser) ( protoreflect.Message, map[protoreflect.FieldNumber]bool) error {
, := .consumeExtensionOrAnyName()
if != nil {
return
}
if := strings.LastIndex(, "/"); >= 0 {
:= .next()
if .err != nil {
return .err
}
if .value == ":" {
= .next()
if .err != nil {
return .err
}
}
var string
switch .value {
case "<":
= ">"
case "{":
= "}"
default:
return .errorf("expected '{' or '<', found %q", .value)
}
, := protoregistry.GlobalTypes.FindMessageByURL()
if != nil {
return .errorf("unrecognized message %q in google.protobuf.Any", [+len("/"):])
}
:= .New()
if := .unmarshalMessage(, ); != nil {
return
}
, := protoV2.Marshal(.Interface())
if != nil {
return .errorf("failed to marshal message of type %q: %v", [+len("/"):], )
}
:= .Descriptor().Fields().ByName("type_url")
:= .Descriptor().Fields().ByName("value")
if [.Number()] {
return .errorf("Any message unpacked multiple times, or %q already set", .Name())
}
if [.Number()] {
return .errorf("Any message unpacked multiple times, or %q already set", .Name())
}
.Set(, protoreflect.ValueOfString())
.Set(, protoreflect.ValueOfBytes())
[.Number()] = true
[.Number()] = true
return nil
}
:= protoreflect.FullName()
, := protoregistry.GlobalTypes.FindExtensionByName()
if == nil && isMessageSet(.Descriptor()) {
, _ = protoregistry.GlobalTypes.FindExtensionByName(.Append("message_set_extension"))
}
if == nil {
return .errorf("unrecognized extension %q", )
}
:= .TypeDescriptor()
if .ContainingMessage().FullName() != .Descriptor().FullName() {
return .errorf("extension field %q does not extend message %q", , .Descriptor().FullName())
}
if := .checkForColon(); != nil {
return
}
:= .Get()
if !.Has() && (.IsList() || .IsMap() || .Message() != nil) {
= .Mutable()
}
, = .unmarshalValue(, )
if != nil {
return
}
.Set(, )
return .consumeOptionalSeparator()
}
func ( *textParser) ( protoreflect.Value, protoreflect.FieldDescriptor) (protoreflect.Value, error) {
:= .next()
if .err != nil {
return , .err
}
if .value == "" {
return , .errorf("unexpected EOF")
}
switch {
case .IsList():
:= .List()
var error
if .value == "[" {
for {
:= .NewElement()
, = .unmarshalSingularValue(, )
if != nil {
return ,
}
.Append()
:= .next()
if .err != nil {
return , .err
}
if .value == "]" {
break
}
if .value != "," {
return , .errorf("Expected ']' or ',' found %q", .value)
}
}
return , nil
}
.back()
:= .NewElement()
, = .unmarshalSingularValue(, )
if != nil {
return ,
}
.Append()
return , nil
case .IsMap():
var string
switch .value {
case "<":
= ">"
case "{":
= "}"
default:
return , .errorf("expected '{' or '<', found %q", .value)
}
:= .MapKey()
:= .MapValue()
:= .Map()
:= .Default()
:= .NewValue()
for {
:= .next()
if .err != nil {
return , .err
}
if .value == {
break
}
var error
switch .value {
case "key":
if := .consumeToken(":"); != nil {
return ,
}
if , = .unmarshalSingularValue(, ); != nil {
return ,
}
if := .consumeOptionalSeparator(); != nil {
return ,
}
case "value":
if := .checkForColon(); != nil {
return ,
}
if , = .unmarshalSingularValue(, ); != nil {
return ,
}
if := .consumeOptionalSeparator(); != nil {
return ,
}
default:
.back()
return , .errorf(`expected "key", "value", or %q, found %q`, , .value)
}
}
.Set(.MapKey(), )
return , nil
default:
.back()
return .unmarshalSingularValue(, )
}
}
func ( *textParser) ( protoreflect.Value, protoreflect.FieldDescriptor) (protoreflect.Value, error) {
:= .next()
if .err != nil {
return , .err
}
if .value == "" {
return , .errorf("unexpected EOF")
}
switch .Kind() {
case protoreflect.BoolKind:
switch .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 , := strconv.ParseInt(.value, 0, 32); == nil {
return protoreflect.ValueOfInt32(int32()), nil
}
if strings.HasPrefix(.value, "0x") {
if , := strconv.ParseUint(.value, 0, 32); == nil {
return protoreflect.ValueOfInt32(int32(-(int64(^) + 1))), nil
}
}
case protoreflect.Int64Kind, protoreflect.Sint64Kind, protoreflect.Sfixed64Kind:
if , := strconv.ParseInt(.value, 0, 64); == nil {
return protoreflect.ValueOfInt64(int64()), nil
}
if strings.HasPrefix(.value, "0x") {
if , := strconv.ParseUint(.value, 0, 64); == nil {
return protoreflect.ValueOfInt64(int64(-(int64(^) + 1))), nil
}
}
case protoreflect.Uint32Kind, protoreflect.Fixed32Kind:
if , := strconv.ParseUint(.value, 0, 32); == nil {
return protoreflect.ValueOfUint32(uint32()), nil
}
case protoreflect.Uint64Kind, protoreflect.Fixed64Kind:
if , := strconv.ParseUint(.value, 0, 64); == nil {
return protoreflect.ValueOfUint64(uint64()), nil
}
case protoreflect.FloatKind:
:= .value
if strings.HasSuffix(, "f") && != "-inf" && != "inf" {
= [:len()-len("f")]
}
if , := strconv.ParseFloat(, 32); == nil {
return protoreflect.ValueOfFloat32(float32()), nil
}
case protoreflect.DoubleKind:
:= .value
if strings.HasSuffix(, "f") && != "-inf" && != "inf" {
= [:len()-len("f")]
}
if , := strconv.ParseFloat(, 64); == nil {
return protoreflect.ValueOfFloat64(float64()), nil
}
case protoreflect.StringKind:
if isQuote(.value[0]) {
return protoreflect.ValueOfString(.unquoted), nil
}
case protoreflect.BytesKind:
if isQuote(.value[0]) {
return protoreflect.ValueOfBytes([]byte(.unquoted)), nil
}
case protoreflect.EnumKind:
if , := strconv.ParseInt(.value, 0, 32); == nil {
return protoreflect.ValueOfEnum(protoreflect.EnumNumber()), nil
}
:= .Enum().Values().ByName(protoreflect.Name(.value))
if != nil {
return protoreflect.ValueOfEnum(.Number()), nil
}
case protoreflect.MessageKind, protoreflect.GroupKind:
var string
switch .value {
case "{":
= "}"
case "<":
= ">"
default:
return , .errorf("expected '{' or '<', found %q", .value)
}
:= .unmarshalMessage(.Message(), )
return ,
default:
panic(fmt.Sprintf("invalid kind %v", .Kind()))
}
return , .errorf("invalid %v: %v", .Kind(), .value)
}
func ( *textParser) ( protoreflect.FieldDescriptor) *ParseError {
:= .next()
if .err != nil {
return .err
}
if .value != ":" {
if .Message() == nil {
return .errorf("expected ':', found %q", .value)
}
.back()
}
return nil
}
func ( *textParser) () (string, error) {
:= .next()
if .err != nil {
return "", .err
}
if len(.value) > 2 && isQuote(.value[0]) && .value[len(.value)-1] == .value[0] {
, := unquoteC(.value[1:len(.value)-1], rune(.value[0]))
if != nil {
return "",
}
return , .consumeToken("]")
}
var []string
for .value != "]" {
= append(, .value)
= .next()
if .err != nil {
return "", .errorf("unrecognized type_url or extension name: %s", .err)
}
if .done && .value != "]" {
return "", .errorf("unclosed type_url or extension name")
}
}
return strings.Join(, ""), nil
}
func ( *textParser) () error {
:= .next()
if .err != nil {
return .err
}
if .value != ";" && .value != "," {
.back()
}
return nil
}
func ( *textParser) ( string, ...interface{}) *ParseError {
:= &ParseError{fmt.Sprintf(, ...), .cur.line, .cur.offset}
.cur.err =
.done = true
return
}
func ( *textParser) () {
:= 0
for < len(.s) && (isWhitespace(.s[]) || .s[] == '#') {
if .s[] == '#' {
for < len(.s) && .s[] != '\n' {
++
}
if == len(.s) {
break
}
}
if .s[] == '\n' {
.line++
}
++
}
.offset +=
.s = .s[:len(.s)]
if len(.s) == 0 {
.done = true
}
}
func ( *textParser) () {
.skipWhitespace()
if .done {
return
}
.cur.err = nil
.cur.offset, .cur.line = .offset, .line
.cur.unquoted = ""
switch .s[0] {
case '<', '>', '{', '}', ':', '[', ']', ';', ',', '/':
.cur.value, .s = .s[0:1], .s[1:len(.s)]
case '"', '\'':
:= 1
for < len(.s) && .s[] != .s[0] && .s[] != '\n' {
if .s[] == '\\' && +1 < len(.s) {
++
}
++
}
if >= len(.s) || .s[] != .s[0] {
.errorf("unmatched quote")
return
}
, := unquoteC(.s[1:], rune(.s[0]))
if != nil {
.errorf("invalid quoted string %s: %v", .s[0:+1], )
return
}
.cur.value, .s = .s[0:+1], .s[+1:len(.s)]
.cur.unquoted =
default:
:= 0
for < len(.s) && isIdentOrNumberChar(.s[]) {
++
}
if == 0 {
.errorf("unexpected byte %#x", .s[0])
return
}
.cur.value, .s = .s[0:], .s[:len(.s)]
}
.offset += len(.cur.value)
}
func ( *textParser) () { .backed = true }
func ( *textParser) () *token {
if .backed || .done {
.backed = false
return &.cur
}
.advance()
if .done {
.cur.value = ""
} else if len(.cur.value) > 0 && isQuote(.cur.value[0]) {
:= .cur
for {
.skipWhitespace()
if .done || !isQuote(.s[0]) {
break
}
.advance()
if .cur.err != nil {
return &.cur
}
.value += " " + .cur.value
.unquoted += .cur.unquoted
}
.done = false
.cur =
}
return &.cur
}
func ( *textParser) ( string) error {
:= .next()
if .err != nil {
return .err
}
if .value != {
.back()
return .errorf("expected %q, found %q", , .value)
}
return nil
}
var errBadUTF8 = errors.New("proto: bad UTF-8")
func ( string, rune) (string, error) {
:= true
for , := range {
if == '\\' || == {
= false
break
}
}
if {
return , nil
}
:= make([]byte, 0, 3*len()/2)
for len() > 0 {
, := utf8.DecodeRuneInString()
if == utf8.RuneError && == 1 {
return "", errBadUTF8
}
= [:]
if != '\\' {
if < utf8.RuneSelf {
= append(, byte())
} else {
= append(, string()...)
}
continue
}
, , := unescape()
if != nil {
return "",
}
= append(, ...)
=
}
return string(), nil
}
func ( string) ( string, string, error) {
, := utf8.DecodeRuneInString()
if == utf8.RuneError && == 1 {
return "", "", errBadUTF8
}
= [:]
switch {
case 'a':
return "\a", , nil
case 'b':
return "\b", , nil
case 'f':
return "\f", , nil
case 'n':
return "\n", , nil
case 'r':
return "\r", , nil
case 't':
return "\t", , nil
case 'v':
return "\v", , nil
case '?':
return "?", , nil
case '\'', '"', '\\':
return string(), , nil
case '0', '1', '2', '3', '4', '5', '6', '7':
if len() < 2 {
return "", "", fmt.Errorf(`\%c requires 2 following digits`, )
}
:= string() + [:2]
= [2:]
, := strconv.ParseUint(, 8, 8)
if != nil {
return "", "", fmt.Errorf(`\%s contains non-octal digits`, )
}
return string([]byte{byte()}), , nil
case 'x', 'X', 'u', 'U':
var int
switch {
case 'x', 'X':
= 2
case 'u':
= 4
case 'U':
= 8
}
if len() < {
return "", "", fmt.Errorf(`\%c requires %d following digits`, , )
}
:= [:]
= [:]
, := strconv.ParseUint(, 16, 64)
if != nil {
return "", "", fmt.Errorf(`\%c%s contains non-hexadecimal digits`, , )
}
if == 'x' || == 'X' {
return string([]byte{byte()}), , nil
}
if > utf8.MaxRune {
return "", "", fmt.Errorf(`\%c%s is not a valid Unicode code point`, , )
}
return string(rune()), , nil
}
return "", "", fmt.Errorf(`unknown escape \%c`, )
}
func ( byte) bool {
switch {
case 'A' <= && <= 'Z', 'a' <= && <= 'z':
return true
case '0' <= && <= '9':
return true
}
switch {
case '-', '+', '.', '_':
return true
}
return false
}
func ( byte) bool {
switch {
case ' ', '\t', '\n', '\r':
return true
}
return false
}
func ( byte) bool {
switch {
case '"', '\'':
return true
}
return false
}