gtsocial-umbx

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

text_decode.go (20106B)


      1 // Copyright 2010 The Go Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style
      3 // license that can be found in the LICENSE file.
      4 
      5 package proto
      6 
      7 import (
      8 	"encoding"
      9 	"errors"
     10 	"fmt"
     11 	"reflect"
     12 	"strconv"
     13 	"strings"
     14 	"unicode/utf8"
     15 
     16 	"google.golang.org/protobuf/encoding/prototext"
     17 	protoV2 "google.golang.org/protobuf/proto"
     18 	"google.golang.org/protobuf/reflect/protoreflect"
     19 	"google.golang.org/protobuf/reflect/protoregistry"
     20 )
     21 
     22 const wrapTextUnmarshalV2 = false
     23 
     24 // ParseError is returned by UnmarshalText.
     25 type ParseError struct {
     26 	Message string
     27 
     28 	// Deprecated: Do not use.
     29 	Line, Offset int
     30 }
     31 
     32 func (e *ParseError) Error() string {
     33 	if wrapTextUnmarshalV2 {
     34 		return e.Message
     35 	}
     36 	if e.Line == 1 {
     37 		return fmt.Sprintf("line 1.%d: %v", e.Offset, e.Message)
     38 	}
     39 	return fmt.Sprintf("line %d: %v", e.Line, e.Message)
     40 }
     41 
     42 // UnmarshalText parses a proto text formatted string into m.
     43 func UnmarshalText(s string, m Message) error {
     44 	if u, ok := m.(encoding.TextUnmarshaler); ok {
     45 		return u.UnmarshalText([]byte(s))
     46 	}
     47 
     48 	m.Reset()
     49 	mi := MessageV2(m)
     50 
     51 	if wrapTextUnmarshalV2 {
     52 		err := prototext.UnmarshalOptions{
     53 			AllowPartial: true,
     54 		}.Unmarshal([]byte(s), mi)
     55 		if err != nil {
     56 			return &ParseError{Message: err.Error()}
     57 		}
     58 		return checkRequiredNotSet(mi)
     59 	} else {
     60 		if err := newTextParser(s).unmarshalMessage(mi.ProtoReflect(), ""); err != nil {
     61 			return err
     62 		}
     63 		return checkRequiredNotSet(mi)
     64 	}
     65 }
     66 
     67 type textParser struct {
     68 	s            string // remaining input
     69 	done         bool   // whether the parsing is finished (success or error)
     70 	backed       bool   // whether back() was called
     71 	offset, line int
     72 	cur          token
     73 }
     74 
     75 type token struct {
     76 	value    string
     77 	err      *ParseError
     78 	line     int    // line number
     79 	offset   int    // byte number from start of input, not start of line
     80 	unquoted string // the unquoted version of value, if it was a quoted string
     81 }
     82 
     83 func newTextParser(s string) *textParser {
     84 	p := new(textParser)
     85 	p.s = s
     86 	p.line = 1
     87 	p.cur.line = 1
     88 	return p
     89 }
     90 
     91 func (p *textParser) unmarshalMessage(m protoreflect.Message, terminator string) (err error) {
     92 	md := m.Descriptor()
     93 	fds := md.Fields()
     94 
     95 	// A struct is a sequence of "name: value", terminated by one of
     96 	// '>' or '}', or the end of the input.  A name may also be
     97 	// "[extension]" or "[type/url]".
     98 	//
     99 	// The whole struct can also be an expanded Any message, like:
    100 	// [type/url] < ... struct contents ... >
    101 	seen := make(map[protoreflect.FieldNumber]bool)
    102 	for {
    103 		tok := p.next()
    104 		if tok.err != nil {
    105 			return tok.err
    106 		}
    107 		if tok.value == terminator {
    108 			break
    109 		}
    110 		if tok.value == "[" {
    111 			if err := p.unmarshalExtensionOrAny(m, seen); err != nil {
    112 				return err
    113 			}
    114 			continue
    115 		}
    116 
    117 		// This is a normal, non-extension field.
    118 		name := protoreflect.Name(tok.value)
    119 		fd := fds.ByName(name)
    120 		switch {
    121 		case fd == nil:
    122 			gd := fds.ByName(protoreflect.Name(strings.ToLower(string(name))))
    123 			if gd != nil && gd.Kind() == protoreflect.GroupKind && gd.Message().Name() == name {
    124 				fd = gd
    125 			}
    126 		case fd.Kind() == protoreflect.GroupKind && fd.Message().Name() != name:
    127 			fd = nil
    128 		case fd.IsWeak() && fd.Message().IsPlaceholder():
    129 			fd = nil
    130 		}
    131 		if fd == nil {
    132 			typeName := string(md.FullName())
    133 			if m, ok := m.Interface().(Message); ok {
    134 				t := reflect.TypeOf(m)
    135 				if t.Kind() == reflect.Ptr {
    136 					typeName = t.Elem().String()
    137 				}
    138 			}
    139 			return p.errorf("unknown field name %q in %v", name, typeName)
    140 		}
    141 		if od := fd.ContainingOneof(); od != nil && m.WhichOneof(od) != nil {
    142 			return p.errorf("field '%s' would overwrite already parsed oneof '%s'", name, od.Name())
    143 		}
    144 		if fd.Cardinality() != protoreflect.Repeated && seen[fd.Number()] {
    145 			return p.errorf("non-repeated field %q was repeated", fd.Name())
    146 		}
    147 		seen[fd.Number()] = true
    148 
    149 		// Consume any colon.
    150 		if err := p.checkForColon(fd); err != nil {
    151 			return err
    152 		}
    153 
    154 		// Parse into the field.
    155 		v := m.Get(fd)
    156 		if !m.Has(fd) && (fd.IsList() || fd.IsMap() || fd.Message() != nil) {
    157 			v = m.Mutable(fd)
    158 		}
    159 		if v, err = p.unmarshalValue(v, fd); err != nil {
    160 			return err
    161 		}
    162 		m.Set(fd, v)
    163 
    164 		if err := p.consumeOptionalSeparator(); err != nil {
    165 			return err
    166 		}
    167 	}
    168 	return nil
    169 }
    170 
    171 func (p *textParser) unmarshalExtensionOrAny(m protoreflect.Message, seen map[protoreflect.FieldNumber]bool) error {
    172 	name, err := p.consumeExtensionOrAnyName()
    173 	if err != nil {
    174 		return err
    175 	}
    176 
    177 	// If it contains a slash, it's an Any type URL.
    178 	if slashIdx := strings.LastIndex(name, "/"); slashIdx >= 0 {
    179 		tok := p.next()
    180 		if tok.err != nil {
    181 			return tok.err
    182 		}
    183 		// consume an optional colon
    184 		if tok.value == ":" {
    185 			tok = p.next()
    186 			if tok.err != nil {
    187 				return tok.err
    188 			}
    189 		}
    190 
    191 		var terminator string
    192 		switch tok.value {
    193 		case "<":
    194 			terminator = ">"
    195 		case "{":
    196 			terminator = "}"
    197 		default:
    198 			return p.errorf("expected '{' or '<', found %q", tok.value)
    199 		}
    200 
    201 		mt, err := protoregistry.GlobalTypes.FindMessageByURL(name)
    202 		if err != nil {
    203 			return p.errorf("unrecognized message %q in google.protobuf.Any", name[slashIdx+len("/"):])
    204 		}
    205 		m2 := mt.New()
    206 		if err := p.unmarshalMessage(m2, terminator); err != nil {
    207 			return err
    208 		}
    209 		b, err := protoV2.Marshal(m2.Interface())
    210 		if err != nil {
    211 			return p.errorf("failed to marshal message of type %q: %v", name[slashIdx+len("/"):], err)
    212 		}
    213 
    214 		urlFD := m.Descriptor().Fields().ByName("type_url")
    215 		valFD := m.Descriptor().Fields().ByName("value")
    216 		if seen[urlFD.Number()] {
    217 			return p.errorf("Any message unpacked multiple times, or %q already set", urlFD.Name())
    218 		}
    219 		if seen[valFD.Number()] {
    220 			return p.errorf("Any message unpacked multiple times, or %q already set", valFD.Name())
    221 		}
    222 		m.Set(urlFD, protoreflect.ValueOfString(name))
    223 		m.Set(valFD, protoreflect.ValueOfBytes(b))
    224 		seen[urlFD.Number()] = true
    225 		seen[valFD.Number()] = true
    226 		return nil
    227 	}
    228 
    229 	xname := protoreflect.FullName(name)
    230 	xt, _ := protoregistry.GlobalTypes.FindExtensionByName(xname)
    231 	if xt == nil && isMessageSet(m.Descriptor()) {
    232 		xt, _ = protoregistry.GlobalTypes.FindExtensionByName(xname.Append("message_set_extension"))
    233 	}
    234 	if xt == nil {
    235 		return p.errorf("unrecognized extension %q", name)
    236 	}
    237 	fd := xt.TypeDescriptor()
    238 	if fd.ContainingMessage().FullName() != m.Descriptor().FullName() {
    239 		return p.errorf("extension field %q does not extend message %q", name, m.Descriptor().FullName())
    240 	}
    241 
    242 	if err := p.checkForColon(fd); err != nil {
    243 		return err
    244 	}
    245 
    246 	v := m.Get(fd)
    247 	if !m.Has(fd) && (fd.IsList() || fd.IsMap() || fd.Message() != nil) {
    248 		v = m.Mutable(fd)
    249 	}
    250 	v, err = p.unmarshalValue(v, fd)
    251 	if err != nil {
    252 		return err
    253 	}
    254 	m.Set(fd, v)
    255 	return p.consumeOptionalSeparator()
    256 }
    257 
    258 func (p *textParser) unmarshalValue(v protoreflect.Value, fd protoreflect.FieldDescriptor) (protoreflect.Value, error) {
    259 	tok := p.next()
    260 	if tok.err != nil {
    261 		return v, tok.err
    262 	}
    263 	if tok.value == "" {
    264 		return v, p.errorf("unexpected EOF")
    265 	}
    266 
    267 	switch {
    268 	case fd.IsList():
    269 		lv := v.List()
    270 		var err error
    271 		if tok.value == "[" {
    272 			// Repeated field with list notation, like [1,2,3].
    273 			for {
    274 				vv := lv.NewElement()
    275 				vv, err = p.unmarshalSingularValue(vv, fd)
    276 				if err != nil {
    277 					return v, err
    278 				}
    279 				lv.Append(vv)
    280 
    281 				tok := p.next()
    282 				if tok.err != nil {
    283 					return v, tok.err
    284 				}
    285 				if tok.value == "]" {
    286 					break
    287 				}
    288 				if tok.value != "," {
    289 					return v, p.errorf("Expected ']' or ',' found %q", tok.value)
    290 				}
    291 			}
    292 			return v, nil
    293 		}
    294 
    295 		// One value of the repeated field.
    296 		p.back()
    297 		vv := lv.NewElement()
    298 		vv, err = p.unmarshalSingularValue(vv, fd)
    299 		if err != nil {
    300 			return v, err
    301 		}
    302 		lv.Append(vv)
    303 		return v, nil
    304 	case fd.IsMap():
    305 		// The map entry should be this sequence of tokens:
    306 		//	< key : KEY value : VALUE >
    307 		// However, implementations may omit key or value, and technically
    308 		// we should support them in any order.
    309 		var terminator string
    310 		switch tok.value {
    311 		case "<":
    312 			terminator = ">"
    313 		case "{":
    314 			terminator = "}"
    315 		default:
    316 			return v, p.errorf("expected '{' or '<', found %q", tok.value)
    317 		}
    318 
    319 		keyFD := fd.MapKey()
    320 		valFD := fd.MapValue()
    321 
    322 		mv := v.Map()
    323 		kv := keyFD.Default()
    324 		vv := mv.NewValue()
    325 		for {
    326 			tok := p.next()
    327 			if tok.err != nil {
    328 				return v, tok.err
    329 			}
    330 			if tok.value == terminator {
    331 				break
    332 			}
    333 			var err error
    334 			switch tok.value {
    335 			case "key":
    336 				if err := p.consumeToken(":"); err != nil {
    337 					return v, err
    338 				}
    339 				if kv, err = p.unmarshalSingularValue(kv, keyFD); err != nil {
    340 					return v, err
    341 				}
    342 				if err := p.consumeOptionalSeparator(); err != nil {
    343 					return v, err
    344 				}
    345 			case "value":
    346 				if err := p.checkForColon(valFD); err != nil {
    347 					return v, err
    348 				}
    349 				if vv, err = p.unmarshalSingularValue(vv, valFD); err != nil {
    350 					return v, err
    351 				}
    352 				if err := p.consumeOptionalSeparator(); err != nil {
    353 					return v, err
    354 				}
    355 			default:
    356 				p.back()
    357 				return v, p.errorf(`expected "key", "value", or %q, found %q`, terminator, tok.value)
    358 			}
    359 		}
    360 		mv.Set(kv.MapKey(), vv)
    361 		return v, nil
    362 	default:
    363 		p.back()
    364 		return p.unmarshalSingularValue(v, fd)
    365 	}
    366 }
    367 
    368 func (p *textParser) unmarshalSingularValue(v protoreflect.Value, fd protoreflect.FieldDescriptor) (protoreflect.Value, error) {
    369 	tok := p.next()
    370 	if tok.err != nil {
    371 		return v, tok.err
    372 	}
    373 	if tok.value == "" {
    374 		return v, p.errorf("unexpected EOF")
    375 	}
    376 
    377 	switch fd.Kind() {
    378 	case protoreflect.BoolKind:
    379 		switch tok.value {
    380 		case "true", "1", "t", "True":
    381 			return protoreflect.ValueOfBool(true), nil
    382 		case "false", "0", "f", "False":
    383 			return protoreflect.ValueOfBool(false), nil
    384 		}
    385 	case protoreflect.Int32Kind, protoreflect.Sint32Kind, protoreflect.Sfixed32Kind:
    386 		if x, err := strconv.ParseInt(tok.value, 0, 32); err == nil {
    387 			return protoreflect.ValueOfInt32(int32(x)), nil
    388 		}
    389 
    390 		// The C++ parser accepts large positive hex numbers that uses
    391 		// two's complement arithmetic to represent negative numbers.
    392 		// This feature is here for backwards compatibility with C++.
    393 		if strings.HasPrefix(tok.value, "0x") {
    394 			if x, err := strconv.ParseUint(tok.value, 0, 32); err == nil {
    395 				return protoreflect.ValueOfInt32(int32(-(int64(^x) + 1))), nil
    396 			}
    397 		}
    398 	case protoreflect.Int64Kind, protoreflect.Sint64Kind, protoreflect.Sfixed64Kind:
    399 		if x, err := strconv.ParseInt(tok.value, 0, 64); err == nil {
    400 			return protoreflect.ValueOfInt64(int64(x)), nil
    401 		}
    402 
    403 		// The C++ parser accepts large positive hex numbers that uses
    404 		// two's complement arithmetic to represent negative numbers.
    405 		// This feature is here for backwards compatibility with C++.
    406 		if strings.HasPrefix(tok.value, "0x") {
    407 			if x, err := strconv.ParseUint(tok.value, 0, 64); err == nil {
    408 				return protoreflect.ValueOfInt64(int64(-(int64(^x) + 1))), nil
    409 			}
    410 		}
    411 	case protoreflect.Uint32Kind, protoreflect.Fixed32Kind:
    412 		if x, err := strconv.ParseUint(tok.value, 0, 32); err == nil {
    413 			return protoreflect.ValueOfUint32(uint32(x)), nil
    414 		}
    415 	case protoreflect.Uint64Kind, protoreflect.Fixed64Kind:
    416 		if x, err := strconv.ParseUint(tok.value, 0, 64); err == nil {
    417 			return protoreflect.ValueOfUint64(uint64(x)), nil
    418 		}
    419 	case protoreflect.FloatKind:
    420 		// Ignore 'f' for compatibility with output generated by C++,
    421 		// but don't remove 'f' when the value is "-inf" or "inf".
    422 		v := tok.value
    423 		if strings.HasSuffix(v, "f") && v != "-inf" && v != "inf" {
    424 			v = v[:len(v)-len("f")]
    425 		}
    426 		if x, err := strconv.ParseFloat(v, 32); err == nil {
    427 			return protoreflect.ValueOfFloat32(float32(x)), nil
    428 		}
    429 	case protoreflect.DoubleKind:
    430 		// Ignore 'f' for compatibility with output generated by C++,
    431 		// but don't remove 'f' when the value is "-inf" or "inf".
    432 		v := tok.value
    433 		if strings.HasSuffix(v, "f") && v != "-inf" && v != "inf" {
    434 			v = v[:len(v)-len("f")]
    435 		}
    436 		if x, err := strconv.ParseFloat(v, 64); err == nil {
    437 			return protoreflect.ValueOfFloat64(float64(x)), nil
    438 		}
    439 	case protoreflect.StringKind:
    440 		if isQuote(tok.value[0]) {
    441 			return protoreflect.ValueOfString(tok.unquoted), nil
    442 		}
    443 	case protoreflect.BytesKind:
    444 		if isQuote(tok.value[0]) {
    445 			return protoreflect.ValueOfBytes([]byte(tok.unquoted)), nil
    446 		}
    447 	case protoreflect.EnumKind:
    448 		if x, err := strconv.ParseInt(tok.value, 0, 32); err == nil {
    449 			return protoreflect.ValueOfEnum(protoreflect.EnumNumber(x)), nil
    450 		}
    451 		vd := fd.Enum().Values().ByName(protoreflect.Name(tok.value))
    452 		if vd != nil {
    453 			return protoreflect.ValueOfEnum(vd.Number()), nil
    454 		}
    455 	case protoreflect.MessageKind, protoreflect.GroupKind:
    456 		var terminator string
    457 		switch tok.value {
    458 		case "{":
    459 			terminator = "}"
    460 		case "<":
    461 			terminator = ">"
    462 		default:
    463 			return v, p.errorf("expected '{' or '<', found %q", tok.value)
    464 		}
    465 		err := p.unmarshalMessage(v.Message(), terminator)
    466 		return v, err
    467 	default:
    468 		panic(fmt.Sprintf("invalid kind %v", fd.Kind()))
    469 	}
    470 	return v, p.errorf("invalid %v: %v", fd.Kind(), tok.value)
    471 }
    472 
    473 // Consume a ':' from the input stream (if the next token is a colon),
    474 // returning an error if a colon is needed but not present.
    475 func (p *textParser) checkForColon(fd protoreflect.FieldDescriptor) *ParseError {
    476 	tok := p.next()
    477 	if tok.err != nil {
    478 		return tok.err
    479 	}
    480 	if tok.value != ":" {
    481 		if fd.Message() == nil {
    482 			return p.errorf("expected ':', found %q", tok.value)
    483 		}
    484 		p.back()
    485 	}
    486 	return nil
    487 }
    488 
    489 // consumeExtensionOrAnyName consumes an extension name or an Any type URL and
    490 // the following ']'. It returns the name or URL consumed.
    491 func (p *textParser) consumeExtensionOrAnyName() (string, error) {
    492 	tok := p.next()
    493 	if tok.err != nil {
    494 		return "", tok.err
    495 	}
    496 
    497 	// If extension name or type url is quoted, it's a single token.
    498 	if len(tok.value) > 2 && isQuote(tok.value[0]) && tok.value[len(tok.value)-1] == tok.value[0] {
    499 		name, err := unquoteC(tok.value[1:len(tok.value)-1], rune(tok.value[0]))
    500 		if err != nil {
    501 			return "", err
    502 		}
    503 		return name, p.consumeToken("]")
    504 	}
    505 
    506 	// Consume everything up to "]"
    507 	var parts []string
    508 	for tok.value != "]" {
    509 		parts = append(parts, tok.value)
    510 		tok = p.next()
    511 		if tok.err != nil {
    512 			return "", p.errorf("unrecognized type_url or extension name: %s", tok.err)
    513 		}
    514 		if p.done && tok.value != "]" {
    515 			return "", p.errorf("unclosed type_url or extension name")
    516 		}
    517 	}
    518 	return strings.Join(parts, ""), nil
    519 }
    520 
    521 // consumeOptionalSeparator consumes an optional semicolon or comma.
    522 // It is used in unmarshalMessage to provide backward compatibility.
    523 func (p *textParser) consumeOptionalSeparator() error {
    524 	tok := p.next()
    525 	if tok.err != nil {
    526 		return tok.err
    527 	}
    528 	if tok.value != ";" && tok.value != "," {
    529 		p.back()
    530 	}
    531 	return nil
    532 }
    533 
    534 func (p *textParser) errorf(format string, a ...interface{}) *ParseError {
    535 	pe := &ParseError{fmt.Sprintf(format, a...), p.cur.line, p.cur.offset}
    536 	p.cur.err = pe
    537 	p.done = true
    538 	return pe
    539 }
    540 
    541 func (p *textParser) skipWhitespace() {
    542 	i := 0
    543 	for i < len(p.s) && (isWhitespace(p.s[i]) || p.s[i] == '#') {
    544 		if p.s[i] == '#' {
    545 			// comment; skip to end of line or input
    546 			for i < len(p.s) && p.s[i] != '\n' {
    547 				i++
    548 			}
    549 			if i == len(p.s) {
    550 				break
    551 			}
    552 		}
    553 		if p.s[i] == '\n' {
    554 			p.line++
    555 		}
    556 		i++
    557 	}
    558 	p.offset += i
    559 	p.s = p.s[i:len(p.s)]
    560 	if len(p.s) == 0 {
    561 		p.done = true
    562 	}
    563 }
    564 
    565 func (p *textParser) advance() {
    566 	// Skip whitespace
    567 	p.skipWhitespace()
    568 	if p.done {
    569 		return
    570 	}
    571 
    572 	// Start of non-whitespace
    573 	p.cur.err = nil
    574 	p.cur.offset, p.cur.line = p.offset, p.line
    575 	p.cur.unquoted = ""
    576 	switch p.s[0] {
    577 	case '<', '>', '{', '}', ':', '[', ']', ';', ',', '/':
    578 		// Single symbol
    579 		p.cur.value, p.s = p.s[0:1], p.s[1:len(p.s)]
    580 	case '"', '\'':
    581 		// Quoted string
    582 		i := 1
    583 		for i < len(p.s) && p.s[i] != p.s[0] && p.s[i] != '\n' {
    584 			if p.s[i] == '\\' && i+1 < len(p.s) {
    585 				// skip escaped char
    586 				i++
    587 			}
    588 			i++
    589 		}
    590 		if i >= len(p.s) || p.s[i] != p.s[0] {
    591 			p.errorf("unmatched quote")
    592 			return
    593 		}
    594 		unq, err := unquoteC(p.s[1:i], rune(p.s[0]))
    595 		if err != nil {
    596 			p.errorf("invalid quoted string %s: %v", p.s[0:i+1], err)
    597 			return
    598 		}
    599 		p.cur.value, p.s = p.s[0:i+1], p.s[i+1:len(p.s)]
    600 		p.cur.unquoted = unq
    601 	default:
    602 		i := 0
    603 		for i < len(p.s) && isIdentOrNumberChar(p.s[i]) {
    604 			i++
    605 		}
    606 		if i == 0 {
    607 			p.errorf("unexpected byte %#x", p.s[0])
    608 			return
    609 		}
    610 		p.cur.value, p.s = p.s[0:i], p.s[i:len(p.s)]
    611 	}
    612 	p.offset += len(p.cur.value)
    613 }
    614 
    615 // Back off the parser by one token. Can only be done between calls to next().
    616 // It makes the next advance() a no-op.
    617 func (p *textParser) back() { p.backed = true }
    618 
    619 // Advances the parser and returns the new current token.
    620 func (p *textParser) next() *token {
    621 	if p.backed || p.done {
    622 		p.backed = false
    623 		return &p.cur
    624 	}
    625 	p.advance()
    626 	if p.done {
    627 		p.cur.value = ""
    628 	} else if len(p.cur.value) > 0 && isQuote(p.cur.value[0]) {
    629 		// Look for multiple quoted strings separated by whitespace,
    630 		// and concatenate them.
    631 		cat := p.cur
    632 		for {
    633 			p.skipWhitespace()
    634 			if p.done || !isQuote(p.s[0]) {
    635 				break
    636 			}
    637 			p.advance()
    638 			if p.cur.err != nil {
    639 				return &p.cur
    640 			}
    641 			cat.value += " " + p.cur.value
    642 			cat.unquoted += p.cur.unquoted
    643 		}
    644 		p.done = false // parser may have seen EOF, but we want to return cat
    645 		p.cur = cat
    646 	}
    647 	return &p.cur
    648 }
    649 
    650 func (p *textParser) consumeToken(s string) error {
    651 	tok := p.next()
    652 	if tok.err != nil {
    653 		return tok.err
    654 	}
    655 	if tok.value != s {
    656 		p.back()
    657 		return p.errorf("expected %q, found %q", s, tok.value)
    658 	}
    659 	return nil
    660 }
    661 
    662 var errBadUTF8 = errors.New("proto: bad UTF-8")
    663 
    664 func unquoteC(s string, quote rune) (string, error) {
    665 	// This is based on C++'s tokenizer.cc.
    666 	// Despite its name, this is *not* parsing C syntax.
    667 	// For instance, "\0" is an invalid quoted string.
    668 
    669 	// Avoid allocation in trivial cases.
    670 	simple := true
    671 	for _, r := range s {
    672 		if r == '\\' || r == quote {
    673 			simple = false
    674 			break
    675 		}
    676 	}
    677 	if simple {
    678 		return s, nil
    679 	}
    680 
    681 	buf := make([]byte, 0, 3*len(s)/2)
    682 	for len(s) > 0 {
    683 		r, n := utf8.DecodeRuneInString(s)
    684 		if r == utf8.RuneError && n == 1 {
    685 			return "", errBadUTF8
    686 		}
    687 		s = s[n:]
    688 		if r != '\\' {
    689 			if r < utf8.RuneSelf {
    690 				buf = append(buf, byte(r))
    691 			} else {
    692 				buf = append(buf, string(r)...)
    693 			}
    694 			continue
    695 		}
    696 
    697 		ch, tail, err := unescape(s)
    698 		if err != nil {
    699 			return "", err
    700 		}
    701 		buf = append(buf, ch...)
    702 		s = tail
    703 	}
    704 	return string(buf), nil
    705 }
    706 
    707 func unescape(s string) (ch string, tail string, err error) {
    708 	r, n := utf8.DecodeRuneInString(s)
    709 	if r == utf8.RuneError && n == 1 {
    710 		return "", "", errBadUTF8
    711 	}
    712 	s = s[n:]
    713 	switch r {
    714 	case 'a':
    715 		return "\a", s, nil
    716 	case 'b':
    717 		return "\b", s, nil
    718 	case 'f':
    719 		return "\f", s, nil
    720 	case 'n':
    721 		return "\n", s, nil
    722 	case 'r':
    723 		return "\r", s, nil
    724 	case 't':
    725 		return "\t", s, nil
    726 	case 'v':
    727 		return "\v", s, nil
    728 	case '?':
    729 		return "?", s, nil // trigraph workaround
    730 	case '\'', '"', '\\':
    731 		return string(r), s, nil
    732 	case '0', '1', '2', '3', '4', '5', '6', '7':
    733 		if len(s) < 2 {
    734 			return "", "", fmt.Errorf(`\%c requires 2 following digits`, r)
    735 		}
    736 		ss := string(r) + s[:2]
    737 		s = s[2:]
    738 		i, err := strconv.ParseUint(ss, 8, 8)
    739 		if err != nil {
    740 			return "", "", fmt.Errorf(`\%s contains non-octal digits`, ss)
    741 		}
    742 		return string([]byte{byte(i)}), s, nil
    743 	case 'x', 'X', 'u', 'U':
    744 		var n int
    745 		switch r {
    746 		case 'x', 'X':
    747 			n = 2
    748 		case 'u':
    749 			n = 4
    750 		case 'U':
    751 			n = 8
    752 		}
    753 		if len(s) < n {
    754 			return "", "", fmt.Errorf(`\%c requires %d following digits`, r, n)
    755 		}
    756 		ss := s[:n]
    757 		s = s[n:]
    758 		i, err := strconv.ParseUint(ss, 16, 64)
    759 		if err != nil {
    760 			return "", "", fmt.Errorf(`\%c%s contains non-hexadecimal digits`, r, ss)
    761 		}
    762 		if r == 'x' || r == 'X' {
    763 			return string([]byte{byte(i)}), s, nil
    764 		}
    765 		if i > utf8.MaxRune {
    766 			return "", "", fmt.Errorf(`\%c%s is not a valid Unicode code point`, r, ss)
    767 		}
    768 		return string(rune(i)), s, nil
    769 	}
    770 	return "", "", fmt.Errorf(`unknown escape \%c`, r)
    771 }
    772 
    773 func isIdentOrNumberChar(c byte) bool {
    774 	switch {
    775 	case 'A' <= c && c <= 'Z', 'a' <= c && c <= 'z':
    776 		return true
    777 	case '0' <= c && c <= '9':
    778 		return true
    779 	}
    780 	switch c {
    781 	case '-', '+', '.', '_':
    782 		return true
    783 	}
    784 	return false
    785 }
    786 
    787 func isWhitespace(c byte) bool {
    788 	switch c {
    789 	case ' ', '\t', '\n', '\r':
    790 		return true
    791 	}
    792 	return false
    793 }
    794 
    795 func isQuote(c byte) bool {
    796 	switch c {
    797 	case '"', '\'':
    798 		return true
    799 	}
    800 	return false
    801 }