xref: /aosp_15_r20/external/golang-protobuf/internal/impl/codec_reflect.go (revision 1c12ee1efe575feb122dbf939ff15148a3b3e8f2)
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
8package impl
9
10import (
11	"reflect"
12
13	"google.golang.org/protobuf/encoding/protowire"
14)
15
16func sizeEnum(p pointer, f *coderFieldInfo, _ marshalOptions) (size int) {
17	v := p.v.Elem().Int()
18	return f.tagsize + protowire.SizeVarint(uint64(v))
19}
20
21func 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
28func 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
41func mergeEnum(dst, src pointer, _ *coderFieldInfo, _ mergeOptions) {
42	dst.v.Elem().Set(src.v.Elem())
43}
44
45var coderEnum = pointerCoderFuncs{
46	size:      sizeEnum,
47	marshal:   appendEnum,
48	unmarshal: consumeEnum,
49	merge:     mergeEnum,
50}
51
52func 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
59func 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
66func mergeEnumNoZero(dst, src pointer, _ *coderFieldInfo, _ mergeOptions) {
67	if src.v.Elem().Int() != 0 {
68		dst.v.Elem().Set(src.v.Elem())
69	}
70}
71
72var coderEnumNoZero = pointerCoderFuncs{
73	size:      sizeEnumNoZero,
74	marshal:   appendEnumNoZero,
75	unmarshal: consumeEnum,
76	merge:     mergeEnumNoZero,
77}
78
79func sizeEnumPtr(p pointer, f *coderFieldInfo, opts marshalOptions) (size int) {
80	return sizeEnum(pointer{p.v.Elem()}, f, opts)
81}
82
83func appendEnumPtr(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) {
84	return appendEnum(b, pointer{p.v.Elem()}, f, opts)
85}
86
87func 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
97func 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
105var coderEnumPtr = pointerCoderFuncs{
106	size:      sizeEnumPtr,
107	marshal:   appendEnumPtr,
108	unmarshal: consumeEnumPtr,
109	merge:     mergeEnumPtr,
110}
111
112func 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
120func 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
129func 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
163func mergeEnumSlice(dst, src pointer, _ *coderFieldInfo, _ mergeOptions) {
164	dst.v.Elem().Set(reflect.AppendSlice(dst.v.Elem(), src.v.Elem()))
165}
166
167var coderEnumSlice = pointerCoderFuncs{
168	size:      sizeEnumSlice,
169	marshal:   appendEnumSlice,
170	unmarshal: consumeEnumSlice,
171	merge:     mergeEnumSlice,
172}
173
174func 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
187func 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
205var coderEnumPackedSlice = pointerCoderFuncs{
206	size:      sizeEnumPackedSlice,
207	marshal:   appendEnumPackedSlice,
208	unmarshal: consumeEnumSlice,
209	merge:     mergeEnumSlice,
210}
211