value.go 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327
  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. "github.com/golang/protobuf/v2/internal/flags"
  34. "github.com/golang/protobuf/v2/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. // Float is a floating-point number (e.g., "1.234" or "1e100").
  47. Float
  48. // String is a quoted string (e.g., `"the quick brown fox"`).
  49. String
  50. // Name is a protocol buffer identifier (e.g., `field_name`).
  51. Name
  52. // List is an ordered list of values (e.g., `[0, "one", true]`).
  53. List
  54. // Message is an ordered map of values (e.g., `{"key": null}`).
  55. Message
  56. )
  57. func (t Type) String() string {
  58. switch t {
  59. case Bool:
  60. return "bool"
  61. case Int:
  62. return "int"
  63. case Uint:
  64. return "uint"
  65. case Float:
  66. return "float"
  67. case String:
  68. return "string"
  69. case Name:
  70. return "name"
  71. case List:
  72. return "list"
  73. case Message:
  74. return "message"
  75. default:
  76. return "<invalid>"
  77. }
  78. }
  79. // Value contains a value of a given Type.
  80. type Value struct {
  81. typ Type
  82. raw []byte // raw bytes of the serialized data
  83. str string // only for String or Name
  84. num uint64 // only for Bool, Int, Uint, or Float
  85. arr []Value // only for List
  86. obj [][2]Value // only for Message
  87. }
  88. // ValueOf returns a Value for a given Go value:
  89. // bool => Bool
  90. // int32, int64 => Int
  91. // uint32, uint64 => Uint
  92. // float32, float64 => Float
  93. // string, []byte => String
  94. // protoreflect.Name => Name
  95. // []Value => List
  96. // [][2]Value => Message
  97. //
  98. // ValueOf panics if the Go type is not one of the above.
  99. func ValueOf(v interface{}) Value {
  100. switch v := v.(type) {
  101. case bool:
  102. if v {
  103. return Value{typ: Bool, num: 1}
  104. } else {
  105. return Value{typ: Bool, num: 0}
  106. }
  107. case int32:
  108. return Value{typ: Int, num: uint64(v)}
  109. case int64:
  110. return Value{typ: Int, num: uint64(v)}
  111. case uint32:
  112. return Value{typ: Uint, num: uint64(v)}
  113. case uint64:
  114. return Value{typ: Uint, num: uint64(v)}
  115. case float32:
  116. return Value{typ: Float, num: math.Float64bits(float64(v))}
  117. case float64:
  118. return Value{typ: Float, num: math.Float64bits(float64(v))}
  119. case string:
  120. return Value{typ: String, str: string(v)}
  121. case []byte:
  122. return Value{typ: String, str: string(v)}
  123. case protoreflect.Name:
  124. return Value{typ: Name, str: string(v)}
  125. case []Value:
  126. return Value{typ: List, arr: v}
  127. case [][2]Value:
  128. return Value{typ: Message, obj: v}
  129. default:
  130. panic(fmt.Sprintf("invalid type %T", v))
  131. }
  132. }
  133. func rawValueOf(v interface{}, raw []byte) Value {
  134. v2 := ValueOf(v)
  135. v2.raw = raw
  136. return v2
  137. }
  138. // Type is the type of the value. When parsing, this is a best-effort guess
  139. // at the resulting type. However, there are ambiguities as to the exact type
  140. // of the value (e.g., "false" is either a bool or a name).
  141. // Thus, some of the types are convertible with each other.
  142. // The Bool, Int, Uint, Float, and Name methods return a boolean to report
  143. // whether the conversion was successful.
  144. func (v Value) Type() Type {
  145. return v.typ
  146. }
  147. // Bool returns v as a bool and reports whether the conversion succeeded.
  148. func (v Value) Bool() (x bool, ok bool) {
  149. switch v.typ {
  150. case Bool:
  151. return v.num > 0, true
  152. case Uint, Int:
  153. // C++ allows a 1-bit unsigned integer (e.g., "0", "1", or "0x1").
  154. if len(v.raw) > 0 && v.raw[0] != '-' && v.num < 2 {
  155. return v.num > 0, true
  156. }
  157. }
  158. return false, false
  159. }
  160. // Int returns v as an int64 of the specified precision and reports whether
  161. // the conversion succeeded.
  162. func (v Value) Int(b64 bool) (x int64, ok bool) {
  163. switch v.typ {
  164. case Int:
  165. n := int64(v.num)
  166. if b64 || (math.MinInt32 <= n && n <= math.MaxInt32) {
  167. return int64(n), true
  168. }
  169. case Uint:
  170. n := uint64(v.num)
  171. if (!b64 && n <= math.MaxInt32) || (b64 && n <= math.MaxInt64) {
  172. return int64(n), true
  173. }
  174. // C++ accepts large positive hex numbers as negative values.
  175. // This feature is here for proto1 backwards compatibility purposes.
  176. if flags.Proto1Legacy && len(v.raw) > 1 && v.raw[0] == '0' && v.raw[1] == 'x' {
  177. if !b64 {
  178. return int64(int32(n)), n <= math.MaxUint32
  179. }
  180. // if !b64 && n <= math.MaxUint32 {
  181. // return int64(int32(n)), true
  182. // }
  183. return int64(n), true
  184. }
  185. }
  186. return 0, false
  187. }
  188. // Uint returns v as an uint64 of the specified precision and reports whether
  189. // the conversion succeeded.
  190. func (v Value) Uint(b64 bool) (x uint64, ok bool) {
  191. switch v.typ {
  192. case Int:
  193. n := int64(v.num)
  194. if len(v.raw) > 0 && v.raw[0] != '-' && (b64 || n <= math.MaxUint32) {
  195. return uint64(n), true
  196. }
  197. case Uint:
  198. n := uint64(v.num)
  199. if b64 || n <= math.MaxUint32 {
  200. return uint64(n), true
  201. }
  202. }
  203. return 0, false
  204. }
  205. // Float returns v as a float64 of the specified precision and reports whether
  206. // the conversion succeeded.
  207. func (v Value) Float(b64 bool) (x float64, ok bool) {
  208. switch v.typ {
  209. case Int:
  210. return float64(int64(v.num)), true // possibly lossy, but allowed
  211. case Uint:
  212. return float64(uint64(v.num)), true // possibly lossy, but allowed
  213. case Float:
  214. n := math.Float64frombits(v.num)
  215. if math.IsNaN(n) || math.IsInf(n, 0) {
  216. return float64(n), true
  217. }
  218. if b64 || math.Abs(n) <= math.MaxFloat32 {
  219. return float64(n), true
  220. }
  221. }
  222. return 0, false
  223. }
  224. // String returns v as a string if the Type is String.
  225. // Otherwise, this returns a formatted string of v for debugging purposes.
  226. //
  227. // Since String is used to represent both text and binary, it is not validated
  228. // to contain valid UTF-8. When using this value with the string type in proto,
  229. // it is the user's responsibility perform additional UTF-8 validation.
  230. func (v Value) String() string {
  231. if v.typ != String {
  232. return v.stringValue()
  233. }
  234. return v.str
  235. }
  236. func (v Value) stringValue() string {
  237. switch v.typ {
  238. case Bool, Int, Uint, Float, Name:
  239. return string(v.Raw())
  240. case List:
  241. var ss []string
  242. for _, v := range v.List() {
  243. ss = append(ss, v.String())
  244. }
  245. return "[" + strings.Join(ss, ",") + "]"
  246. case Message:
  247. var ss []string
  248. for _, v := range v.Message() {
  249. k := v[0].String()
  250. if v[0].Type() == String {
  251. k = "[" + k + "]"
  252. }
  253. ss = append(ss, k+":"+v[1].String())
  254. }
  255. return "{" + strings.Join(ss, ",") + "}"
  256. default:
  257. return "<invalid>"
  258. }
  259. }
  260. // Name returns the field name or enum value name and reports whether the value
  261. // can be treated as an identifier.
  262. func (v Value) Name() (protoreflect.Name, bool) {
  263. switch v.typ {
  264. case Bool, Float:
  265. // Ambiguity arises in unmarshalValue since "nan" may interpreted as
  266. // either a Name type (for enum values) or a Float type.
  267. // Similarly, "true" may be interpreted as either a Name or Bool type.
  268. n := protoreflect.Name(v.raw)
  269. if n.IsValid() {
  270. return n, true
  271. }
  272. case Name:
  273. return protoreflect.Name(v.str), true
  274. }
  275. return "", false
  276. }
  277. // List returns the elements of v and panics if the Type is not List.
  278. // Mutations on the return value may not be observable from the Raw method.
  279. func (v Value) List() []Value {
  280. if v.typ != List {
  281. panic("value is not a list")
  282. }
  283. return v.arr
  284. }
  285. // Message returns the items of v and panics if the Type is not Message.
  286. // The [2]Value represents a key and value pair, where the key is either
  287. // a Name (representing a field name), a String (representing extension field
  288. // names or the Any type URL), or an Uint for unknown fields.
  289. //
  290. // Mutations on the return value may not be observable from the Raw method.
  291. func (v Value) Message() [][2]Value {
  292. if v.typ != Message {
  293. panic("value is not a message")
  294. }
  295. return v.obj
  296. }
  297. // Raw returns the raw representation of the value.
  298. // The returned value may alias the input given to Unmarshal.
  299. func (v Value) Raw() []byte {
  300. if len(v.raw) > 0 {
  301. return v.raw
  302. }
  303. p := encoder{}
  304. if err := p.marshalValue(v); !p.nerr.Merge(err) {
  305. return []byte("<invalid>")
  306. }
  307. return p.out
  308. }