github.com/jhump/protoreflect@v1.16.0/desc/protoparse/ast/values.go (about)

     1  package ast
     2  
     3  import (
     4  	"fmt"
     5  	"math"
     6  	"strings"
     7  )
     8  
     9  // ValueNode is an AST node that represents a literal value.
    10  //
    11  // It also includes references (e.g. IdentifierValueNode), which can be
    12  // used as values in some contexts, such as describing the default value
    13  // for a field, which can refer to an enum value.
    14  //
    15  // This also allows NoSourceNode to be used in place of a real value node
    16  // for some usages.
    17  type ValueNode interface {
    18  	Node
    19  	// Value returns a Go representation of the value. For scalars, this
    20  	// will be a string, int64, uint64, float64, or bool. This could also
    21  	// be an Identifier (e.g. IdentValueNodes). It can also be a composite
    22  	// literal:
    23  	//   * For array literals, the type returned will be []ValueNode
    24  	//   * For message literals, the type returned will be []*MessageFieldNode
    25  	Value() interface{}
    26  }
    27  
    28  var _ ValueNode = (*IdentNode)(nil)
    29  var _ ValueNode = (*CompoundIdentNode)(nil)
    30  var _ ValueNode = (*StringLiteralNode)(nil)
    31  var _ ValueNode = (*CompoundStringLiteralNode)(nil)
    32  var _ ValueNode = (*UintLiteralNode)(nil)
    33  var _ ValueNode = (*PositiveUintLiteralNode)(nil)
    34  var _ ValueNode = (*NegativeIntLiteralNode)(nil)
    35  var _ ValueNode = (*FloatLiteralNode)(nil)
    36  var _ ValueNode = (*SpecialFloatLiteralNode)(nil)
    37  var _ ValueNode = (*SignedFloatLiteralNode)(nil)
    38  var _ ValueNode = (*BoolLiteralNode)(nil)
    39  var _ ValueNode = (*ArrayLiteralNode)(nil)
    40  var _ ValueNode = (*MessageLiteralNode)(nil)
    41  var _ ValueNode = NoSourceNode{}
    42  
    43  // StringValueNode is an AST node that represents a string literal.
    44  // Such a node can be a single literal (*StringLiteralNode) or a
    45  // concatenation of multiple literals (*CompoundStringLiteralNode).
    46  type StringValueNode interface {
    47  	ValueNode
    48  	AsString() string
    49  }
    50  
    51  var _ StringValueNode = (*StringLiteralNode)(nil)
    52  var _ StringValueNode = (*CompoundStringLiteralNode)(nil)
    53  
    54  // StringLiteralNode represents a simple string literal. Example:
    55  //
    56  //	"proto2"
    57  type StringLiteralNode struct {
    58  	terminalNode
    59  	// Val is the actual string value that the literal indicates.
    60  	Val string
    61  }
    62  
    63  // NewStringLiteralNode creates a new *StringLiteralNode with the given val.
    64  func NewStringLiteralNode(val string, info TokenInfo) *StringLiteralNode {
    65  	return &StringLiteralNode{
    66  		terminalNode: info.asTerminalNode(),
    67  		Val:          val,
    68  	}
    69  }
    70  
    71  func (n *StringLiteralNode) Value() interface{} {
    72  	return n.AsString()
    73  }
    74  
    75  func (n *StringLiteralNode) AsString() string {
    76  	return n.Val
    77  }
    78  
    79  // CompoundStringLiteralNode represents a compound string literal, which is
    80  // the concatenaton of adjacent string literals. Example:
    81  //
    82  //	"this "  "is"   " all one "   "string"
    83  type CompoundStringLiteralNode struct {
    84  	compositeNode
    85  	Val string
    86  }
    87  
    88  // NewCompoundLiteralStringNode creates a new *CompoundStringLiteralNode that
    89  // consists of the given string components. The components argument may not be
    90  // empty.
    91  func NewCompoundLiteralStringNode(components ...*StringLiteralNode) *CompoundStringLiteralNode {
    92  	if len(components) == 0 {
    93  		panic("must have at least one component")
    94  	}
    95  	children := make([]Node, len(components))
    96  	var b strings.Builder
    97  	for i, comp := range components {
    98  		children[i] = comp
    99  		b.WriteString(comp.Val)
   100  	}
   101  	return &CompoundStringLiteralNode{
   102  		compositeNode: compositeNode{
   103  			children: children,
   104  		},
   105  		Val: b.String(),
   106  	}
   107  }
   108  
   109  func (n *CompoundStringLiteralNode) Value() interface{} {
   110  	return n.AsString()
   111  }
   112  
   113  func (n *CompoundStringLiteralNode) AsString() string {
   114  	return n.Val
   115  }
   116  
   117  // IntValueNode is an AST node that represents an integer literal. If
   118  // an integer literal is too large for an int64 (or uint64 for
   119  // positive literals), it is represented instead by a FloatValueNode.
   120  type IntValueNode interface {
   121  	ValueNode
   122  	AsInt64() (int64, bool)
   123  	AsUint64() (uint64, bool)
   124  }
   125  
   126  // AsInt32 range checks the given int value and returns its value is
   127  // in the range or 0, false if it is outside the range.
   128  func AsInt32(n IntValueNode, min, max int32) (int32, bool) {
   129  	i, ok := n.AsInt64()
   130  	if !ok {
   131  		return 0, false
   132  	}
   133  	if i < int64(min) || i > int64(max) {
   134  		return 0, false
   135  	}
   136  	return int32(i), true
   137  }
   138  
   139  var _ IntValueNode = (*UintLiteralNode)(nil)
   140  var _ IntValueNode = (*PositiveUintLiteralNode)(nil)
   141  var _ IntValueNode = (*NegativeIntLiteralNode)(nil)
   142  
   143  // UintLiteralNode represents a simple integer literal with no sign character.
   144  type UintLiteralNode struct {
   145  	terminalNode
   146  	// Val is the numeric value indicated by the literal
   147  	Val uint64
   148  }
   149  
   150  // NewUintLiteralNode creates a new *UintLiteralNode with the given val.
   151  func NewUintLiteralNode(val uint64, info TokenInfo) *UintLiteralNode {
   152  	return &UintLiteralNode{
   153  		terminalNode: info.asTerminalNode(),
   154  		Val:          val,
   155  	}
   156  }
   157  
   158  func (n *UintLiteralNode) Value() interface{} {
   159  	return n.Val
   160  }
   161  
   162  func (n *UintLiteralNode) AsInt64() (int64, bool) {
   163  	if n.Val > math.MaxInt64 {
   164  		return 0, false
   165  	}
   166  	return int64(n.Val), true
   167  }
   168  
   169  func (n *UintLiteralNode) AsUint64() (uint64, bool) {
   170  	return n.Val, true
   171  }
   172  
   173  func (n *UintLiteralNode) AsFloat() float64 {
   174  	return float64(n.Val)
   175  }
   176  
   177  // PositiveUintLiteralNode represents an integer literal with a positive (+) sign.
   178  //
   179  // Deprecated: A valid AST will not contain a node of this type. The Protobuf
   180  // language does not actually allow a numeric literal to have a leading "+"
   181  // positive sign.
   182  type PositiveUintLiteralNode struct {
   183  	compositeNode
   184  	Plus *RuneNode
   185  	Uint *UintLiteralNode
   186  	Val  uint64
   187  }
   188  
   189  // NewPositiveUintLiteralNode creates a new *PositiveUintLiteralNode. Both
   190  // arguments must be non-nil.
   191  //
   192  // Deprecated: The ast.PositiveUintLiteralNode node type should not be used.
   193  func NewPositiveUintLiteralNode(sign *RuneNode, i *UintLiteralNode) *PositiveUintLiteralNode {
   194  	if sign == nil {
   195  		panic("sign is nil")
   196  	}
   197  	if i == nil {
   198  		panic("i is nil")
   199  	}
   200  	children := []Node{sign, i}
   201  	return &PositiveUintLiteralNode{
   202  		compositeNode: compositeNode{
   203  			children: children,
   204  		},
   205  		Plus: sign,
   206  		Uint: i,
   207  		Val:  i.Val,
   208  	}
   209  }
   210  
   211  func (n *PositiveUintLiteralNode) Value() interface{} {
   212  	return n.Val
   213  }
   214  
   215  func (n *PositiveUintLiteralNode) AsInt64() (int64, bool) {
   216  	if n.Val > math.MaxInt64 {
   217  		return 0, false
   218  	}
   219  	return int64(n.Val), true
   220  }
   221  
   222  func (n *PositiveUintLiteralNode) AsUint64() (uint64, bool) {
   223  	return n.Val, true
   224  }
   225  
   226  // NegativeIntLiteralNode represents an integer literal with a negative (-) sign.
   227  type NegativeIntLiteralNode struct {
   228  	compositeNode
   229  	Minus *RuneNode
   230  	Uint  *UintLiteralNode
   231  	Val   int64
   232  }
   233  
   234  // NewNegativeIntLiteralNode creates a new *NegativeIntLiteralNode. Both
   235  // arguments must be non-nil.
   236  func NewNegativeIntLiteralNode(sign *RuneNode, i *UintLiteralNode) *NegativeIntLiteralNode {
   237  	if sign == nil {
   238  		panic("sign is nil")
   239  	}
   240  	if i == nil {
   241  		panic("i is nil")
   242  	}
   243  	children := []Node{sign, i}
   244  	return &NegativeIntLiteralNode{
   245  		compositeNode: compositeNode{
   246  			children: children,
   247  		},
   248  		Minus: sign,
   249  		Uint:  i,
   250  		Val:   -int64(i.Val),
   251  	}
   252  }
   253  
   254  func (n *NegativeIntLiteralNode) Value() interface{} {
   255  	return n.Val
   256  }
   257  
   258  func (n *NegativeIntLiteralNode) AsInt64() (int64, bool) {
   259  	return n.Val, true
   260  }
   261  
   262  func (n *NegativeIntLiteralNode) AsUint64() (uint64, bool) {
   263  	if n.Val < 0 {
   264  		return 0, false
   265  	}
   266  	return uint64(n.Val), true
   267  }
   268  
   269  // FloatValueNode is an AST node that represents a numeric literal with
   270  // a floating point, in scientific notation, or too large to fit in an
   271  // int64 or uint64.
   272  type FloatValueNode interface {
   273  	ValueNode
   274  	AsFloat() float64
   275  }
   276  
   277  var _ FloatValueNode = (*FloatLiteralNode)(nil)
   278  var _ FloatValueNode = (*SpecialFloatLiteralNode)(nil)
   279  var _ FloatValueNode = (*UintLiteralNode)(nil)
   280  
   281  // FloatLiteralNode represents a floating point numeric literal.
   282  type FloatLiteralNode struct {
   283  	terminalNode
   284  	// Val is the numeric value indicated by the literal
   285  	Val float64
   286  }
   287  
   288  // NewFloatLiteralNode creates a new *FloatLiteralNode with the given val.
   289  func NewFloatLiteralNode(val float64, info TokenInfo) *FloatLiteralNode {
   290  	return &FloatLiteralNode{
   291  		terminalNode: info.asTerminalNode(),
   292  		Val:          val,
   293  	}
   294  }
   295  
   296  func (n *FloatLiteralNode) Value() interface{} {
   297  	return n.AsFloat()
   298  }
   299  
   300  func (n *FloatLiteralNode) AsFloat() float64 {
   301  	return n.Val
   302  }
   303  
   304  // SpecialFloatLiteralNode represents a special floating point numeric literal
   305  // for "inf" and "nan" values.
   306  type SpecialFloatLiteralNode struct {
   307  	*KeywordNode
   308  	Val float64
   309  }
   310  
   311  // NewSpecialFloatLiteralNode returns a new *SpecialFloatLiteralNode for the
   312  // given keyword, which must be "inf" or "nan".
   313  func NewSpecialFloatLiteralNode(name *KeywordNode) *SpecialFloatLiteralNode {
   314  	var f float64
   315  	if name.Val == "inf" {
   316  		f = math.Inf(1)
   317  	} else {
   318  		f = math.NaN()
   319  	}
   320  	return &SpecialFloatLiteralNode{
   321  		KeywordNode: name,
   322  		Val:         f,
   323  	}
   324  }
   325  
   326  func (n *SpecialFloatLiteralNode) Value() interface{} {
   327  	return n.AsFloat()
   328  }
   329  
   330  func (n *SpecialFloatLiteralNode) AsFloat() float64 {
   331  	return n.Val
   332  }
   333  
   334  // SignedFloatLiteralNode represents a signed floating point number.
   335  type SignedFloatLiteralNode struct {
   336  	compositeNode
   337  	Sign  *RuneNode
   338  	Float FloatValueNode
   339  	Val   float64
   340  }
   341  
   342  // NewSignedFloatLiteralNode creates a new *SignedFloatLiteralNode. Both
   343  // arguments must be non-nil.
   344  func NewSignedFloatLiteralNode(sign *RuneNode, f FloatValueNode) *SignedFloatLiteralNode {
   345  	if sign == nil {
   346  		panic("sign is nil")
   347  	}
   348  	if f == nil {
   349  		panic("f is nil")
   350  	}
   351  	children := []Node{sign, f}
   352  	val := f.AsFloat()
   353  	if sign.Rune == '-' {
   354  		val = -val
   355  	}
   356  	return &SignedFloatLiteralNode{
   357  		compositeNode: compositeNode{
   358  			children: children,
   359  		},
   360  		Sign:  sign,
   361  		Float: f,
   362  		Val:   val,
   363  	}
   364  }
   365  
   366  func (n *SignedFloatLiteralNode) Value() interface{} {
   367  	return n.Val
   368  }
   369  
   370  func (n *SignedFloatLiteralNode) AsFloat() float64 {
   371  	return n.Val
   372  }
   373  
   374  // BoolLiteralNode represents a boolean literal.
   375  //
   376  // Deprecated: The AST uses IdentNode for boolean literals, where the
   377  // identifier value is "true" or "false". This is required because an
   378  // identifier "true" is not necessarily a boolean value as it could also
   379  // be an enum value named "true" (ditto for "false").
   380  type BoolLiteralNode struct {
   381  	*KeywordNode
   382  	Val bool
   383  }
   384  
   385  // NewBoolLiteralNode returns a new *BoolLiteralNode for the given keyword,
   386  // which must be "true" or "false".
   387  func NewBoolLiteralNode(name *KeywordNode) *BoolLiteralNode {
   388  	return &BoolLiteralNode{
   389  		KeywordNode: name,
   390  		Val:         name.Val == "true",
   391  	}
   392  }
   393  
   394  func (n *BoolLiteralNode) Value() interface{} {
   395  	return n.Val
   396  }
   397  
   398  // ArrayLiteralNode represents an array literal, which is only allowed inside of
   399  // a MessageLiteralNode, to indicate values for a repeated field. Example:
   400  //
   401  //	["foo", "bar", "baz"]
   402  type ArrayLiteralNode struct {
   403  	compositeNode
   404  	OpenBracket *RuneNode
   405  	Elements    []ValueNode
   406  	// Commas represent the separating ',' characters between elements. The
   407  	// length of this slice must be exactly len(Elements)-1, with each item
   408  	// in Elements having a corresponding item in this slice *except the last*
   409  	// (since a trailing comma is not allowed).
   410  	Commas       []*RuneNode
   411  	CloseBracket *RuneNode
   412  }
   413  
   414  // NewArrayLiteralNode creates a new *ArrayLiteralNode. The openBracket and
   415  // closeBracket args must be non-nil and represent the "[" and "]" runes that
   416  // surround the array values. The given commas arg must have a length that is
   417  // one less than the length of the vals arg. However, vals may be empty, in
   418  // which case commas must also be empty.
   419  func NewArrayLiteralNode(openBracket *RuneNode, vals []ValueNode, commas []*RuneNode, closeBracket *RuneNode) *ArrayLiteralNode {
   420  	if openBracket == nil {
   421  		panic("openBracket is nil")
   422  	}
   423  	if closeBracket == nil {
   424  		panic("closeBracket is nil")
   425  	}
   426  	if len(vals) == 0 && len(commas) != 0 {
   427  		panic("vals is empty but commas is not")
   428  	}
   429  	if len(vals) > 0 && len(commas) != len(vals)-1 {
   430  		panic(fmt.Sprintf("%d vals requires %d commas, not %d", len(vals), len(vals)-1, len(commas)))
   431  	}
   432  	children := make([]Node, 0, len(vals)*2+1)
   433  	children = append(children, openBracket)
   434  	for i, val := range vals {
   435  		if i > 0 {
   436  			if commas[i-1] == nil {
   437  				panic(fmt.Sprintf("commas[%d] is nil", i-1))
   438  			}
   439  			children = append(children, commas[i-1])
   440  		}
   441  		if val == nil {
   442  			panic(fmt.Sprintf("vals[%d] is nil", i))
   443  		}
   444  		children = append(children, val)
   445  	}
   446  	children = append(children, closeBracket)
   447  
   448  	return &ArrayLiteralNode{
   449  		compositeNode: compositeNode{
   450  			children: children,
   451  		},
   452  		OpenBracket:  openBracket,
   453  		Elements:     vals,
   454  		Commas:       commas,
   455  		CloseBracket: closeBracket,
   456  	}
   457  }
   458  
   459  func (n *ArrayLiteralNode) Value() interface{} {
   460  	return n.Elements
   461  }
   462  
   463  // MessageLiteralNode represents a message literal, which is compatible with the
   464  // protobuf text format and can be used for custom options with message types.
   465  // Example:
   466  //
   467  //	{ foo:1 foo:2 foo:3 bar:<name:"abc" id:123> }
   468  type MessageLiteralNode struct {
   469  	compositeNode
   470  	Open     *RuneNode // should be '{' or '<'
   471  	Elements []*MessageFieldNode
   472  	// Separator characters between elements, which can be either ','
   473  	// or ';' if present. This slice must be exactly len(Elements) in
   474  	// length, with each item in Elements having one corresponding item
   475  	// in Seps. Separators in message literals are optional, so a given
   476  	// item in this slice may be nil to indicate absence of a separator.
   477  	Seps  []*RuneNode
   478  	Close *RuneNode // should be '}' or '>', depending on Open
   479  }
   480  
   481  // NewMessageLiteralNode creates a new *MessageLiteralNode. The openSym and
   482  // closeSym runes must not be nil and should be "{" and "}" or "<" and ">".
   483  //
   484  // Unlike separators (dots and commas) used for other AST nodes that represent
   485  // a list of elements, the seps arg must be the SAME length as vals, and it may
   486  // contain nil values to indicate absence of a separator (in fact, it could be
   487  // all nils).
   488  func NewMessageLiteralNode(openSym *RuneNode, vals []*MessageFieldNode, seps []*RuneNode, closeSym *RuneNode) *MessageLiteralNode {
   489  	if openSym == nil {
   490  		panic("openSym is nil")
   491  	}
   492  	if closeSym == nil {
   493  		panic("closeSym is nil")
   494  	}
   495  	if len(seps) != len(vals) {
   496  		panic(fmt.Sprintf("%d vals requires %d commas, not %d", len(vals), len(vals), len(seps)))
   497  	}
   498  	numChildren := len(vals) + 2
   499  	for _, sep := range seps {
   500  		if sep != nil {
   501  			numChildren++
   502  		}
   503  	}
   504  	children := make([]Node, 0, numChildren)
   505  	children = append(children, openSym)
   506  	for i, val := range vals {
   507  		if val == nil {
   508  			panic(fmt.Sprintf("vals[%d] is nil", i))
   509  		}
   510  		children = append(children, val)
   511  		if seps[i] != nil {
   512  			children = append(children, seps[i])
   513  		}
   514  	}
   515  	children = append(children, closeSym)
   516  
   517  	return &MessageLiteralNode{
   518  		compositeNode: compositeNode{
   519  			children: children,
   520  		},
   521  		Open:     openSym,
   522  		Elements: vals,
   523  		Seps:     seps,
   524  		Close:    closeSym,
   525  	}
   526  }
   527  
   528  func (n *MessageLiteralNode) Value() interface{} {
   529  	return n.Elements
   530  }
   531  
   532  // MessageFieldNode represents a single field (name and value) inside of a
   533  // message literal. Example:
   534  //
   535  //	foo:"bar"
   536  type MessageFieldNode struct {
   537  	compositeNode
   538  	Name *FieldReferenceNode
   539  	// Sep represents the ':' separator between the name and value. If
   540  	// the value is a message literal (and thus starts with '<' or '{')
   541  	// or an array literal (starting with '[') then the separator is
   542  	// optional, and thus may be nil.
   543  	Sep *RuneNode
   544  	Val ValueNode
   545  }
   546  
   547  // NewMessageFieldNode creates a new *MessageFieldNode. All args except sep
   548  // must be non-nil.
   549  func NewMessageFieldNode(name *FieldReferenceNode, sep *RuneNode, val ValueNode) *MessageFieldNode {
   550  	if name == nil {
   551  		panic("name is nil")
   552  	}
   553  	if val == nil {
   554  		panic("val is nil")
   555  	}
   556  	numChildren := 2
   557  	if sep != nil {
   558  		numChildren++
   559  	}
   560  	children := make([]Node, 0, numChildren)
   561  	children = append(children, name)
   562  	if sep != nil {
   563  		children = append(children, sep)
   564  	}
   565  	children = append(children, val)
   566  
   567  	return &MessageFieldNode{
   568  		compositeNode: compositeNode{
   569  			children: children,
   570  		},
   571  		Name: name,
   572  		Sep:  sep,
   573  		Val:  val,
   574  	}
   575  }