blob: 498cb751fe5f76f6c298035a9db3dfc0443afffe [file] [log] [blame]
Rob Pikeaaa3a622010-03-20 22:32:34 -07001// 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
32/*
33 The proto package converts data structures to and from the
34 wire format of protocol buffers. It works in concert with the
35 Go source code generated for .proto files by the protocol compiler.
36
37 A summary of the properties of the protocol buffer interface
38 for a protocol buffer variable v:
39
40 - Names are turned from camel_case to CamelCase for export.
41 - There are no methods on v to set and get fields; just treat
42 them as structure fields.
43 - The zero value for a struct is its correct initialization state.
44 All desired fields must be set before marshaling.
45 - A Reset() method will restore a protobuf struct to its zero state.
Rob Pikeaaa3a622010-03-20 22:32:34 -070046 - Non-repeated fields are pointers to the values; nil means unset.
47 That is, optional or required field int32 f becomes F *int32.
48 - Repeated fields are slices.
49 - Helper functions are available to simplify the getting and setting of fields:
50 foo.String = proto.String("hello") // set field
51 s := proto.GetString(foo.String) // get field
52 - Constants are defined to hold the default values of all fields that
53 have them. They have the form Default_StructName_FieldName.
54 - Enums are given type names and maps between names to values,
55 plus a helper function to create values. Enum values are prefixed
David Symonds350c58f2011-08-03 12:09:32 +100056 with the enum's type name. Enum types have a String method.
Rob Pikeaaa3a622010-03-20 22:32:34 -070057 - Nested groups and enums have type names prefixed with the name of
58 the surrounding message type.
David Symonds9bd0a832010-04-11 10:02:32 +100059 - Extensions are given descriptor names that start with E_,
60 followed by an underscore-delimited list of the nested messages
61 that contain it (if any) followed by the CamelCased name of the
62 extension field itself. HasExtension, ClearExtension, GetExtension
63 and SetExtension are functions for manipulating extensions.
Rob Pikeaaa3a622010-03-20 22:32:34 -070064 - Marshal and Unmarshal are functions to encode and decode the wire format.
65
66 The simplest way to describe this is to see an example.
67 Given file test.proto, containing
68
69 package example;
70
71 enum FOO { X = 17; };
72
73 message Test {
74 required string label = 1;
75 optional int32 type = 2 [default=77];
76 repeated int64 reps = 3;
77 optional group OptionalGroup = 4 {
78 required string RequiredField = 5;
79 };
80 }
81
82 The resulting file, test.pb.go, is:
83
84 package example
85
86 import "goprotobuf.googlecode.com/hg/proto"
87
88 type FOO int32
89 const (
90 FOO_X = 17
91 )
92 var FOO_name = map[int32] string {
93 17: "X",
94 }
95 var FOO_value = map[string] int32 {
96 "X": 17,
97 }
98 func NewFOO(x int32) *FOO {
99 e := FOO(x)
100 return &e
101 }
David Symonds350c58f2011-08-03 12:09:32 +1000102 func (x FOO) String() string {
103 return proto.EnumName(FOO_name, int32(x))
104 }
Rob Pikeaaa3a622010-03-20 22:32:34 -0700105
106 type Test struct {
David Symonds8935abf2011-07-04 15:53:16 +1000107 Label *string `protobuf:"bytes,1,req,name=label"`
108 Type *int32 `protobuf:"varint,2,opt,name=type,def=77"`
109 Reps []int64 `protobuf:"varint,3,rep,name=reps"`
110 Optionalgroup *Test_OptionalGroup `protobuf:"group,4,opt,name=optionalgroup"`
Rob Pikeaaa3a622010-03-20 22:32:34 -0700111 XXX_unrecognized []byte
112 }
113 func (this *Test) Reset() {
114 *this = Test{}
115 }
Rob Pikeaaa3a622010-03-20 22:32:34 -0700116 const Default_Test_Type int32 = 77
117
118 type Test_OptionalGroup struct {
David Symonds8935abf2011-07-04 15:53:16 +1000119 RequiredField *string `protobuf:"bytes,5,req"`
Rob Pikeaaa3a622010-03-20 22:32:34 -0700120 XXX_unrecognized []byte
121 }
122 func (this *Test_OptionalGroup) Reset() {
123 *this = Test_OptionalGroup{}
124 }
Rob Pikeaaa3a622010-03-20 22:32:34 -0700125
126 func init() {
127 proto.RegisterEnum("example.FOO", FOO_name, FOO_value)
128 }
129
130 To create and play with a Test object:
131
132 package main
133
134 import (
135 "log"
136
137 "goprotobuf.googlecode.com/hg/proto"
138 "./example.pb"
139 )
140
141 func main() {
David Symondscc7142e2010-11-06 14:37:15 +1100142 test := &example.Test{
Rob Pikeaaa3a622010-03-20 22:32:34 -0700143 Label: proto.String("hello"),
144 Type: proto.Int32(17),
David Symondscc7142e2010-11-06 14:37:15 +1100145 Optionalgroup: &example.Test_OptionalGroup{
Rob Pikeaaa3a622010-03-20 22:32:34 -0700146 RequiredField: proto.String("good bye"),
147 },
148 }
149 data, err := proto.Marshal(test)
150 if err != nil {
Rob Pike4202e4d2011-02-11 16:06:41 -0800151 log.Fatal("marshaling error: ", err)
Rob Pikeaaa3a622010-03-20 22:32:34 -0700152 }
David Symondscc7142e2010-11-06 14:37:15 +1100153 newTest := new(example.Test)
Rob Pikeaaa3a622010-03-20 22:32:34 -0700154 err = proto.Unmarshal(data, newTest)
155 if err != nil {
Rob Pike4202e4d2011-02-11 16:06:41 -0800156 log.Fatal("unmarshaling error: ", err)
Rob Pikeaaa3a622010-03-20 22:32:34 -0700157 }
158 // Now test and newTest contain the same data.
159 if proto.GetString(test.Label) != proto.GetString(newTest.Label) {
Rob Pike4202e4d2011-02-11 16:06:41 -0800160 log.Fatalf("data mismatch %q != %q", proto.GetString(test.Label), proto.GetString(newTest.Label))
Rob Pikeaaa3a622010-03-20 22:32:34 -0700161 }
162 // etc.
163 }
164*/
165package proto
166
167import (
168 "fmt"
David Symondsb79d99b2011-08-29 16:38:49 +1000169 "log"
170 "reflect"
Rob Pikeaaa3a622010-03-20 22:32:34 -0700171 "strconv"
David Symondsb79d99b2011-08-29 16:38:49 +1000172 "sync"
Rob Pikeaaa3a622010-03-20 22:32:34 -0700173)
174
175// Stats records allocation details about the protocol buffer encoders
176// and decoders. Useful for tuning the library itself.
177type Stats struct {
178 Emalloc uint64 // mallocs in encode
179 Dmalloc uint64 // mallocs in decode
180 Encode uint64 // number of encodes
181 Decode uint64 // number of decodes
182 Chit uint64 // number of cache hits
183 Cmiss uint64 // number of cache misses
184}
185
186var stats Stats
187
188// GetStats returns a copy of the global Stats structure.
189func GetStats() Stats { return stats }
190
191// A Buffer is a buffer manager for marshaling and unmarshaling
192// protocol buffers. It may be reused between invocations to
193// reduce memory usage. It is not necessary to use a Buffer;
194// the global functions Marshal and Unmarshal create a
195// temporary Buffer and are fine for most applications.
196type Buffer struct {
197 buf []byte // encode/decode byte stream
198 index int // write point
199 freelist [10][]byte // list of available buffers
200 nfreelist int // number of free buffers
David Symonds049646b2011-10-21 11:13:45 +1100201 ptr uintptr // used to avoid a heap allocation.
Rob Pike76f6ee52011-10-20 12:58:28 -0700202 // pools of basic types to amortize allocation.
David Symonds049646b2011-10-21 11:13:45 +1100203 bools []bool
Rob Pike76f6ee52011-10-20 12:58:28 -0700204 int32s []int32
205 int64s []int64
Rob Pikeaaa3a622010-03-20 22:32:34 -0700206}
207
208// NewBuffer allocates a new Buffer and initializes its internal data to
209// the contents of the argument slice.
210func NewBuffer(e []byte) *Buffer {
211 p := new(Buffer)
212 if e == nil {
213 e = p.bufalloc()
214 }
215 p.buf = e
216 p.index = 0
217 return p
218}
219
220// Reset resets the Buffer, ready for marshaling a new protocol buffer.
221func (p *Buffer) Reset() {
222 if p.buf == nil {
223 p.buf = p.bufalloc()
224 }
225 p.buf = p.buf[0:0] // for reading/writing
226 p.index = 0 // for reading
227}
228
229// SetBuf replaces the internal buffer with the slice,
230// ready for unmarshaling the contents of the slice.
231func (p *Buffer) SetBuf(s []byte) {
232 p.buf = s
233 p.index = 0
234}
235
236// Bytes returns the contents of the Buffer.
237func (p *Buffer) Bytes() []byte { return p.buf }
238
239// Allocate a buffer for the Buffer.
240func (p *Buffer) bufalloc() []byte {
241 if p.nfreelist > 0 {
242 // reuse an old one
243 p.nfreelist--
244 s := p.freelist[p.nfreelist]
245 return s[0:0]
246 }
247 // make a new one
248 s := make([]byte, 0, 16)
249 return s
250}
251
252// Free (and remember in freelist) a byte buffer for the Buffer.
253func (p *Buffer) buffree(s []byte) {
254 if p.nfreelist < len(p.freelist) {
255 // Take next slot.
256 p.freelist[p.nfreelist] = s
257 p.nfreelist++
258 return
259 }
260
261 // Find the smallest.
262 besti := -1
263 bestl := len(s)
264 for i, b := range p.freelist {
265 if len(b) < bestl {
266 besti = i
267 bestl = len(b)
268 }
269 }
270
271 // Overwrite the smallest.
272 if besti >= 0 {
273 p.freelist[besti] = s
274 }
275}
276
277/*
278 * Helper routines for simplifying the creation of optional fields of basic type.
279 */
280
281// Bool is a helper routine that allocates a new bool value
282// to store v and returns a pointer to it.
283func Bool(v bool) *bool {
284 p := new(bool)
285 *p = v
286 return p
287}
288
289// Int32 is a helper routine that allocates a new int32 value
290// to store v and returns a pointer to it.
291func Int32(v int32) *int32 {
292 p := new(int32)
293 *p = v
294 return p
295}
296
297// Int is a helper routine that allocates a new int32 value
298// to store v and returns a pointer to it, but unlike Int32
299// its argument value is an int.
300func Int(v int) *int32 {
301 p := new(int32)
302 *p = int32(v)
303 return p
304}
305
306// Int64 is a helper routine that allocates a new int64 value
307// to store v and returns a pointer to it.
308func Int64(v int64) *int64 {
309 p := new(int64)
310 *p = v
311 return p
312}
313
314// Float32 is a helper routine that allocates a new float32 value
315// to store v and returns a pointer to it.
316func Float32(v float32) *float32 {
317 p := new(float32)
318 *p = v
319 return p
320}
321
322// Float64 is a helper routine that allocates a new float64 value
323// to store v and returns a pointer to it.
324func Float64(v float64) *float64 {
325 p := new(float64)
326 *p = v
327 return p
328}
329
330// Uint32 is a helper routine that allocates a new uint32 value
331// to store v and returns a pointer to it.
332func Uint32(v uint32) *uint32 {
333 p := new(uint32)
334 *p = v
335 return p
336}
337
338// Uint64 is a helper routine that allocates a new uint64 value
339// to store v and returns a pointer to it.
340func Uint64(v uint64) *uint64 {
341 p := new(uint64)
342 *p = v
343 return p
344}
345
346// String is a helper routine that allocates a new string value
347// to store v and returns a pointer to it.
348func String(v string) *string {
349 p := new(string)
350 *p = v
351 return p
352}
353
354/*
355 * Helper routines for simplifying the fetching of optional fields of basic type.
356 * If the field is missing, they return the zero for the type.
357 */
358
359// GetBool is a helper routine that returns an optional bool value.
360func GetBool(p *bool) bool {
361 if p == nil {
362 return false
363 }
364 return *p
365}
366
367// GetInt32 is a helper routine that returns an optional int32 value.
368func GetInt32(p *int32) int32 {
369 if p == nil {
370 return 0
371 }
372 return *p
373}
374
375// GetInt64 is a helper routine that returns an optional int64 value.
376func GetInt64(p *int64) int64 {
377 if p == nil {
378 return 0
379 }
380 return *p
381}
382
383// GetFloat32 is a helper routine that returns an optional float32 value.
384func GetFloat32(p *float32) float32 {
385 if p == nil {
386 return 0
387 }
388 return *p
389}
390
391// GetFloat64 is a helper routine that returns an optional float64 value.
392func GetFloat64(p *float64) float64 {
393 if p == nil {
394 return 0
395 }
396 return *p
397}
398
399// GetUint32 is a helper routine that returns an optional uint32 value.
400func GetUint32(p *uint32) uint32 {
401 if p == nil {
402 return 0
403 }
404 return *p
405}
406
407// GetUint64 is a helper routine that returns an optional uint64 value.
408func GetUint64(p *uint64) uint64 {
409 if p == nil {
410 return 0
411 }
412 return *p
413}
414
415// GetString is a helper routine that returns an optional string value.
416func GetString(p *string) string {
417 if p == nil {
418 return ""
419 }
420 return *p
421}
422
423// EnumName is a helper function to simplify printing protocol buffer enums
424// by name. Given an enum map and a value, it returns a useful string.
425func EnumName(m map[int32]string, v int32) string {
426 s, ok := m[v]
427 if ok {
428 return s
429 }
430 return "unknown_enum_" + strconv.Itoa(int(v))
431}
432
433// DebugPrint dumps the encoded data in b in a debugging format with a header
434// including the string s. Used in testing but made available for general debugging.
435func (o *Buffer) DebugPrint(s string, b []byte) {
436 var u uint64
437
438 obuf := o.buf
439 index := o.index
440 o.buf = b
441 o.index = 0
442 depth := 0
443
444 fmt.Printf("\n--- %s ---\n", s)
445
446out:
447 for {
448 for i := 0; i < depth; i++ {
449 fmt.Print(" ")
450 }
451
452 index := o.index
453 if index == len(o.buf) {
454 break
455 }
456
457 op, err := o.DecodeVarint()
458 if err != nil {
459 fmt.Printf("%3d: fetching op err %v\n", index, err)
460 break out
461 }
462 tag := op >> 3
463 wire := op & 7
464
465 switch wire {
466 default:
467 fmt.Printf("%3d: t=%3d unknown wire=%d\n",
468 index, tag, wire)
469 break out
470
471 case WireBytes:
472 var r []byte
473
474 r, err = o.DecodeRawBytes(false)
475 if err != nil {
476 break out
477 }
478 fmt.Printf("%3d: t=%3d bytes [%d]", index, tag, len(r))
479 if len(r) <= 6 {
480 for i := 0; i < len(r); i++ {
481 fmt.Printf(" %.2x", r[i])
482 }
483 } else {
484 for i := 0; i < 3; i++ {
485 fmt.Printf(" %.2x", r[i])
486 }
487 fmt.Printf(" ..")
488 for i := len(r) - 3; i < len(r); i++ {
489 fmt.Printf(" %.2x", r[i])
490 }
491 }
492 fmt.Printf("\n")
493
494 case WireFixed32:
495 u, err = o.DecodeFixed32()
496 if err != nil {
497 fmt.Printf("%3d: t=%3d fix32 err %v\n", index, tag, err)
498 break out
499 }
500 fmt.Printf("%3d: t=%3d fix32 %d\n", index, tag, u)
501
502 case WireFixed64:
503 u, err = o.DecodeFixed64()
504 if err != nil {
505 fmt.Printf("%3d: t=%3d fix64 err %v\n", index, tag, err)
506 break out
507 }
508 fmt.Printf("%3d: t=%3d fix64 %d\n", index, tag, u)
509 break
510
511 case WireVarint:
512 u, err = o.DecodeVarint()
513 if err != nil {
514 fmt.Printf("%3d: t=%3d varint err %v\n", index, tag, err)
515 break out
516 }
517 fmt.Printf("%3d: t=%3d varint %d\n", index, tag, u)
518
519 case WireStartGroup:
520 if err != nil {
521 fmt.Printf("%3d: t=%3d start err %v\n", index, tag, err)
522 break out
523 }
524 fmt.Printf("%3d: t=%3d start\n", index, tag)
525 depth++
526
527 case WireEndGroup:
528 depth--
529 if err != nil {
530 fmt.Printf("%3d: t=%3d end err %v\n", index, tag, err)
531 break out
532 }
533 fmt.Printf("%3d: t=%3d end\n", index, tag)
534 }
535 }
536
537 if depth != 0 {
538 fmt.Printf("%3d: start-end not balanced %d\n", o.index, depth)
539 }
540 fmt.Printf("\n")
541
542 o.buf = obuf
543 o.index = index
544}
David Symondsb79d99b2011-08-29 16:38:49 +1000545
546// SetDefaults sets unset protocol buffer fields to their default values.
547// It only modifies fields that are both unset and have defined defaults.
548// It recursively sets default values in any non-nil sub-messages.
549func SetDefaults(pb interface{}) {
550 v := reflect.ValueOf(pb)
551 if v.Kind() != reflect.Ptr || v.Elem().Kind() != reflect.Struct {
552 log.Printf("proto: hit non-pointer-to-struct %v", v)
553 }
554 setDefaults(v, true, false)
555}
556
557// v is a pointer to a struct.
558func setDefaults(v reflect.Value, recur, zeros bool) {
559 v = v.Elem()
560
David Symonds72607582011-11-01 12:52:01 +1100561 defaultMu.RLock()
David Symondsb79d99b2011-08-29 16:38:49 +1000562 dm, ok := defaults[v.Type()]
David Symonds72607582011-11-01 12:52:01 +1100563 defaultMu.RUnlock()
David Symondsb79d99b2011-08-29 16:38:49 +1000564 if !ok {
565 dm = buildDefaultMessage(v.Type())
566 defaultMu.Lock()
567 defaults[v.Type()] = dm
568 defaultMu.Unlock()
569 }
570
571 for _, sf := range dm.scalars {
572 f := v.Field(sf.index)
573 if !f.IsNil() {
574 // field already set
575 continue
576 }
577 dv := sf.value
578 if dv == nil && !zeros {
579 // no explicit default, and don't want to set zeros
580 continue
581 }
582 fptr := f.Addr().Interface() // **T
583 // TODO: Consider batching the allocations we do here.
584 switch sf.kind {
585 case reflect.Bool:
586 b := new(bool)
587 if dv != nil {
588 *b = dv.(bool)
589 }
590 *(fptr.(**bool)) = b
591 case reflect.Float32:
592 f := new(float32)
593 if dv != nil {
594 *f = dv.(float32)
595 }
596 *(fptr.(**float32)) = f
597 case reflect.Float64:
598 f := new(float64)
599 if dv != nil {
600 *f = dv.(float64)
601 }
602 *(fptr.(**float64)) = f
603 case reflect.Int32:
604 // might be an enum
605 if ft := f.Type(); ft != int32PtrType {
606 // enum
607 f.Set(reflect.New(ft.Elem()))
608 if dv != nil {
609 f.Elem().SetInt(int64(dv.(int32)))
610 }
611 } else {
612 // int32 field
613 i := new(int32)
614 if dv != nil {
615 *i = dv.(int32)
616 }
617 *(fptr.(**int32)) = i
618 }
619 case reflect.Int64:
620 i := new(int64)
621 if dv != nil {
622 *i = dv.(int64)
623 }
624 *(fptr.(**int64)) = i
625 case reflect.String:
626 s := new(string)
627 if dv != nil {
628 *s = dv.(string)
629 }
630 *(fptr.(**string)) = s
631 case reflect.Uint8:
632 // exceptional case: []byte
633 var b []byte
634 if dv != nil {
635 db := dv.([]byte)
636 b = make([]byte, len(db))
637 copy(b, db)
638 } else {
639 b = []byte{}
640 }
641 *(fptr.(*[]byte)) = b
642 case reflect.Uint32:
643 u := new(uint32)
644 if dv != nil {
645 *u = dv.(uint32)
646 }
647 *(fptr.(**uint32)) = u
648 case reflect.Uint64:
649 u := new(uint64)
650 if dv != nil {
651 *u = dv.(uint64)
652 }
653 *(fptr.(**uint64)) = u
654 default:
655 log.Printf("proto: can't set default for field %v (sf.kind=%v)", f, sf.kind)
656 }
657 }
658
659 for _, ni := range dm.nested {
David Symonds814b9362011-12-13 09:10:47 +1100660 f := v.Field(ni)
661 if f.IsNil() {
662 continue
663 }
664 setDefaults(f, recur, zeros)
David Symondsb79d99b2011-08-29 16:38:49 +1000665 }
666}
667
668var (
669 // defaults maps a protocol buffer struct type to a slice of the fields,
670 // with its scalar fields set to their proto-declared non-zero default values.
David Symonds72607582011-11-01 12:52:01 +1100671 defaultMu sync.RWMutex
David Symondsb79d99b2011-08-29 16:38:49 +1000672 defaults = make(map[reflect.Type]defaultMessage)
673
674 int32PtrType = reflect.TypeOf((*int32)(nil))
675)
676
677// defaultMessage represents information about the default values of a message.
678type defaultMessage struct {
679 scalars []scalarField
680 nested []int // struct field index of nested messages
681}
682
683type scalarField struct {
684 index int // struct field index
685 kind reflect.Kind // element type (the T in *T or []T)
686 value interface{} // the proto-declared default value, or nil
687}
688
689// t is a struct type.
690func buildDefaultMessage(t reflect.Type) (dm defaultMessage) {
691 sprop := GetProperties(t)
692 for _, prop := range sprop.Prop {
693 fi := sprop.tags[prop.Tag]
694 ft := t.Field(fi).Type
695
696 // nested messages
697 if ft.Kind() == reflect.Ptr && ft.Elem().Kind() == reflect.Struct {
698 dm.nested = append(dm.nested, fi)
699 continue
700 }
701
702 sf := scalarField{
703 index: fi,
704 kind: ft.Elem().Kind(),
705 }
706
707 // scalar fields without defaults
708 if prop.Default == "" {
709 dm.scalars = append(dm.scalars, sf)
710 continue
711 }
712
713 // a scalar field: either *T or []byte
714 switch ft.Elem().Kind() {
715 case reflect.Bool:
David Symonds93be46f2011-12-08 12:58:23 +1100716 x, err := strconv.ParseBool(prop.Default)
David Symondsb79d99b2011-08-29 16:38:49 +1000717 if err != nil {
718 log.Printf("proto: bad default bool %q: %v", prop.Default, err)
719 continue
720 }
721 sf.value = x
722 case reflect.Float32:
David Symonds93be46f2011-12-08 12:58:23 +1100723 x, err := strconv.ParseFloat(prop.Default, 32)
David Symondsb79d99b2011-08-29 16:38:49 +1000724 if err != nil {
725 log.Printf("proto: bad default float32 %q: %v", prop.Default, err)
726 continue
727 }
David Symonds93be46f2011-12-08 12:58:23 +1100728 sf.value = float32(x)
David Symondsb79d99b2011-08-29 16:38:49 +1000729 case reflect.Float64:
David Symonds93be46f2011-12-08 12:58:23 +1100730 x, err := strconv.ParseFloat(prop.Default, 64)
David Symondsb79d99b2011-08-29 16:38:49 +1000731 if err != nil {
732 log.Printf("proto: bad default float64 %q: %v", prop.Default, err)
733 continue
734 }
735 sf.value = x
736 case reflect.Int32:
David Symonds93be46f2011-12-08 12:58:23 +1100737 x, err := strconv.ParseInt(prop.Default, 10, 32)
David Symondsb79d99b2011-08-29 16:38:49 +1000738 if err != nil {
739 log.Printf("proto: bad default int32 %q: %v", prop.Default, err)
740 continue
741 }
742 sf.value = int32(x)
743 case reflect.Int64:
David Symonds93be46f2011-12-08 12:58:23 +1100744 x, err := strconv.ParseInt(prop.Default, 10, 64)
David Symondsb79d99b2011-08-29 16:38:49 +1000745 if err != nil {
746 log.Printf("proto: bad default int64 %q: %v", prop.Default, err)
747 continue
748 }
749 sf.value = x
750 case reflect.String:
751 sf.value = prop.Default
752 case reflect.Uint8:
753 // []byte (not *uint8)
754 sf.value = []byte(prop.Default)
755 case reflect.Uint32:
David Symonds93be46f2011-12-08 12:58:23 +1100756 x, err := strconv.ParseUint(prop.Default, 10, 32)
David Symondsb79d99b2011-08-29 16:38:49 +1000757 if err != nil {
758 log.Printf("proto: bad default uint32 %q: %v", prop.Default, err)
759 continue
760 }
761 sf.value = uint32(x)
762 case reflect.Uint64:
David Symonds93be46f2011-12-08 12:58:23 +1100763 x, err := strconv.ParseUint(prop.Default, 10, 64)
David Symondsb79d99b2011-08-29 16:38:49 +1000764 if err != nil {
765 log.Printf("proto: bad default uint64 %q: %v", prop.Default, err)
766 continue
767 }
768 sf.value = x
769 default:
770 log.Printf("proto: unhandled def kind %v", ft.Elem().Kind())
771 continue
772 }
773
774 dm.scalars = append(dm.scalars, sf)
775 }
776
777 return dm
778}