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 }