1 // Go support for Protocol Buffers - Google's data interchange format
3 // Copyright 2010 Google Inc. All rights reserved.
4 // http://code.google.com/p/goprotobuf/
6 // Redistribution and use in source and binary forms, with or without
7 // modification, are permitted provided that the following conditions are
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
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.
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.
34 // Functions for writing the text protocol buffer format.
47 // textWriter is an io.Writer that tracks its indentation level.
48 type textWriter struct {
50 complete bool // if the current position is a complete line
51 compact bool // whether to write out as a one-liner
57 func (w *textWriter) Write(p []byte) (n int, err os.Error) {
60 frags := strings.Split(string(p), "\n")
62 w.writer.Write([]byte(strings.Join(frags, " ")))
66 for i, frag := range frags {
68 for j := 0; j < w.ind; j++ {
69 w.writer.Write([]byte{' ', ' '})
74 w.writer.Write([]byte(frag))
76 w.writer.Write([]byte{'\n'})
79 w.complete = len(frags[len(frags)-1]) == 0
84 func (w *textWriter) WriteByte(c byte) os.Error {
86 _, err := w.Write(w.c[:])
90 func (w *textWriter) indent() { w.ind++ }
92 func (w *textWriter) unindent() {
94 log.Printf("proto: textWriter unindented too far!")
100 func writeName(w *textWriter, props *Properties) {
101 io.WriteString(w, props.OrigName)
102 if props.Wire != "group" {
108 messageSetType = reflect.TypeOf((*MessageSet)(nil)).Elem()
109 extendableProtoType = reflect.TypeOf((*extendableProto)(nil)).Elem()
112 func writeStruct(w *textWriter, sv reflect.Value) {
113 if sv.Type() == messageSetType {
114 writeMessageSet(w, sv.Addr().Interface().(*MessageSet))
119 sprops := GetProperties(st)
120 for i := 0; i < sv.NumField(); i++ {
122 if name := st.Field(i).Name; strings.HasPrefix(name, "XXX_") {
123 // There's only two XXX_ fields:
124 // XXX_unrecognized []byte
125 // XXX_extensions map[int32]proto.Extension
126 // The first is handled here;
127 // the second is handled at the bottom of this function.
128 if name == "XXX_unrecognized" && !fv.IsNil() {
129 writeUnknownStruct(w, fv.Interface().([]byte))
133 props := sprops.Prop[i]
134 if fv.Kind() == reflect.Ptr && fv.IsNil() {
135 // Field not filled in. This could be an optional field or
136 // a required field that wasn't filled in. Either way, there
137 // isn't anything we can show for it.
140 if fv.Kind() == reflect.Slice && fv.IsNil() {
141 // Repeated field that is empty, or a bytes field that is unused.
145 if props.Repeated && fv.Kind() == reflect.Slice {
147 for j := 0; j < fv.Len(); j++ {
152 writeAny(w, fv.Index(j), props)
162 if props.Enum != "" && tryWriteEnum(w, props.Enum, fv) {
165 writeAny(w, fv, props)
170 // Extensions (the XXX_extensions field).
172 if pv.Type().Implements(extendableProtoType) {
173 writeExtensions(w, pv)
177 // tryWriteEnum attempts to write an enum value as a symbolic constant.
178 // If the enum is unregistered, nothing is written and false is returned.
179 func tryWriteEnum(w *textWriter, enum string, v reflect.Value) bool {
180 v = reflect.Indirect(v)
181 if v.Type().Kind() != reflect.Int32 {
184 m, ok := enumNameMaps[enum]
188 str, ok := m[int32(v.Int())]
196 // writeAny writes an arbitrary field.
197 func writeAny(w *textWriter, v reflect.Value, props *Properties) {
198 v = reflect.Indirect(v)
200 // We don't attempt to serialise every possible value type; only those
201 // that can occur in protocol buffers, plus a few extra that were easy.
204 // Should only be a []byte; repeated fields are handled in writeStruct.
205 writeString(w, string(v.Interface().([]byte)))
207 writeString(w, v.String())
209 // Required/optional group/message.
210 var bra, ket byte = '<', '>'
211 if props != nil && props.Wire == "group" {
223 fmt.Fprint(w, v.Interface())
227 // equivalent to C's isprint.
228 func isprint(c byte) bool {
229 return c >= 0x20 && c < 0x7f
232 // writeString writes a string in the protocol buffer text format.
233 // It is similar to strconv.Quote except we don't use Go escape sequences,
234 // we treat the string as a byte sequence, and we use octal escapes.
235 // These differences are to maintain interoperability with the other
236 // languages' implementations of the text format.
237 func writeString(w *textWriter, s string) {
240 // Loop over the bytes, not the runes.
241 for i := 0; i < len(s); i++ {
242 // Divergence from C++: we don't escape apostrophes.
243 // There's no need to escape them, and the C++ parser
244 // copes with a naked apostrophe.
245 switch c := s[i]; c {
247 w.Write([]byte{'\\', 'n'})
249 w.Write([]byte{'\\', 'r'})
251 w.Write([]byte{'\\', 't'})
253 w.Write([]byte{'\\', '"'})
255 w.Write([]byte{'\\', '\\'})
260 fmt.Fprintf(w, "\\%03o", c)
268 func writeMessageSet(w *textWriter, ms *MessageSet) {
269 for _, item := range ms.Item {
271 if msd, ok := messageSetMap[id]; ok {
272 // Known message set type.
273 fmt.Fprintf(w, "[%s]: <\n", msd.name)
276 pb := reflect.New(msd.t.Elem())
277 if err := Unmarshal(item.Message, pb.Interface()); err != nil {
278 fmt.Fprintf(w, "/* bad message: %v */\n", err)
280 writeStruct(w, pb.Elem())
284 fmt.Fprintf(w, "[%d]: <\n", id)
286 writeUnknownStruct(w, item.Message)
289 w.Write([]byte(">\n"))
293 func writeUnknownStruct(w *textWriter, data []byte) {
295 fmt.Fprintf(w, "/* %d unknown bytes */\n", len(data))
298 for b.index < len(b.buf) {
299 x, err := b.DecodeVarint()
301 fmt.Fprintf(w, "/* %v */\n", err)
304 wire, tag := x&7, x>>3
305 if wire == WireEndGroup {
307 w.Write([]byte("}\n"))
310 fmt.Fprintf(w, "tag%d", tag)
311 if wire != WireStartGroup {
314 if !w.compact || wire == WireStartGroup {
319 buf, err := b.DecodeRawBytes(false)
321 fmt.Fprintf(w, "%q", buf)
323 fmt.Fprintf(w, "/* %v */", err)
326 x, err := b.DecodeFixed32()
327 writeUnknownInt(w, x, err)
329 x, err := b.DecodeFixed64()
330 writeUnknownInt(w, x, err)
335 x, err := b.DecodeVarint()
336 writeUnknownInt(w, x, err)
338 fmt.Fprintf(w, "/* unknown wire type %d */", wire)
344 func writeUnknownInt(w *textWriter, x uint64, err os.Error) {
348 fmt.Fprintf(w, "/* %v */", err)
352 type int32Slice []int32
354 func (s int32Slice) Len() int { return len(s) }
355 func (s int32Slice) Less(i, j int) bool { return s[i] < s[j] }
356 func (s int32Slice) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
358 // writeExtensions writes all the extensions in pv.
359 // pv is assumed to be a pointer to a protocol message struct that is extendable.
360 func writeExtensions(w *textWriter, pv reflect.Value) {
361 emap := extensionMaps[pv.Type().Elem()]
362 ep := pv.Interface().(extendableProto)
364 // Order the extensions by ID.
365 // This isn't strictly necessary, but it will give us
366 // canonical output, which will also make testing easier.
367 m := ep.ExtensionMap()
368 ids := make([]int32, 0, len(m))
370 ids = append(ids, id)
372 sort.Sort(int32Slice(ids))
374 for _, extNum := range ids {
376 var desc *ExtensionDesc
381 // Unknown extension.
382 writeUnknownStruct(w, ext.enc)
386 pb, err := GetExtension(ep, desc)
388 fmt.Fprintln(os.Stderr, "proto: failed getting extension: ", err)
392 fmt.Fprintf(w, "[%s]:", desc.Name)
396 writeAny(w, reflect.ValueOf(pb), nil)
401 func marshalText(w io.Writer, pb interface{}, compact bool) {
403 w.Write([]byte("<nil>"))
406 aw := new(textWriter)
411 v := reflect.ValueOf(pb)
412 // We should normally be passed a struct, or a pointer to a struct,
413 // and we don't want the outer < and > in that case.
414 v = reflect.Indirect(v)
415 if v.Kind() == reflect.Struct {
422 // MarshalText writes a given protocol buffer in text format.
423 // Values that are not protocol buffers can also be written, but their formatting is not guaranteed.
424 func MarshalText(w io.Writer, pb interface{}) { marshalText(w, pb, false) }
426 // CompactText writes a given protocl buffer in compact text format (one line).
427 // Values that are not protocol buffers can also be written, but their formatting is not guaranteed.
428 func CompactText(w io.Writer, pb interface{}) { marshalText(w, pb, true) }
430 // CompactTextString is the same as CompactText, but returns the string directly.
431 func CompactTextString(pb interface{}) string {
432 buf := new(bytes.Buffer)
433 marshalText(buf, pb, true)