|
|
package gen
import ( "fmt" "io"
"github.com/tinylib/msgp/msgp" )
func marshal(w io.Writer) *marshalGen { return &marshalGen{ p: printer{w: w}, } }
type marshalGen struct { passes p printer fuse []byte }
func (m *marshalGen) Method() Method { return Marshal }
func (m *marshalGen) Apply(dirs []string) error { return nil }
func (m *marshalGen) Execute(p Elem) error { if !m.p.ok() { return m.p.err } p = m.applyall(p) if p == nil { return nil } if !IsPrintable(p) { return nil }
m.p.comment("MarshalMsg implements msgp.Marshaler")
// save the vname before
// calling methodReceiver so
// that z.Msgsize() is printed correctly
c := p.Varname()
m.p.printf("\nfunc (%s %s) MarshalMsg(b []byte) (o []byte, err error) {", p.Varname(), imutMethodReceiver(p)) m.p.printf("\no = msgp.Require(b, %s.Msgsize())", c) next(m, p) m.p.nakedReturn() return m.p.err }
func (m *marshalGen) rawAppend(typ string, argfmt string, arg interface{}) { m.p.printf("\no = msgp.Append%s(o, %s)", typ, fmt.Sprintf(argfmt, arg)) }
func (m *marshalGen) fuseHook() { if len(m.fuse) > 0 { m.rawbytes(m.fuse) m.fuse = m.fuse[:0] } }
func (m *marshalGen) Fuse(b []byte) { if len(m.fuse) == 0 { m.fuse = b } else { m.fuse = append(m.fuse, b...) } }
func (m *marshalGen) gStruct(s *Struct) { if !m.p.ok() { return }
if s.AsTuple { m.tuple(s) } else { m.mapstruct(s) } return }
func (m *marshalGen) tuple(s *Struct) { data := make([]byte, 0, 5) data = msgp.AppendArrayHeader(data, uint32(len(s.Fields))) m.p.printf("\n// array header, size %d", len(s.Fields)) m.Fuse(data) if len(s.Fields) == 0 { m.fuseHook() } for i := range s.Fields { if !m.p.ok() { return } next(m, s.Fields[i].FieldElem) } }
func (m *marshalGen) mapstruct(s *Struct) { data := make([]byte, 0, 64) data = msgp.AppendMapHeader(data, uint32(len(s.Fields))) m.p.printf("\n// map header, size %d", len(s.Fields)) m.Fuse(data) if len(s.Fields) == 0 { m.fuseHook() } for i := range s.Fields { if !m.p.ok() { return } data = msgp.AppendString(nil, s.Fields[i].FieldTag)
m.p.printf("\n// string %q", s.Fields[i].FieldTag) m.Fuse(data)
next(m, s.Fields[i].FieldElem) } }
// append raw data
func (m *marshalGen) rawbytes(bts []byte) { m.p.print("\no = append(o, ") for _, b := range bts { m.p.printf("0x%x,", b) } m.p.print(")") }
func (m *marshalGen) gMap(s *Map) { if !m.p.ok() { return } m.fuseHook() vname := s.Varname() m.rawAppend(mapHeader, lenAsUint32, vname) m.p.printf("\nfor %s, %s := range %s {", s.Keyidx, s.Validx, vname) m.rawAppend(stringTyp, literalFmt, s.Keyidx) next(m, s.Value) m.p.closeblock() }
func (m *marshalGen) gSlice(s *Slice) { if !m.p.ok() { return } m.fuseHook() vname := s.Varname() m.rawAppend(arrayHeader, lenAsUint32, vname) m.p.rangeBlock(s.Index, vname, m, s.Els) }
func (m *marshalGen) gArray(a *Array) { if !m.p.ok() { return } m.fuseHook() if be, ok := a.Els.(*BaseElem); ok && be.Value == Byte { m.rawAppend("Bytes", "(%s)[:]", a.Varname()) return }
m.rawAppend(arrayHeader, literalFmt, coerceArraySize(a.Size)) m.p.rangeBlock(a.Index, a.Varname(), m, a.Els) }
func (m *marshalGen) gPtr(p *Ptr) { if !m.p.ok() { return } m.fuseHook() m.p.printf("\nif %s == nil {\no = msgp.AppendNil(o)\n} else {", p.Varname()) next(m, p.Value) m.p.closeblock() }
func (m *marshalGen) gBase(b *BaseElem) { if !m.p.ok() { return } m.fuseHook() vname := b.Varname()
if b.Convert { if b.ShimMode == Cast { vname = tobaseConvert(b) } else { vname = randIdent() m.p.printf("\nvar %s %s", vname, b.BaseType()) m.p.printf("\n%s, err = %s", vname, tobaseConvert(b)) m.p.printf(errcheck) } }
var echeck bool switch b.Value { case IDENT: echeck = true m.p.printf("\no, err = %s.MarshalMsg(o)", vname) case Intf, Ext: echeck = true m.p.printf("\no, err = msgp.Append%s(o, %s)", b.BaseName(), vname) default: m.rawAppend(b.BaseName(), literalFmt, vname) }
if echeck { m.p.print(errcheck) } }
|