PageRenderTime 26ms CodeModel.GetById 14ms RepoModel.GetById 0ms app.codeStats 0ms

/proto/text.go

https://code.google.com/p/goprotobuf/
Go | 469 lines | 348 code | 46 blank | 75 comment | 87 complexity | a1fd38c0eaf04d0d17298fdd70f69559 MD5 | raw file
Possible License(s): BSD-3-Clause
  1. // Go support for Protocol Buffers - Google's data interchange format
  2. //
  3. // Copyright 2010 Google Inc. All rights reserved.
  4. // http://code.google.com/p/goprotobuf/
  5. //
  6. // Redistribution and use in source and binary forms, with or without
  7. // modification, are permitted provided that the following conditions are
  8. // met:
  9. //
  10. // * Redistributions of source code must retain the above copyright
  11. // notice, this list of conditions and the following disclaimer.
  12. // * Redistributions in binary form must reproduce the above
  13. // copyright notice, this list of conditions and the following disclaimer
  14. // in the documentation and/or other materials provided with the
  15. // distribution.
  16. // * Neither the name of Google Inc. nor the names of its
  17. // contributors may be used to endorse or promote products derived from
  18. // this software without specific prior written permission.
  19. //
  20. // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  21. // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  22. // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  23. // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  24. // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  25. // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  26. // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  27. // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  28. // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  29. // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  30. // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  31. package proto
  32. // Functions for writing the text protocol buffer format.
  33. import (
  34. "bytes"
  35. "fmt"
  36. "io"
  37. "log"
  38. "os"
  39. "reflect"
  40. "sort"
  41. "strings"
  42. )
  43. // textWriter is an io.Writer that tracks its indentation level.
  44. type textWriter struct {
  45. ind int
  46. complete bool // if the current position is a complete line
  47. compact bool // whether to write out as a one-liner
  48. writer io.Writer
  49. c [1]byte // scratch
  50. }
  51. func (w *textWriter) Write(p []byte) (n int, err error) {
  52. n, err = len(p), nil
  53. frags := strings.Split(string(p), "\n")
  54. if w.compact {
  55. w.writer.Write([]byte(strings.Join(frags, " ")))
  56. return
  57. }
  58. for i, frag := range frags {
  59. if w.complete {
  60. for j := 0; j < w.ind; j++ {
  61. w.writer.Write([]byte{' ', ' '})
  62. }
  63. w.complete = false
  64. }
  65. w.writer.Write([]byte(frag))
  66. if i+1 < len(frags) {
  67. w.writer.Write([]byte{'\n'})
  68. }
  69. }
  70. w.complete = len(frags[len(frags)-1]) == 0
  71. return
  72. }
  73. func (w *textWriter) WriteByte(c byte) error {
  74. w.c[0] = c
  75. _, err := w.Write(w.c[:])
  76. return err
  77. }
  78. func (w *textWriter) indent() { w.ind++ }
  79. func (w *textWriter) unindent() {
  80. if w.ind == 0 {
  81. log.Printf("proto: textWriter unindented too far!")
  82. return
  83. }
  84. w.ind--
  85. }
  86. func writeName(w *textWriter, props *Properties) {
  87. io.WriteString(w, props.OrigName)
  88. if props.Wire != "group" {
  89. w.WriteByte(':')
  90. }
  91. }
  92. var (
  93. messageSetType = reflect.TypeOf((*MessageSet)(nil)).Elem()
  94. extendableProtoType = reflect.TypeOf((*extendableProto)(nil)).Elem()
  95. )
  96. // raw is the interface satisfied by RawMessage.
  97. type raw interface {
  98. Bytes() []byte
  99. }
  100. func writeStruct(w *textWriter, sv reflect.Value) {
  101. if sv.Type() == messageSetType {
  102. writeMessageSet(w, sv.Addr().Interface().(*MessageSet))
  103. return
  104. }
  105. st := sv.Type()
  106. sprops := GetProperties(st)
  107. for i := 0; i < sv.NumField(); i++ {
  108. fv := sv.Field(i)
  109. if name := st.Field(i).Name; strings.HasPrefix(name, "XXX_") {
  110. // There's only two XXX_ fields:
  111. // XXX_unrecognized []byte
  112. // XXX_extensions map[int32]proto.Extension
  113. // The first is handled here;
  114. // the second is handled at the bottom of this function.
  115. if name == "XXX_unrecognized" && !fv.IsNil() {
  116. writeUnknownStruct(w, fv.Interface().([]byte))
  117. }
  118. continue
  119. }
  120. props := sprops.Prop[i]
  121. if fv.Kind() == reflect.Ptr && fv.IsNil() {
  122. // Field not filled in. This could be an optional field or
  123. // a required field that wasn't filled in. Either way, there
  124. // isn't anything we can show for it.
  125. continue
  126. }
  127. if fv.Kind() == reflect.Slice && fv.IsNil() {
  128. // Repeated field that is empty, or a bytes field that is unused.
  129. continue
  130. }
  131. if props.Repeated && fv.Kind() == reflect.Slice {
  132. // Repeated field.
  133. for j := 0; j < fv.Len(); j++ {
  134. writeName(w, props)
  135. if !w.compact {
  136. w.WriteByte(' ')
  137. }
  138. writeAny(w, fv.Index(j), props)
  139. w.WriteByte('\n')
  140. }
  141. continue
  142. }
  143. writeName(w, props)
  144. if !w.compact {
  145. w.WriteByte(' ')
  146. }
  147. if b, ok := fv.Interface().(raw); ok {
  148. writeRaw(w, b.Bytes())
  149. continue
  150. }
  151. if props.Enum != "" && tryWriteEnum(w, props.Enum, fv) {
  152. // Enum written.
  153. } else {
  154. writeAny(w, fv, props)
  155. }
  156. w.WriteByte('\n')
  157. }
  158. // Extensions (the XXX_extensions field).
  159. pv := sv.Addr()
  160. if pv.Type().Implements(extendableProtoType) {
  161. writeExtensions(w, pv)
  162. }
  163. }
  164. // writeRaw writes an uninterpreted raw message.
  165. func writeRaw(w *textWriter, b []byte) {
  166. w.WriteByte('<')
  167. if !w.compact {
  168. w.WriteByte('\n')
  169. }
  170. w.indent()
  171. writeUnknownStruct(w, b)
  172. w.unindent()
  173. w.WriteByte('>')
  174. }
  175. // tryWriteEnum attempts to write an enum value as a symbolic constant.
  176. // If the enum is unregistered, nothing is written and false is returned.
  177. func tryWriteEnum(w *textWriter, enum string, v reflect.Value) bool {
  178. v = reflect.Indirect(v)
  179. if v.Type().Kind() != reflect.Int32 {
  180. return false
  181. }
  182. m, ok := enumNameMaps[enum]
  183. if !ok {
  184. return false
  185. }
  186. str, ok := m[int32(v.Int())]
  187. if !ok {
  188. return false
  189. }
  190. fmt.Fprintf(w, str)
  191. return true
  192. }
  193. // writeAny writes an arbitrary field.
  194. func writeAny(w *textWriter, v reflect.Value, props *Properties) {
  195. v = reflect.Indirect(v)
  196. // We don't attempt to serialise every possible value type; only those
  197. // that can occur in protocol buffers, plus a few extra that were easy.
  198. switch v.Kind() {
  199. case reflect.Slice:
  200. // Should only be a []byte; repeated fields are handled in writeStruct.
  201. writeString(w, string(v.Interface().([]byte)))
  202. case reflect.String:
  203. writeString(w, v.String())
  204. case reflect.Struct:
  205. // Required/optional group/message.
  206. var bra, ket byte = '<', '>'
  207. if props != nil && props.Wire == "group" {
  208. bra, ket = '{', '}'
  209. }
  210. w.WriteByte(bra)
  211. if !w.compact {
  212. w.WriteByte('\n')
  213. }
  214. w.indent()
  215. writeStruct(w, v)
  216. w.unindent()
  217. w.WriteByte(ket)
  218. default:
  219. fmt.Fprint(w, v.Interface())
  220. }
  221. }
  222. // equivalent to C's isprint.
  223. func isprint(c byte) bool {
  224. return c >= 0x20 && c < 0x7f
  225. }
  226. // writeString writes a string in the protocol buffer text format.
  227. // It is similar to strconv.Quote except we don't use Go escape sequences,
  228. // we treat the string as a byte sequence, and we use octal escapes.
  229. // These differences are to maintain interoperability with the other
  230. // languages' implementations of the text format.
  231. func writeString(w *textWriter, s string) {
  232. w.WriteByte('"')
  233. // Loop over the bytes, not the runes.
  234. for i := 0; i < len(s); i++ {
  235. // Divergence from C++: we don't escape apostrophes.
  236. // There's no need to escape them, and the C++ parser
  237. // copes with a naked apostrophe.
  238. switch c := s[i]; c {
  239. case '\n':
  240. w.Write([]byte{'\\', 'n'})
  241. case '\r':
  242. w.Write([]byte{'\\', 'r'})
  243. case '\t':
  244. w.Write([]byte{'\\', 't'})
  245. case '"':
  246. w.Write([]byte{'\\', '"'})
  247. case '\\':
  248. w.Write([]byte{'\\', '\\'})
  249. default:
  250. if isprint(c) {
  251. w.WriteByte(c)
  252. } else {
  253. fmt.Fprintf(w, "\\%03o", c)
  254. }
  255. }
  256. }
  257. w.WriteByte('"')
  258. }
  259. func writeMessageSet(w *textWriter, ms *MessageSet) {
  260. for _, item := range ms.Item {
  261. id := *item.TypeId
  262. if msd, ok := messageSetMap[id]; ok {
  263. // Known message set type.
  264. fmt.Fprintf(w, "[%s]: <\n", msd.name)
  265. w.indent()
  266. pb := reflect.New(msd.t.Elem())
  267. if err := Unmarshal(item.Message, pb.Interface()); err != nil {
  268. fmt.Fprintf(w, "/* bad message: %v */\n", err)
  269. } else {
  270. writeStruct(w, pb.Elem())
  271. }
  272. } else {
  273. // Unknown type.
  274. fmt.Fprintf(w, "[%d]: <\n", id)
  275. w.indent()
  276. writeUnknownStruct(w, item.Message)
  277. }
  278. w.unindent()
  279. w.Write([]byte(">\n"))
  280. }
  281. }
  282. func writeUnknownStruct(w *textWriter, data []byte) {
  283. if !w.compact {
  284. fmt.Fprintf(w, "/* %d unknown bytes */\n", len(data))
  285. }
  286. b := NewBuffer(data)
  287. for b.index < len(b.buf) {
  288. x, err := b.DecodeVarint()
  289. if err != nil {
  290. fmt.Fprintf(w, "/* %v */\n", err)
  291. return
  292. }
  293. wire, tag := x&7, x>>3
  294. if wire == WireEndGroup {
  295. w.unindent()
  296. w.Write([]byte("}\n"))
  297. continue
  298. }
  299. fmt.Fprintf(w, "tag%d", tag)
  300. if wire != WireStartGroup {
  301. w.WriteByte(':')
  302. }
  303. if !w.compact || wire == WireStartGroup {
  304. w.WriteByte(' ')
  305. }
  306. switch wire {
  307. case WireBytes:
  308. buf, err := b.DecodeRawBytes(false)
  309. if err == nil {
  310. fmt.Fprintf(w, "%q", buf)
  311. } else {
  312. fmt.Fprintf(w, "/* %v */", err)
  313. }
  314. case WireFixed32:
  315. x, err := b.DecodeFixed32()
  316. writeUnknownInt(w, x, err)
  317. case WireFixed64:
  318. x, err := b.DecodeFixed64()
  319. writeUnknownInt(w, x, err)
  320. case WireStartGroup:
  321. fmt.Fprint(w, "{")
  322. w.indent()
  323. case WireVarint:
  324. x, err := b.DecodeVarint()
  325. writeUnknownInt(w, x, err)
  326. default:
  327. fmt.Fprintf(w, "/* unknown wire type %d */", wire)
  328. }
  329. w.WriteByte('\n')
  330. }
  331. }
  332. func writeUnknownInt(w *textWriter, x uint64, err error) {
  333. if err == nil {
  334. fmt.Fprint(w, x)
  335. } else {
  336. fmt.Fprintf(w, "/* %v */", err)
  337. }
  338. }
  339. type int32Slice []int32
  340. func (s int32Slice) Len() int { return len(s) }
  341. func (s int32Slice) Less(i, j int) bool { return s[i] < s[j] }
  342. func (s int32Slice) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
  343. // writeExtensions writes all the extensions in pv.
  344. // pv is assumed to be a pointer to a protocol message struct that is extendable.
  345. func writeExtensions(w *textWriter, pv reflect.Value) {
  346. emap := extensionMaps[pv.Type().Elem()]
  347. ep := pv.Interface().(extendableProto)
  348. // Order the extensions by ID.
  349. // This isn't strictly necessary, but it will give us
  350. // canonical output, which will also make testing easier.
  351. m := ep.ExtensionMap()
  352. ids := make([]int32, 0, len(m))
  353. for id := range m {
  354. ids = append(ids, id)
  355. }
  356. sort.Sort(int32Slice(ids))
  357. for _, extNum := range ids {
  358. ext := m[extNum]
  359. var desc *ExtensionDesc
  360. if emap != nil {
  361. desc = emap[extNum]
  362. }
  363. if desc == nil {
  364. // Unknown extension.
  365. writeUnknownStruct(w, ext.enc)
  366. continue
  367. }
  368. pb, err := GetExtension(ep, desc)
  369. if err != nil {
  370. fmt.Fprintln(os.Stderr, "proto: failed getting extension: ", err)
  371. continue
  372. }
  373. fmt.Fprintf(w, "[%s]:", desc.Name)
  374. if !w.compact {
  375. w.WriteByte(' ')
  376. }
  377. writeAny(w, reflect.ValueOf(pb), nil)
  378. w.WriteByte('\n')
  379. }
  380. }
  381. func marshalText(w io.Writer, pb interface{}, compact bool) {
  382. if pb == nil {
  383. w.Write([]byte("<nil>"))
  384. return
  385. }
  386. aw := new(textWriter)
  387. aw.writer = w
  388. aw.complete = true
  389. aw.compact = compact
  390. // Reject non-pointer inputs (it's a bad practice to pass potentially large protos around by value).
  391. v := reflect.ValueOf(pb)
  392. if v.Kind() != reflect.Ptr {
  393. w.Write([]byte("<struct-by-value>"))
  394. return
  395. }
  396. // Dereference the received pointer so we don't have outer < and >.
  397. v = reflect.Indirect(v)
  398. if v.Kind() == reflect.Struct {
  399. writeStruct(aw, v)
  400. } else {
  401. writeAny(aw, v, nil)
  402. }
  403. }
  404. // MarshalText writes a given protocol buffer in text format.
  405. // Values that are not protocol buffers can also be written, but their formatting is not guaranteed.
  406. func MarshalText(w io.Writer, pb interface{}) { marshalText(w, pb, false) }
  407. // MarshalTextString is the same as MarshalText, but returns the string directly.
  408. func MarshalTextString(pb interface{}) string {
  409. var buf bytes.Buffer
  410. marshalText(&buf, pb, false)
  411. return buf.String()
  412. }
  413. // CompactText writes a given protocl buffer in compact text format (one line).
  414. // Values that are not protocol buffers can also be written, but their formatting is not guaranteed.
  415. func CompactText(w io.Writer, pb interface{}) { marshalText(w, pb, true) }
  416. // CompactTextString is the same as CompactText, but returns the string directly.
  417. func CompactTextString(pb interface{}) string {
  418. var buf bytes.Buffer
  419. marshalText(&buf, pb, true)
  420. return buf.String()
  421. }