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  }