// 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.
type Decoder struct {
	// lastCall is last method called, either readCall or peekCall.
	// Initial value is readCall.
	lastCall call

	// lastToken contains the last read token.
	lastToken Token

	// lastErr contains the last read error.
	lastErr 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.
	openStack []byte

	// orig is used in reporting line and column.
	orig []byte
	// 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.
var ErrUnexpectedEOF = errors.New("%v", io.ErrUnexpectedEOF)

// 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.
func ( *Decoder) ( Kind) (Token, error) {
	// Trim leading spaces.
	.consume(0)
	 := false
	if len(.in) == 0 {
		 = true
	}

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

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

	case Name:
		// 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  {
		case bof:
			// 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()
			}

		case MessageOpen:
			// 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()
			}

		case ListOpen:
			// 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, )
			}
		}

	case MessageOpen:
		// 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  {
		case bof:
			// 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()
			}

		case MessageOpen:
			// 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()
			}

		case ListOpen:
			// 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, )
			}
		}

	case ListOpen:
		// 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  {
		case bof:
			// 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()
			}

		case MessageOpen:
			// 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()
			}

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

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

		case MessageOpen:
			// 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:
			if  == semicolon {
				// 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 %c", ))
}

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", errId(.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) {
	 := len(.orig) - len(.in)
	// 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", errId(.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.
func ( *Decoder) ( Kind,  int,  uint8) Token {
	// 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 
}

// errId extracts a byte sequence that looks like an invalid ID
// (for the purposes of error reporting).
func ( []byte) []byte {
	const  = 32
	for  := 0;  < len(); {
		if  >  {
			return append([::], "…"...)
		}
		,  := utf8.DecodeRune([:])
		if  > utf8.RuneSelf || ( != '/' && isDelim(byte())) {
			if  == 0 {
				// Either the first byte is invalid UTF-8 or a
				// delimiter, or the first rune is non-ASCII.
				// Return it as-is.
				 = 
			}
			return [::]
		}
		 += 
	}
	// No delimiter found.
	return 
}

// isDelim returns true if given byte is a delimiter character.
func ( byte) bool {
	return !( == '-' ||  == '+' ||  == '.' ||  == '_' ||
		('a' <=  &&  <= 'z') ||
		('A' <=  &&  <= 'Z') ||
		('0' <=  &&  <= '9'))
}