Copyright 2018 The Go Authors. All rights reserved. Use of this source code is governed by a BSD-style license that can be found in the LICENSE file.

package text

import (
	
	
	
	
	
	

	
)
Decoder is a token-based textproto decoder.
lastCall is last method called, either readCall or peekCall. Initial value is readCall.
lastToken contains the last read token.
lastErr contains the last read error.
openStack is a stack containing the byte characters for MessageOpen and ListOpen kinds. The top of stack represents the message or the list that the current token is nested in. An empty stack means the current token is at the top level message. The characters '{' and '<' both represent the MessageOpen kind.
orig is used in reporting line and column.
in contains the unconsumed input.
	in []byte
}
NewDecoder returns a Decoder to read the given []byte.
func ( []byte) *Decoder {
	return &Decoder{orig: , in: }
}
ErrUnexpectedEOF means that EOF was encountered in the middle of the input.
call specifies which Decoder method was invoked.
type call uint8

const (
	readCall call = iota
	peekCall
)
Peek looks ahead and returns the next token and error without advancing a read.
func ( *Decoder) () (Token, error) {
	defer func() { .lastCall = peekCall }()
	if .lastCall == readCall {
		.lastToken, .lastErr = .Read()
	}
	return .lastToken, .lastErr
}
Read returns the next token. It will return an error if there is no valid token.
func ( *Decoder) () (Token, error) {
	defer func() { .lastCall = readCall }()
	if .lastCall == peekCall {
		return .lastToken, .lastErr
	}

	,  := .parseNext(.lastToken.kind)
	if  != nil {
		return Token{}, 
	}

	switch .kind {
	case comma, semicolon:
		,  = .parseNext(.kind)
		if  != nil {
			return Token{}, 
		}
	}
	.lastToken = 
	return , nil
}

const (
	mismatchedFmt = "mismatched close character %q"
	unexpectedFmt = "unexpected character %q"
)
parseNext parses the next Token based on given last kind.
Trim leading spaces.
	.consume(0)
	 := false
	if len(.in) == 0 {
		 = true
	}

	switch  {
	case EOF:
		return .consumeToken(EOF, 0, 0), nil

Start of top level message. Next token can be EOF or Name.
		if  {
			return .consumeToken(EOF, 0, 0), nil
		}
		return .parseFieldName()

Next token can be MessageOpen, ListOpen or Scalar.
		if  {
			return Token{}, ErrUnexpectedEOF
		}
		switch  := .in[0];  {
		case '{', '<':
			.pushOpenStack()
			return .consumeToken(MessageOpen, 1, 0), nil
		case '[':
			.pushOpenStack()
			return .consumeToken(ListOpen, 1, 0), nil
		default:
			return .parseScalar()
		}

	case Scalar:
		,  := .currentOpenKind()
		switch  {
Top level message. Next token can be EOF, comma, semicolon or Name.
			if  {
				return .consumeToken(EOF, 0, 0), nil
			}
			switch .in[0] {
			case ',':
				return .consumeToken(comma, 1, 0), nil
			case ';':
				return .consumeToken(semicolon, 1, 0), nil
			default:
				return .parseFieldName()
			}

Next token can be MessageClose, comma, semicolon or Name.
			if  {
				return Token{}, ErrUnexpectedEOF
			}
			switch  := .in[0];  {
			case :
				.popOpenStack()
				return .consumeToken(MessageClose, 1, 0), nil
			case otherCloseChar[]:
				return Token{}, .newSyntaxError(mismatchedFmt, )
			case ',':
				return .consumeToken(comma, 1, 0), nil
			case ';':
				return .consumeToken(semicolon, 1, 0), nil
			default:
				return .parseFieldName()
			}

Next token can be ListClose or comma.
			if  {
				return Token{}, ErrUnexpectedEOF
			}
			switch  := .in[0];  {
			case ']':
				.popOpenStack()
				return .consumeToken(ListClose, 1, 0), nil
			case ',':
				return .consumeToken(comma, 1, 0), nil
			default:
				return Token{}, .newSyntaxError(unexpectedFmt, )
			}
		}

Next token can be MessageClose or Name.
		if  {
			return Token{}, ErrUnexpectedEOF
		}
		,  := .currentOpenKind()
		switch  := .in[0];  {
		case :
			.popOpenStack()
			return .consumeToken(MessageClose, 1, 0), nil
		case otherCloseChar[]:
			return Token{}, .newSyntaxError(mismatchedFmt, )
		default:
			return .parseFieldName()
		}

	case MessageClose:
		,  := .currentOpenKind()
		switch  {
Top level message. Next token can be EOF, comma, semicolon or Name.
			if  {
				return .consumeToken(EOF, 0, 0), nil
			}
			switch  := .in[0];  {
			case ',':
				return .consumeToken(comma, 1, 0), nil
			case ';':
				return .consumeToken(semicolon, 1, 0), nil
			default:
				return .parseFieldName()
			}

Next token can be MessageClose, comma, semicolon or Name.
			if  {
				return Token{}, ErrUnexpectedEOF
			}
			switch  := .in[0];  {
			case :
				.popOpenStack()
				return .consumeToken(MessageClose, 1, 0), nil
			case otherCloseChar[]:
				return Token{}, .newSyntaxError(mismatchedFmt, )
			case ',':
				return .consumeToken(comma, 1, 0), nil
			case ';':
				return .consumeToken(semicolon, 1, 0), nil
			default:
				return .parseFieldName()
			}

Next token can be ListClose or comma
			if  {
				return Token{}, ErrUnexpectedEOF
			}
			switch  := .in[0];  {
			case :
				.popOpenStack()
				return .consumeToken(ListClose, 1, 0), nil
			case ',':
				return .consumeToken(comma, 1, 0), nil
			default:
				return Token{}, .newSyntaxError(unexpectedFmt, )
			}
		}

Next token can be ListClose, MessageStart or Scalar.
		if  {
			return Token{}, ErrUnexpectedEOF
		}
		switch  := .in[0];  {
		case ']':
			.popOpenStack()
			return .consumeToken(ListClose, 1, 0), nil
		case '{', '<':
			.pushOpenStack()
			return .consumeToken(MessageOpen, 1, 0), nil
		default:
			return .parseScalar()
		}

	case ListClose:
		,  := .currentOpenKind()
		switch  {
Top level message. Next token can be EOF, comma, semicolon or Name.
			if  {
				return .consumeToken(EOF, 0, 0), nil
			}
			switch  := .in[0];  {
			case ',':
				return .consumeToken(comma, 1, 0), nil
			case ';':
				return .consumeToken(semicolon, 1, 0), nil
			default:
				return .parseFieldName()
			}

Next token can be MessageClose, comma, semicolon or Name.
			if  {
				return Token{}, ErrUnexpectedEOF
			}
			switch  := .in[0];  {
			case :
				.popOpenStack()
				return .consumeToken(MessageClose, 1, 0), nil
			case otherCloseChar[]:
				return Token{}, .newSyntaxError(mismatchedFmt, )
			case ',':
				return .consumeToken(comma, 1, 0), nil
			case ';':
				return .consumeToken(semicolon, 1, 0), nil
			default:
				return .parseFieldName()
			}

It is not possible to have this case. Let it panic below.
		}

	case comma, semicolon:
		,  := .currentOpenKind()
		switch  {
Top level message. Next token can be EOF or Name.
			if  {
				return .consumeToken(EOF, 0, 0), nil
			}
			return .parseFieldName()

Next token can be MessageClose or Name.
			if  {
				return Token{}, ErrUnexpectedEOF
			}
			switch  := .in[0];  {
			case :
				.popOpenStack()
				return .consumeToken(MessageClose, 1, 0), nil
			case otherCloseChar[]:
				return Token{}, .newSyntaxError(mismatchedFmt, )
			default:
				return .parseFieldName()
			}

		case ListOpen:
It is not be possible to have this case as logic here should not have produced a semicolon Token when inside a list. Let it panic below.
				break
Next token can be MessageOpen or Scalar.
			if  {
				return Token{}, ErrUnexpectedEOF
			}
			switch  := .in[0];  {
			case '{', '<':
				.pushOpenStack()
				return .consumeToken(MessageOpen, 1, 0), nil
			default:
				return .parseScalar()
			}
		}
	}

	,  := .Position(len(.orig) - len(.in))
	panic(fmt.Sprintf("Decoder.parseNext: bug at handling line %d:%d with lastKind=%v", , , ))
}

var otherCloseChar = map[byte]byte{
	'}': '>',
	'>': '}',
}
currentOpenKind indicates whether current position is inside a message, list or top-level message by returning MessageOpen, ListOpen or bof respectively. If the returned kind is either a MessageOpen or ListOpen, it also returns the corresponding closing character.
func ( *Decoder) () (Kind, byte) {
	if len(.openStack) == 0 {
		return bof, 0
	}
	 := .openStack[len(.openStack)-1]
	switch  {
	case '{':
		return MessageOpen, '}'
	case '<':
		return MessageOpen, '>'
	case '[':
		return ListOpen, ']'
	}
	panic(fmt.Sprintf("Decoder: openStack contains invalid byte %s", string()))
}

func ( *Decoder) ( byte) {
	.openStack = append(.openStack, )
}

func ( *Decoder) () {
	.openStack = .openStack[:len(.openStack)-1]
}
parseFieldName parses field name and separator.
func ( *Decoder) () ( Token,  error) {
	defer func() {
		if  == nil && .tryConsumeChar(':') {
			.attrs |= hasSeparator
		}
	}()
Extension or Any type URL.
	if .in[0] == '[' {
		return .parseTypeName()
	}
Identifier.
	if  := parseIdent(.in, false);  > 0 {
		return .consumeToken(Name, , uint8(IdentName)), nil
	}
Field number. Identify if input is a valid number that is not negative and is decimal integer within 32-bit range.
	if  := parseNumber(.in); .size > 0 {
		if !.neg && .kind == numDec {
			if ,  := strconv.ParseInt(string(.in[:.size]), 10, 32);  == nil {
				return .consumeToken(Name, .size, uint8(FieldNumber)), nil
			}
		}
		return Token{}, .newSyntaxError("invalid field number: %s", .in[:.size])
	}

	return Token{}, .newSyntaxError("invalid field name: %s", errRegexp.Find(.in))
}
parseTypeName parses Any type URL or extension field name. The name is enclosed in [ and ] characters. The C++ parser does not handle many legal URL strings. This implementation is more liberal and allows for the pattern ^[-_a-zA-Z0-9]+([./][-_a-zA-Z0-9]+)*`). Whitespaces and comments are allowed in between [ ], '.', '/' and the sub names.
func ( *Decoder) () (Token, error) {
Use alias s to advance first in order to use d.in for error handling. Caller already checks for [ as first character.
	 := consume(.in[1:], 0)
	if len() == 0 {
		return Token{}, ErrUnexpectedEOF
	}

	var  []byte
	for len() > 0 && isTypeNameChar([0]) {
		 = append(, [0])
		 = [1:]
	}
	 = consume(, 0)

	var  bool
	for len() > 0 && ! {
		switch {
		case [0] == ']':
			 = [1:]
			 = true

		case [0] == '/', [0] == '.':
			if len() > 0 && ([len()-1] == '/' || [len()-1] == '.') {
				return Token{}, .newSyntaxError("invalid type URL/extension field name: %s",
					.orig[:len(.orig)-len()+1])
			}
			 = append(, [0])
			 = [1:]
			 = consume(, 0)
			for len() > 0 && isTypeNameChar([0]) {
				 = append(, [0])
				 = [1:]
			}
			 = consume(, 0)

		default:
			return Token{}, .newSyntaxError(
				"invalid type URL/extension field name: %s", .orig[:len(.orig)-len()+1])
		}
	}

	if ! {
		return Token{}, ErrUnexpectedEOF
	}
First character cannot be '.'. Last character cannot be '.' or '/'.
	 := len()
	if  == 0 || [0] == '.' || [-1] == '.' || [-1] == '/' {
		return Token{}, .newSyntaxError("invalid type URL/extension field name: %s",
			.orig[:len(.orig)-len()])
	}

	.in = 
	 := len(.orig) - len(.in)
	.consume(0)

	return Token{
		kind:  Name,
		attrs: uint8(TypeName),
		pos:   ,
		raw:   .orig[:],
		str:   string(),
	}, nil
}

func ( byte) bool {
	return ( == '-' ||  == '_' ||
		('0' <=  &&  <= '9') ||
		('a' <=  &&  <= 'z') ||
		('A' <=  &&  <= 'Z'))
}

func ( byte) bool {
	switch  {
	case ' ', '\n', '\r', '\t':
		return true
	default:
		return false
	}
}
parseIdent parses an unquoted proto identifier and returns size. If allowNeg is true, it allows '-' to be the first character in the identifier. This is used when parsing literal values like -infinity, etc. Regular expression matches an identifier: `^[_a-zA-Z][_a-zA-Z0-9]*`
func ( []byte,  bool) int {
	var  int

	 := 
	if len() == 0 {
		return 0
	}

	if  && [0] == '-' {
		 = [1:]
		++
		if len() == 0 {
			return 0
		}
	}

	switch {
	case [0] == '_',
		'a' <= [0] && [0] <= 'z',
		'A' <= [0] && [0] <= 'Z':
		 = [1:]
		++
	default:
		return 0
	}

	for len() > 0 && ([0] == '_' ||
		'a' <= [0] && [0] <= 'z' ||
		'A' <= [0] && [0] <= 'Z' ||
		'0' <= [0] && [0] <= '9') {
		 = [1:]
		++
	}

	if len() > 0 && !isDelim([0]) {
		return 0
	}

	return 
}
parseScalar parses for a string, literal or number value.
func ( *Decoder) () (Token, error) {
	if .in[0] == '"' || .in[0] == '\'' {
		return .parseStringValue()
	}

	if ,  := .parseLiteralValue();  {
		return , nil
	}

	if ,  := .parseNumberValue();  {
		return , nil
	}

	return Token{}, .newSyntaxError("invalid scalar value: %s", errRegexp.Find(.in))
}
parseLiteralValue parses a literal value. A literal value is used for bools, special floats and enums. This function simply identifies that the field value is a literal.
func ( *Decoder) () (Token, bool) {
	 := parseIdent(.in, true)
	if  == 0 {
		return Token{}, false
	}
	return .consumeToken(Scalar, , literalValue), true
}
consumeToken constructs a Token for given Kind from d.in and consumes given size-length from it.
Important to compute raw and pos before consuming.
	 := Token{
		kind:  ,
		attrs: ,
		pos:   len(.orig) - len(.in),
		raw:   .in[:],
	}
	.consume()
	return 
}
newSyntaxError returns a syntax error with line and column information for current position.
func ( *Decoder) ( string,  ...interface{}) error {
	 := errors.New(, ...)
	,  := .Position(len(.orig) - len(.in))
	return errors.New("syntax error (line %d:%d): %v", , , )
}
Position returns line and column number of given index of the original input. It will panic if index is out of range.
func ( *Decoder) ( int) ( int,  int) {
	 := .orig[:]
	 = bytes.Count(, []byte("\n")) + 1
	if  := bytes.LastIndexByte(, '\n');  >= 0 {
		 = [+1:]
	}
	 = utf8.RuneCount() + 1 // ignore multi-rune characters
	return , 
}

func ( *Decoder) ( byte) bool {
	if len(.in) > 0 && .in[0] ==  {
		.consume(1)
		return true
	}
	return false
}
consume consumes n bytes of input and any subsequent whitespace or comments.
func ( *Decoder) ( int) {
	.in = consume(.in, )
	return
}
consume consumes n bytes of input and any subsequent whitespace or comments.
func ( []byte,  int) []byte {
	 = [:]
	for len() > 0 {
		switch [0] {
		case ' ', '\n', '\r', '\t':
			 = [1:]
		case '#':
			if  := bytes.IndexByte(, '\n');  >= 0 {
				 = [+len("\n"):]
			} else {
				 = nil
			}
		default:
			return 
		}
	}
	return 
}
Any sequence that looks like a non-delimiter (for error reporting).
var errRegexp = regexp.MustCompile(`^([-+._a-zA-Z0-9\/]+|.)`)
isDelim returns true if given byte is a delimiter character.
func ( byte) bool {
	return !( == '-' ||  == '+' ||  == '.' ||  == '_' ||
		('a' <=  &&  <= 'z') ||
		('A' <=  &&  <= 'Z') ||
		('0' <=  &&  <= '9'))