...

Source file src/google.golang.org/protobuf/internal/encoding/json/decode_token.go

Documentation: google.golang.org/protobuf/internal/encoding/json

     1  // Copyright 2019 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 json
     6  
     7  import (
     8  	"bytes"
     9  	"fmt"
    10  	"strconv"
    11  )
    12  
    13  // Kind represents a token kind expressible in the JSON format.
    14  type Kind uint16
    15  
    16  const (
    17  	Invalid Kind = (1 << iota) / 2
    18  	EOF
    19  	Null
    20  	Bool
    21  	Number
    22  	String
    23  	Name
    24  	ObjectOpen
    25  	ObjectClose
    26  	ArrayOpen
    27  	ArrayClose
    28  
    29  	// comma is only for parsing in between tokens and
    30  	// does not need to be exported.
    31  	comma
    32  )
    33  
    34  func (k Kind) String() string {
    35  	switch k {
    36  	case EOF:
    37  		return "eof"
    38  	case Null:
    39  		return "null"
    40  	case Bool:
    41  		return "bool"
    42  	case Number:
    43  		return "number"
    44  	case String:
    45  		return "string"
    46  	case ObjectOpen:
    47  		return "{"
    48  	case ObjectClose:
    49  		return "}"
    50  	case Name:
    51  		return "name"
    52  	case ArrayOpen:
    53  		return "["
    54  	case ArrayClose:
    55  		return "]"
    56  	case comma:
    57  		return ","
    58  	}
    59  	return "<invalid>"
    60  }
    61  
    62  // Token provides a parsed token kind and value.
    63  //
    64  // Values are provided by the difference accessor methods. The accessor methods
    65  // Name, Bool, and ParsedString will panic if called on the wrong kind. There
    66  // are different accessor methods for the Number kind for converting to the
    67  // appropriate Go numeric type and those methods have the ok return value.
    68  type Token struct {
    69  	// Token kind.
    70  	kind Kind
    71  	// pos provides the position of the token in the original input.
    72  	pos int
    73  	// raw bytes of the serialized token.
    74  	// This is a subslice into the original input.
    75  	raw []byte
    76  	// boo is parsed boolean value.
    77  	boo bool
    78  	// str is parsed string value.
    79  	str string
    80  }
    81  
    82  // Kind returns the token kind.
    83  func (t Token) Kind() Kind {
    84  	return t.kind
    85  }
    86  
    87  // RawString returns the read value in string.
    88  func (t Token) RawString() string {
    89  	return string(t.raw)
    90  }
    91  
    92  // Pos returns the token position from the input.
    93  func (t Token) Pos() int {
    94  	return t.pos
    95  }
    96  
    97  // Name returns the object name if token is Name, else it panics.
    98  func (t Token) Name() string {
    99  	if t.kind == Name {
   100  		return t.str
   101  	}
   102  	panic(fmt.Sprintf("Token is not a Name: %v", t.RawString()))
   103  }
   104  
   105  // Bool returns the bool value if token kind is Bool, else it panics.
   106  func (t Token) Bool() bool {
   107  	if t.kind == Bool {
   108  		return t.boo
   109  	}
   110  	panic(fmt.Sprintf("Token is not a Bool: %v", t.RawString()))
   111  }
   112  
   113  // ParsedString returns the string value for a JSON string token or the read
   114  // value in string if token is not a string.
   115  func (t Token) ParsedString() string {
   116  	if t.kind == String {
   117  		return t.str
   118  	}
   119  	panic(fmt.Sprintf("Token is not a String: %v", t.RawString()))
   120  }
   121  
   122  // Float returns the floating-point number if token kind is Number.
   123  //
   124  // The floating-point precision is specified by the bitSize parameter: 32 for
   125  // float32 or 64 for float64. If bitSize=32, the result still has type float64,
   126  // but it will be convertible to float32 without changing its value. It will
   127  // return false if the number exceeds the floating point limits for given
   128  // bitSize.
   129  func (t Token) Float(bitSize int) (float64, bool) {
   130  	if t.kind != Number {
   131  		return 0, false
   132  	}
   133  	f, err := strconv.ParseFloat(t.RawString(), bitSize)
   134  	if err != nil {
   135  		return 0, false
   136  	}
   137  	return f, true
   138  }
   139  
   140  // Int returns the signed integer number if token is Number.
   141  //
   142  // The given bitSize specifies the integer type that the result must fit into.
   143  // It returns false if the number is not an integer value or if the result
   144  // exceeds the limits for given bitSize.
   145  func (t Token) Int(bitSize int) (int64, bool) {
   146  	s, ok := t.getIntStr()
   147  	if !ok {
   148  		return 0, false
   149  	}
   150  	n, err := strconv.ParseInt(s, 10, bitSize)
   151  	if err != nil {
   152  		return 0, false
   153  	}
   154  	return n, true
   155  }
   156  
   157  // Uint returns the signed integer number if token is Number.
   158  //
   159  // The given bitSize specifies the unsigned integer type that the result must
   160  // fit into. It returns false if the number is not an unsigned integer value
   161  // or if the result exceeds the limits for given bitSize.
   162  func (t Token) Uint(bitSize int) (uint64, bool) {
   163  	s, ok := t.getIntStr()
   164  	if !ok {
   165  		return 0, false
   166  	}
   167  	n, err := strconv.ParseUint(s, 10, bitSize)
   168  	if err != nil {
   169  		return 0, false
   170  	}
   171  	return n, true
   172  }
   173  
   174  func (t Token) getIntStr() (string, bool) {
   175  	if t.kind != Number {
   176  		return "", false
   177  	}
   178  	parts, ok := parseNumberParts(t.raw)
   179  	if !ok {
   180  		return "", false
   181  	}
   182  	return normalizeToIntString(parts)
   183  }
   184  
   185  // TokenEquals returns true if given Tokens are equal, else false.
   186  func TokenEquals(x, y Token) bool {
   187  	return x.kind == y.kind &&
   188  		x.pos == y.pos &&
   189  		bytes.Equal(x.raw, y.raw) &&
   190  		x.boo == y.boo &&
   191  		x.str == y.str
   192  }
   193  

View as plain text