codec_reflect.go (5412B)
1 // Copyright 2019 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 //go:build purego || appengine 6 // +build purego appengine 7 8 package impl 9 10 import ( 11 "reflect" 12 13 "google.golang.org/protobuf/encoding/protowire" 14 ) 15 16 func sizeEnum(p pointer, f *coderFieldInfo, _ marshalOptions) (size int) { 17 v := p.v.Elem().Int() 18 return f.tagsize + protowire.SizeVarint(uint64(v)) 19 } 20 21 func appendEnum(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { 22 v := p.v.Elem().Int() 23 b = protowire.AppendVarint(b, f.wiretag) 24 b = protowire.AppendVarint(b, uint64(v)) 25 return b, nil 26 } 27 28 func consumeEnum(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, _ unmarshalOptions) (out unmarshalOutput, err error) { 29 if wtyp != protowire.VarintType { 30 return out, errUnknown 31 } 32 v, n := protowire.ConsumeVarint(b) 33 if n < 0 { 34 return out, errDecode 35 } 36 p.v.Elem().SetInt(int64(v)) 37 out.n = n 38 return out, nil 39 } 40 41 func mergeEnum(dst, src pointer, _ *coderFieldInfo, _ mergeOptions) { 42 dst.v.Elem().Set(src.v.Elem()) 43 } 44 45 var coderEnum = pointerCoderFuncs{ 46 size: sizeEnum, 47 marshal: appendEnum, 48 unmarshal: consumeEnum, 49 merge: mergeEnum, 50 } 51 52 func sizeEnumNoZero(p pointer, f *coderFieldInfo, opts marshalOptions) (size int) { 53 if p.v.Elem().Int() == 0 { 54 return 0 55 } 56 return sizeEnum(p, f, opts) 57 } 58 59 func appendEnumNoZero(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { 60 if p.v.Elem().Int() == 0 { 61 return b, nil 62 } 63 return appendEnum(b, p, f, opts) 64 } 65 66 func mergeEnumNoZero(dst, src pointer, _ *coderFieldInfo, _ mergeOptions) { 67 if src.v.Elem().Int() != 0 { 68 dst.v.Elem().Set(src.v.Elem()) 69 } 70 } 71 72 var coderEnumNoZero = pointerCoderFuncs{ 73 size: sizeEnumNoZero, 74 marshal: appendEnumNoZero, 75 unmarshal: consumeEnum, 76 merge: mergeEnumNoZero, 77 } 78 79 func sizeEnumPtr(p pointer, f *coderFieldInfo, opts marshalOptions) (size int) { 80 return sizeEnum(pointer{p.v.Elem()}, f, opts) 81 } 82 83 func appendEnumPtr(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { 84 return appendEnum(b, pointer{p.v.Elem()}, f, opts) 85 } 86 87 func consumeEnumPtr(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) { 88 if wtyp != protowire.VarintType { 89 return out, errUnknown 90 } 91 if p.v.Elem().IsNil() { 92 p.v.Elem().Set(reflect.New(p.v.Elem().Type().Elem())) 93 } 94 return consumeEnum(b, pointer{p.v.Elem()}, wtyp, f, opts) 95 } 96 97 func mergeEnumPtr(dst, src pointer, _ *coderFieldInfo, _ mergeOptions) { 98 if !src.v.Elem().IsNil() { 99 v := reflect.New(dst.v.Type().Elem().Elem()) 100 v.Elem().Set(src.v.Elem().Elem()) 101 dst.v.Elem().Set(v) 102 } 103 } 104 105 var coderEnumPtr = pointerCoderFuncs{ 106 size: sizeEnumPtr, 107 marshal: appendEnumPtr, 108 unmarshal: consumeEnumPtr, 109 merge: mergeEnumPtr, 110 } 111 112 func sizeEnumSlice(p pointer, f *coderFieldInfo, opts marshalOptions) (size int) { 113 s := p.v.Elem() 114 for i, llen := 0, s.Len(); i < llen; i++ { 115 size += protowire.SizeVarint(uint64(s.Index(i).Int())) + f.tagsize 116 } 117 return size 118 } 119 120 func appendEnumSlice(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { 121 s := p.v.Elem() 122 for i, llen := 0, s.Len(); i < llen; i++ { 123 b = protowire.AppendVarint(b, f.wiretag) 124 b = protowire.AppendVarint(b, uint64(s.Index(i).Int())) 125 } 126 return b, nil 127 } 128 129 func consumeEnumSlice(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) { 130 s := p.v.Elem() 131 if wtyp == protowire.BytesType { 132 b, n := protowire.ConsumeBytes(b) 133 if n < 0 { 134 return out, errDecode 135 } 136 for len(b) > 0 { 137 v, n := protowire.ConsumeVarint(b) 138 if n < 0 { 139 return out, errDecode 140 } 141 rv := reflect.New(s.Type().Elem()).Elem() 142 rv.SetInt(int64(v)) 143 s.Set(reflect.Append(s, rv)) 144 b = b[n:] 145 } 146 out.n = n 147 return out, nil 148 } 149 if wtyp != protowire.VarintType { 150 return out, errUnknown 151 } 152 v, n := protowire.ConsumeVarint(b) 153 if n < 0 { 154 return out, errDecode 155 } 156 rv := reflect.New(s.Type().Elem()).Elem() 157 rv.SetInt(int64(v)) 158 s.Set(reflect.Append(s, rv)) 159 out.n = n 160 return out, nil 161 } 162 163 func mergeEnumSlice(dst, src pointer, _ *coderFieldInfo, _ mergeOptions) { 164 dst.v.Elem().Set(reflect.AppendSlice(dst.v.Elem(), src.v.Elem())) 165 } 166 167 var coderEnumSlice = pointerCoderFuncs{ 168 size: sizeEnumSlice, 169 marshal: appendEnumSlice, 170 unmarshal: consumeEnumSlice, 171 merge: mergeEnumSlice, 172 } 173 174 func sizeEnumPackedSlice(p pointer, f *coderFieldInfo, opts marshalOptions) (size int) { 175 s := p.v.Elem() 176 llen := s.Len() 177 if llen == 0 { 178 return 0 179 } 180 n := 0 181 for i := 0; i < llen; i++ { 182 n += protowire.SizeVarint(uint64(s.Index(i).Int())) 183 } 184 return f.tagsize + protowire.SizeBytes(n) 185 } 186 187 func appendEnumPackedSlice(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { 188 s := p.v.Elem() 189 llen := s.Len() 190 if llen == 0 { 191 return b, nil 192 } 193 b = protowire.AppendVarint(b, f.wiretag) 194 n := 0 195 for i := 0; i < llen; i++ { 196 n += protowire.SizeVarint(uint64(s.Index(i).Int())) 197 } 198 b = protowire.AppendVarint(b, uint64(n)) 199 for i := 0; i < llen; i++ { 200 b = protowire.AppendVarint(b, uint64(s.Index(i).Int())) 201 } 202 return b, nil 203 } 204 205 var coderEnumPackedSlice = pointerCoderFuncs{ 206 size: sizeEnumPackedSlice, 207 marshal: appendEnumPackedSlice, 208 unmarshal: consumeEnumSlice, 209 merge: mergeEnumSlice, 210 }