...

Source file src/github.com/launchdarkly/go-jsonstream/v3/jreader/token_reader_easyjson.go

Documentation: github.com/launchdarkly/go-jsonstream/v3/jreader

     1  //go:build launchdarkly_easyjson
     2  // +build launchdarkly_easyjson
     3  
     4  package jreader
     5  
     6  // This file defines the easyjson-based implementation of the low-level JSON tokenizer, which is used instead
     7  // of token_reader_default.go if the launchdarkly_easyjson build tag is enabled.
     8  //
     9  // For the contract governing the behavior of the exported methods in this type, see the comments on the
    10  // corresponding methods in token_reader_default.go.
    11  
    12  import (
    13  	"fmt"
    14  	"strings"
    15  
    16  	"github.com/mailru/easyjson/jlexer"
    17  )
    18  
    19  type tokenReader struct {
    20  	// We might be initialized either with a pointer to an existing Lexer, in which case we'll use that.
    21  	pLexer *jlexer.Lexer
    22  	// Or, we might be initialized with a byte slice so we must create our own Lexer. We'd like to avoid
    23  	// allocating that on the heap, so we'll store it here.
    24  	inlineLexer          jlexer.Lexer
    25  	posBeforeCallingNull int
    26  	posAfterCallingNull  int
    27  	posBeforeValue       int
    28  }
    29  
    30  func newTokenReader(data []byte) tokenReader {
    31  	return tokenReader{inlineLexer: jlexer.Lexer{Data: data}}
    32  }
    33  
    34  func newTokenReaderFromEasyjsonLexer(lexer *jlexer.Lexer) tokenReader {
    35  	return tokenReader{pLexer: lexer}
    36  }
    37  
    38  func (tr *tokenReader) EOF() bool {
    39  	pLexer := tr.pLexer
    40  	if pLexer == nil {
    41  		pLexer = &tr.inlineLexer
    42  	}
    43  	if pLexer.Error() != nil {
    44  		return true
    45  	}
    46  	pLexer.Consumed()
    47  	return pLexer.Error() == nil
    48  }
    49  
    50  func (tr *tokenReader) LastPos() int {
    51  	if tr.pLexer == nil {
    52  		return tr.inlineLexer.GetPos()
    53  	}
    54  	return tr.pLexer.GetPos()
    55  }
    56  
    57  func (tr *tokenReader) Null() (bool, error) {
    58  	pLexer := tr.pLexer
    59  	if pLexer == nil {
    60  		pLexer = &tr.inlineLexer
    61  	}
    62  	// The "posBefore/posAfter" stuff is because it's not possible to rewind a Lexer. If we call Null(),
    63  	// and the value isn't null, the Lexer will cache that token for the next read, but GetPos() will
    64  	// still be pointing *after* the token and that'll screw up our error reporting.
    65  	tr.posBeforeCallingNull = pLexer.GetPos()
    66  	if pLexer.IsNull() {
    67  		// Lexer.IsNull can return a misleading true value if there's a parsing error
    68  		if err := pLexer.Error(); err != nil {
    69  			return false, tr.translateLexerError()
    70  		}
    71  		pLexer.Null()
    72  		return true, nil
    73  	}
    74  	tr.posAfterCallingNull = pLexer.GetPos()
    75  	return false, tr.translateLexerError()
    76  }
    77  
    78  func (tr *tokenReader) Bool() (bool, error) {
    79  	pLexer := tr.pLexer
    80  	if pLexer == nil {
    81  		pLexer = &tr.inlineLexer
    82  	}
    83  	tr.markPosBeforeValue()
    84  	val := pLexer.Bool()
    85  	if pLexer.Error() == nil {
    86  		return val, nil
    87  	}
    88  	return false, tr.translateLexerErrorWithExpectedType(BoolValue)
    89  }
    90  
    91  func (tr *tokenReader) Number() (float64, error) {
    92  	pLexer := tr.pLexer
    93  	if pLexer == nil {
    94  		pLexer = &tr.inlineLexer
    95  	}
    96  	tr.markPosBeforeValue()
    97  	val := pLexer.Float64()
    98  	if pLexer.Error() == nil {
    99  		return val, nil
   100  	}
   101  	return 0, tr.translateLexerErrorWithExpectedType(NumberValue)
   102  }
   103  
   104  func (tr *tokenReader) String() (string, error) {
   105  	pLexer := tr.pLexer
   106  	if pLexer == nil {
   107  		pLexer = &tr.inlineLexer
   108  	}
   109  	tr.markPosBeforeValue()
   110  	val := pLexer.String()
   111  	if pLexer.Error() == nil {
   112  		return val, nil
   113  	}
   114  	return "", tr.translateLexerErrorWithExpectedType(StringValue)
   115  }
   116  
   117  func (tr *tokenReader) PropertyName() ([]byte, error) {
   118  	pLexer := tr.pLexer
   119  	if pLexer == nil {
   120  		pLexer = &tr.inlineLexer
   121  	}
   122  	val := pLexer.UnsafeBytes()
   123  	if err := pLexer.Error(); err != nil {
   124  		return nil, tr.translateLexerError()
   125  	}
   126  	pLexer.WantColon()
   127  	pLexer.FetchToken()
   128  	return val, tr.translateLexerError()
   129  }
   130  
   131  func (tr *tokenReader) Delimiter(delim byte) (bool, error) {
   132  	pLexer := tr.pLexer
   133  	if pLexer == nil {
   134  		pLexer = &tr.inlineLexer
   135  	}
   136  	if err := pLexer.Error(); err != nil {
   137  		return false, tr.translateLexerError()
   138  	}
   139  	found := false
   140  	if pLexer.IsDelim(byte(delim)) {
   141  		pLexer.Delim(delim)
   142  		found = true
   143  	}
   144  	// IsDelim can return a misleading true value if there's a parsing error
   145  	if err := pLexer.Error(); err != nil {
   146  		return false, tr.translateLexerError()
   147  	}
   148  	return found, nil
   149  }
   150  
   151  func (tr *tokenReader) EndDelimiterOrComma(delim byte) (bool, error) {
   152  	pLexer := tr.pLexer
   153  	if pLexer == nil {
   154  		pLexer = &tr.inlineLexer
   155  	}
   156  	if pLexer.Error() != nil {
   157  		return false, tr.translateLexerError()
   158  	}
   159  	pLexer.WantComma()
   160  	if pLexer.IsDelim(delim) {
   161  		pLexer.Delim(delim)
   162  		return true, nil
   163  	}
   164  	return false, tr.translateLexerError()
   165  }
   166  
   167  func (tr *tokenReader) Any() (AnyValue, error) {
   168  	pLexer := tr.pLexer
   169  	if pLexer == nil {
   170  		pLexer = &tr.inlineLexer
   171  	}
   172  	value, err := readAnyValue(pLexer)
   173  	if err != nil {
   174  		return AnyValue{}, tr.translateLexerError()
   175  	}
   176  	return value, nil
   177  }
   178  
   179  func (tr *tokenReader) lexerError() error {
   180  	if tr.pLexer == nil {
   181  		return tr.inlineLexer.Error()
   182  	}
   183  	return tr.pLexer.Error()
   184  }
   185  
   186  func readAnyValue(lexer *jlexer.Lexer) (AnyValue, error) {
   187  	if lexer.IsDelim('[') {
   188  		// IsDelim can return a misleading true value if there's a parsing error
   189  		if err := lexer.Error(); err != nil {
   190  			return AnyValue{}, err
   191  		}
   192  		lexer.Delim('[')
   193  		return AnyValue{Kind: ArrayValue}, nil
   194  	}
   195  	if lexer.IsDelim('{') {
   196  		if err := lexer.Error(); err != nil {
   197  			return AnyValue{}, err
   198  		}
   199  		lexer.Delim('{')
   200  		return AnyValue{Kind: ObjectValue}, nil
   201  	}
   202  	intf := lexer.Interface()
   203  	if err := lexer.Error(); err != nil {
   204  		return AnyValue{}, err
   205  	}
   206  	if intf == nil {
   207  		return AnyValue{Kind: NullValue}, nil
   208  	}
   209  	switch v := intf.(type) {
   210  	case bool:
   211  		return AnyValue{Kind: BoolValue, Bool: v}, nil
   212  	case int:
   213  		return AnyValue{Kind: NumberValue, Number: float64(v)}, nil
   214  	case float64:
   215  		return AnyValue{Kind: NumberValue, Number: v}, nil
   216  	case string:
   217  		return AnyValue{Kind: StringValue, String: v}, nil
   218  	}
   219  	return AnyValue{}, fmt.Errorf("Lexer.Interface() returned unrecognized type %T", intf)
   220  }
   221  
   222  func (tr *tokenReader) markPosBeforeValue() {
   223  	pos := tr.LastPos()
   224  	if pos == tr.posAfterCallingNull {
   225  		pos = tr.posBeforeCallingNull
   226  	}
   227  }
   228  
   229  func (tr *tokenReader) translateLexerError() error {
   230  	return tr.translateLexerErrorWithExpectedType(-1)
   231  }
   232  
   233  func (tr *tokenReader) translateLexerErrorWithExpectedType(expectedType ValueKind) error {
   234  	pLexer := tr.pLexer
   235  	if pLexer == nil {
   236  		pLexer = &tr.inlineLexer
   237  	}
   238  	originalError := pLexer.Error()
   239  	if originalError == nil {
   240  		return nil
   241  	}
   242  	le, ok := originalError.(*jlexer.LexerError)
   243  	if !ok {
   244  		return originalError
   245  	}
   246  	if strings.HasPrefix(le.Reason, "expected ") && expectedType >= 0 {
   247  		// LexerError is not very useful for determining what the invalid token was, because it tends to
   248  		// leave the Data property empty and put the Offset property *after* the bad token. Fortunately,
   249  		// it's very easy to create a new Lexer to re-parse from where we started.
   250  		tempLexer := jlexer.Lexer{Data: pLexer.Data[tr.posBeforeValue:]}
   251  		value, err := readAnyValue(&tempLexer)
   252  		if err != nil {
   253  			return translateLexerParseError(err)
   254  		}
   255  		return TypeError{Expected: expectedType, Actual: value.Kind, Offset: tr.posBeforeValue}
   256  	}
   257  	return translateLexerParseError(originalError)
   258  }
   259  
   260  func translateLexerParseError(err error) error {
   261  	if le, ok := err.(*jlexer.LexerError); ok {
   262  		return SyntaxError{Message: strings.TrimPrefix(le.Reason, "parse error: "), Offset: le.Offset}
   263  	}
   264  	return err
   265  }
   266  

View as plain text