value.go 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334
  1. // Copyright 2018 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. // Package text implements the text format for protocol buffers.
  5. // This package has no semantic understanding for protocol buffers and is only
  6. // a parser and composer for the format.
  7. //
  8. // There is no formal specification for the protobuf text format, as such the
  9. // C++ implementation (see google::protobuf::TextFormat) is the reference
  10. // implementation of the text format.
  11. //
  12. // This package is neither a superset nor a subset of the C++ implementation.
  13. // This implementation permits a more liberal grammar in some cases to be
  14. // backwards compatible with the historical Go implementation.
  15. // Future parsings unique to Go should not be added.
  16. // Some grammars allowed by the C++ implementation are deliberately
  17. // not implemented here because they are considered a bug by the protobuf team
  18. // and should not be replicated.
  19. //
  20. // The Go implementation should implement a sufficient amount of the C++
  21. // grammar such that the default text serialization by C++ can be parsed by Go.
  22. // However, just because the C++ parser accepts some input does not mean that
  23. // the Go implementation should as well.
  24. //
  25. // The text format is almost a superset of JSON except:
  26. // * message keys are not quoted strings, but identifiers
  27. // * the top-level value must be a message without the delimiters
  28. package text
  29. import (
  30. "fmt"
  31. "math"
  32. "strings"
  33. "google.golang.org/protobuf/internal/flags"
  34. "google.golang.org/protobuf/reflect/protoreflect"
  35. )
  36. // Type represents a type expressible in the text format.
  37. type Type uint8
  38. const (
  39. _ Type = iota
  40. // Bool is a boolean (e.g., "true" or "false").
  41. Bool
  42. // Int is a signed integer (e.g., "-1423").
  43. Int
  44. // Uint is an unsigned integer (e.g., "0xdeadbeef").
  45. Uint
  46. // Float32 is a 32-bit floating-point number (e.g., "1.234" or "1e38").
  47. // This allows encoding to differentiate the bitsize used for formatting.
  48. Float32
  49. // Float64 is a 64-bit floating-point number.
  50. Float64
  51. // String is a quoted string (e.g., `"the quick brown fox"`).
  52. String
  53. // Name is a protocol buffer identifier (e.g., `field_name`).
  54. Name
  55. // List is an ordered list of values (e.g., `[0, "one", true]`).
  56. List
  57. // Message is an ordered map of values (e.g., `{"key": null}`).
  58. Message
  59. )
  60. func (t Type) String() string {
  61. switch t {
  62. case Bool:
  63. return "bool"
  64. case Int:
  65. return "int"
  66. case Uint:
  67. return "uint"
  68. case Float32:
  69. return "float32"
  70. case Float64:
  71. return "float64"
  72. case String:
  73. return "string"
  74. case Name:
  75. return "name"
  76. case List:
  77. return "list"
  78. case Message:
  79. return "message"
  80. default:
  81. return "<invalid>"
  82. }
  83. }
  84. // Value contains a value of a given Type.
  85. type Value struct {
  86. typ Type
  87. raw []byte // raw bytes of the serialized data
  88. str string // only for String or Name
  89. num uint64 // only for Bool, Int, Uint, Float32, or Float64
  90. arr []Value // only for List
  91. obj [][2]Value // only for Message
  92. }
  93. // ValueOf returns a Value for a given Go value:
  94. // bool => Bool
  95. // int32, int64 => Int
  96. // uint32, uint64 => Uint
  97. // float32 => Float32
  98. // float64 => Float64
  99. // string, []byte => String
  100. // protoreflect.Name => Name
  101. // []Value => List
  102. // [][2]Value => Message
  103. //
  104. // ValueOf panics if the Go type is not one of the above.
  105. func ValueOf(v interface{}) Value {
  106. switch v := v.(type) {
  107. case bool:
  108. if v {
  109. return Value{typ: Bool, num: 1}
  110. } else {
  111. return Value{typ: Bool, num: 0}
  112. }
  113. case int32:
  114. return Value{typ: Int, num: uint64(v)}
  115. case int64:
  116. return Value{typ: Int, num: uint64(v)}
  117. case uint32:
  118. return Value{typ: Uint, num: uint64(v)}
  119. case uint64:
  120. return Value{typ: Uint, num: uint64(v)}
  121. case float32:
  122. // Store as float64 bits.
  123. return Value{typ: Float32, num: math.Float64bits(float64(v))}
  124. case float64:
  125. return Value{typ: Float64, num: math.Float64bits(float64(v))}
  126. case string:
  127. return Value{typ: String, str: string(v)}
  128. case []byte:
  129. return Value{typ: String, str: string(v)}
  130. case protoreflect.Name:
  131. return Value{typ: Name, str: string(v)}
  132. case []Value:
  133. return Value{typ: List, arr: v}
  134. case [][2]Value:
  135. return Value{typ: Message, obj: v}
  136. default:
  137. panic(fmt.Sprintf("invalid type %T", v))
  138. }
  139. }
  140. func rawValueOf(v interface{}, raw []byte) Value {
  141. v2 := ValueOf(v)
  142. v2.raw = raw
  143. return v2
  144. }
  145. // Type is the type of the value. When parsing, this is a best-effort guess
  146. // at the resulting type. However, there are ambiguities as to the exact type
  147. // of the value (e.g., "false" is either a bool or a name).
  148. // Thus, some of the types are convertible with each other.
  149. // The Bool, Int, Uint, Float32, Float64, and Name methods return a boolean to
  150. // report whether the conversion was successful.
  151. func (v Value) Type() Type {
  152. return v.typ
  153. }
  154. // Bool returns v as a bool and reports whether the conversion succeeded.
  155. func (v Value) Bool() (x bool, ok bool) {
  156. switch v.typ {
  157. case Bool:
  158. return v.num > 0, true
  159. case Uint, Int:
  160. // C++ allows a 1-bit unsigned integer (e.g., "0", "1", or "0x1").
  161. if len(v.raw) > 0 && v.raw[0] != '-' && v.num < 2 {
  162. return v.num > 0, true
  163. }
  164. }
  165. return false, false
  166. }
  167. // Int returns v as an int64 of the specified precision and reports whether
  168. // the conversion succeeded.
  169. func (v Value) Int(b64 bool) (x int64, ok bool) {
  170. switch v.typ {
  171. case Int:
  172. n := int64(v.num)
  173. if b64 || (math.MinInt32 <= n && n <= math.MaxInt32) {
  174. return int64(n), true
  175. }
  176. case Uint:
  177. n := uint64(v.num)
  178. if (!b64 && n <= math.MaxInt32) || (b64 && n <= math.MaxInt64) {
  179. return int64(n), true
  180. }
  181. // C++ accepts large positive hex numbers as negative values.
  182. // This feature is here for proto1 backwards compatibility purposes.
  183. if flags.ProtoLegacy && len(v.raw) > 1 && v.raw[0] == '0' && v.raw[1] == 'x' {
  184. if !b64 {
  185. return int64(int32(n)), n <= math.MaxUint32
  186. }
  187. // if !b64 && n <= math.MaxUint32 {
  188. // return int64(int32(n)), true
  189. // }
  190. return int64(n), true
  191. }
  192. }
  193. return 0, false
  194. }
  195. // Uint returns v as an uint64 of the specified precision and reports whether
  196. // the conversion succeeded.
  197. func (v Value) Uint(b64 bool) (x uint64, ok bool) {
  198. switch v.typ {
  199. case Int:
  200. n := int64(v.num)
  201. if len(v.raw) > 0 && v.raw[0] != '-' && (b64 || n <= math.MaxUint32) {
  202. return uint64(n), true
  203. }
  204. case Uint:
  205. n := uint64(v.num)
  206. if b64 || n <= math.MaxUint32 {
  207. return uint64(n), true
  208. }
  209. }
  210. return 0, false
  211. }
  212. // Float returns v as a float64 of the specified precision and reports whether
  213. // the conversion succeeded.
  214. func (v Value) Float(b64 bool) (x float64, ok bool) {
  215. switch v.typ {
  216. case Int:
  217. return float64(int64(v.num)), true // possibly lossy, but allowed
  218. case Uint:
  219. return float64(uint64(v.num)), true // possibly lossy, but allowed
  220. case Float32, Float64:
  221. n := math.Float64frombits(v.num)
  222. if math.IsNaN(n) || math.IsInf(n, 0) {
  223. return float64(n), true
  224. }
  225. if b64 || math.Abs(n) <= math.MaxFloat32 {
  226. return float64(n), true
  227. }
  228. }
  229. return 0, false
  230. }
  231. // String returns v as a string if the Type is String.
  232. // Otherwise, this returns a formatted string of v for debugging purposes.
  233. //
  234. // Since String is used to represent both text and binary, it is not validated
  235. // to contain valid UTF-8. When using this value with the string type in proto,
  236. // it is the user's responsibility perform additional UTF-8 validation.
  237. func (v Value) String() string {
  238. if v.typ != String {
  239. return v.stringValue()
  240. }
  241. return v.str
  242. }
  243. func (v Value) stringValue() string {
  244. switch v.typ {
  245. case Bool, Int, Uint, Float32, Float64, Name:
  246. return string(v.Raw())
  247. case List:
  248. var ss []string
  249. for _, v := range v.List() {
  250. ss = append(ss, v.String())
  251. }
  252. return "[" + strings.Join(ss, ",") + "]"
  253. case Message:
  254. var ss []string
  255. for _, v := range v.Message() {
  256. k := v[0].String()
  257. if v[0].Type() == String {
  258. k = "[" + k + "]"
  259. }
  260. ss = append(ss, k+":"+v[1].String())
  261. }
  262. return "{" + strings.Join(ss, ",") + "}"
  263. default:
  264. return "<invalid>"
  265. }
  266. }
  267. // Name returns the field name or enum value name and reports whether the value
  268. // can be treated as an identifier.
  269. func (v Value) Name() (protoreflect.Name, bool) {
  270. switch v.typ {
  271. case Bool, Float32, Float64:
  272. // Ambiguity arises in unmarshalValue since "nan" may interpreted as
  273. // either a Name type (for enum values) or a Float32/Float64 type.
  274. // Similarly, "true" may be interpreted as either a Name or Bool type.
  275. n := protoreflect.Name(v.raw)
  276. if n.IsValid() {
  277. return n, true
  278. }
  279. case Name:
  280. return protoreflect.Name(v.str), true
  281. }
  282. return "", false
  283. }
  284. // List returns the elements of v and panics if the Type is not List.
  285. // Mutations on the return value may not be observable from the Raw method.
  286. func (v Value) List() []Value {
  287. if v.typ != List {
  288. panic("value is not a list")
  289. }
  290. return v.arr
  291. }
  292. // Message returns the items of v and panics if the Type is not Message.
  293. // The [2]Value represents a key and value pair, where the key is either
  294. // a Name (representing a field name), a String (representing extension field
  295. // names or the Any type URL), or an Uint for unknown fields.
  296. //
  297. // Mutations on the return value may not be observable from the Raw method.
  298. func (v Value) Message() [][2]Value {
  299. if v.typ != Message {
  300. panic("value is not a message")
  301. }
  302. return v.obj
  303. }
  304. // Raw returns the raw representation of the value.
  305. // The returned value may alias the input given to Unmarshal.
  306. func (v Value) Raw() []byte {
  307. if len(v.raw) > 0 {
  308. return v.raw
  309. }
  310. p := encoder{}
  311. if err := p.marshalValue(v); err != nil {
  312. return []byte("<invalid>")
  313. }
  314. return p.out
  315. }