|
|
@@ -602,8 +602,9 @@ func (p *textParser) readStruct(sv reflect.Value, terminator string) error {
|
|
|
|
|
|
// The map entry should be this sequence of tokens:
|
|
|
// < key : KEY value : VALUE >
|
|
|
- // Technically the "key" and "value" could come in any order,
|
|
|
- // but in practice they won't.
|
|
|
+ // However, implementations may omit key or value, and technically
|
|
|
+ // we should support them in any order. See b/28924776 for a time
|
|
|
+ // this went wrong.
|
|
|
|
|
|
tok := p.next()
|
|
|
var terminator string
|
|
|
@@ -615,32 +616,39 @@ func (p *textParser) readStruct(sv reflect.Value, terminator string) error {
|
|
|
default:
|
|
|
return p.errorf("expected '{' or '<', found %q", tok.value)
|
|
|
}
|
|
|
- if err := p.consumeToken("key"); err != nil {
|
|
|
- return err
|
|
|
- }
|
|
|
- if err := p.consumeToken(":"); err != nil {
|
|
|
- return err
|
|
|
- }
|
|
|
- if err := p.readAny(key, props.mkeyprop); err != nil {
|
|
|
- return err
|
|
|
- }
|
|
|
- if err := p.consumeOptionalSeparator(); err != nil {
|
|
|
- return err
|
|
|
- }
|
|
|
- if err := p.consumeToken("value"); err != nil {
|
|
|
- return err
|
|
|
- }
|
|
|
- if err := p.checkForColon(props.mvalprop, dst.Type().Elem()); err != nil {
|
|
|
- return err
|
|
|
- }
|
|
|
- if err := p.readAny(val, props.mvalprop); err != nil {
|
|
|
- return err
|
|
|
- }
|
|
|
- if err := p.consumeOptionalSeparator(); err != nil {
|
|
|
- return err
|
|
|
- }
|
|
|
- if err := p.consumeToken(terminator); err != nil {
|
|
|
- return err
|
|
|
+ for {
|
|
|
+ tok := p.next()
|
|
|
+ if tok.err != nil {
|
|
|
+ return tok.err
|
|
|
+ }
|
|
|
+ if tok.value == terminator {
|
|
|
+ break
|
|
|
+ }
|
|
|
+ switch tok.value {
|
|
|
+ case "key":
|
|
|
+ if err := p.consumeToken(":"); err != nil {
|
|
|
+ return err
|
|
|
+ }
|
|
|
+ if err := p.readAny(key, props.mkeyprop); err != nil {
|
|
|
+ return err
|
|
|
+ }
|
|
|
+ if err := p.consumeOptionalSeparator(); err != nil {
|
|
|
+ return err
|
|
|
+ }
|
|
|
+ case "value":
|
|
|
+ if err := p.checkForColon(props.mvalprop, dst.Type().Elem()); err != nil {
|
|
|
+ return err
|
|
|
+ }
|
|
|
+ if err := p.readAny(val, props.mvalprop); err != nil {
|
|
|
+ return err
|
|
|
+ }
|
|
|
+ if err := p.consumeOptionalSeparator(); err != nil {
|
|
|
+ return err
|
|
|
+ }
|
|
|
+ default:
|
|
|
+ p.back()
|
|
|
+ return p.errorf(`expected "key", "value", or %q, found %q`, terminator, tok.value)
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
dst.SetMapIndex(key, val)
|