github.com/segmentio/encoding@v0.4.0/proto/pointer.go (about) 1 package proto 2 3 import ( 4 "reflect" 5 "unsafe" 6 ) 7 8 func pointerCodecOf(t reflect.Type, seen map[reflect.Type]*codec) *codec { 9 p := new(codec) 10 seen[t] = p 11 c := codecOf(t.Elem(), seen) 12 p.wire = c.wire 13 p.size = pointerSizeFuncOf(t, c) 14 p.encode = pointerEncodeFuncOf(t, c) 15 p.decode = pointerDecodeFuncOf(t, c) 16 return p 17 } 18 19 func pointerSizeFuncOf(t reflect.Type, c *codec) sizeFunc { 20 return func(p unsafe.Pointer, flags flags) int { 21 if p != nil { 22 if !flags.has(inline) { 23 p = *(*unsafe.Pointer)(p) 24 } 25 return c.size(p, flags.without(inline).with(wantzero)) 26 } 27 return 0 28 } 29 } 30 31 func pointerEncodeFuncOf(t reflect.Type, c *codec) encodeFunc { 32 return func(b []byte, p unsafe.Pointer, flags flags) (int, error) { 33 if p != nil { 34 if !flags.has(inline) { 35 p = *(*unsafe.Pointer)(p) 36 } 37 return c.encode(b, p, flags.without(inline).with(wantzero)) 38 } 39 return 0, nil 40 } 41 } 42 43 func pointerDecodeFuncOf(t reflect.Type, c *codec) decodeFunc { 44 t = t.Elem() 45 return func(b []byte, p unsafe.Pointer, flags flags) (int, error) { 46 v := (*unsafe.Pointer)(p) 47 if *v == nil { 48 *v = unsafe.Pointer(reflect.New(t).Pointer()) 49 } 50 return c.decode(b, *v, flags) 51 } 52 }