1// Protocol Buffers for Go with Gadgets
2//
3// Copyright (c) 2018, The GoGo Authors. All rights reserved.
4// http://github.com/gogo/protobuf
5//
6// Redistribution and use in source and binary forms, with or without
7// modification, are permitted provided that the following conditions are
8// met:
9//
10//     * Redistributions of source code must retain the above copyright
11// notice, this list of conditions and the following disclaimer.
12//     * Redistributions in binary form must reproduce the above
13// copyright notice, this list of conditions and the following disclaimer
14// in the documentation and/or other materials provided with the
15// distribution.
16//
17// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
29package proto
30
31import (
32	"reflect"
33	"time"
34)
35
36// makeMessageRefMarshaler differs a bit from makeMessageMarshaler
37// It marshal a message T instead of a *T
38func makeMessageRefMarshaler(u *marshalInfo) (sizer, marshaler) {
39	return func(ptr pointer, tagsize int) int {
40			siz := u.size(ptr)
41			return siz + SizeVarint(uint64(siz)) + tagsize
42		},
43		func(b []byte, ptr pointer, wiretag uint64, deterministic bool) ([]byte, error) {
44			b = appendVarint(b, wiretag)
45			siz := u.cachedsize(ptr)
46			b = appendVarint(b, uint64(siz))
47			return u.marshal(b, ptr, deterministic)
48		}
49}
50
51// makeMessageRefSliceMarshaler differs quite a lot from makeMessageSliceMarshaler
52// It marshals a slice of messages []T instead of []*T
53func makeMessageRefSliceMarshaler(u *marshalInfo) (sizer, marshaler) {
54	return func(ptr pointer, tagsize int) int {
55			s := ptr.getSlice(u.typ)
56			n := 0
57			for i := 0; i < s.Len(); i++ {
58				elem := s.Index(i)
59				e := elem.Interface()
60				v := toAddrPointer(&e, false)
61				siz := u.size(v)
62				n += siz + SizeVarint(uint64(siz)) + tagsize
63			}
64			return n
65		},
66		func(b []byte, ptr pointer, wiretag uint64, deterministic bool) ([]byte, error) {
67			s := ptr.getSlice(u.typ)
68			var err, errreq error
69			for i := 0; i < s.Len(); i++ {
70				elem := s.Index(i)
71				e := elem.Interface()
72				v := toAddrPointer(&e, false)
73				b = appendVarint(b, wiretag)
74				siz := u.size(v)
75				b = appendVarint(b, uint64(siz))
76				b, err = u.marshal(b, v, deterministic)
77
78				if err != nil {
79					if _, ok := err.(*RequiredNotSetError); ok {
80						// Required field in submessage is not set.
81						// We record the error but keep going, to give a complete marshaling.
82						if errreq == nil {
83							errreq = err
84						}
85						continue
86					}
87					if err == ErrNil {
88						err = errRepeatedHasNil
89					}
90					return b, err
91				}
92			}
93
94			return b, errreq
95		}
96}
97
98func makeCustomPtrMarshaler(u *marshalInfo) (sizer, marshaler) {
99	return func(ptr pointer, tagsize int) int {
100			if ptr.isNil() {
101				return 0
102			}
103			m := ptr.asPointerTo(reflect.PtrTo(u.typ)).Elem().Interface().(custom)
104			siz := m.Size()
105			return tagsize + SizeVarint(uint64(siz)) + siz
106		}, func(b []byte, ptr pointer, wiretag uint64, deterministic bool) ([]byte, error) {
107			if ptr.isNil() {
108				return b, nil
109			}
110			m := ptr.asPointerTo(reflect.PtrTo(u.typ)).Elem().Interface().(custom)
111			siz := m.Size()
112			buf, err := m.Marshal()
113			if err != nil {
114				return nil, err
115			}
116			b = appendVarint(b, wiretag)
117			b = appendVarint(b, uint64(siz))
118			b = append(b, buf...)
119			return b, nil
120		}
121}
122
123func makeCustomMarshaler(u *marshalInfo) (sizer, marshaler) {
124	return func(ptr pointer, tagsize int) int {
125			m := ptr.asPointerTo(u.typ).Interface().(custom)
126			siz := m.Size()
127			return tagsize + SizeVarint(uint64(siz)) + siz
128		}, func(b []byte, ptr pointer, wiretag uint64, deterministic bool) ([]byte, error) {
129			m := ptr.asPointerTo(u.typ).Interface().(custom)
130			siz := m.Size()
131			buf, err := m.Marshal()
132			if err != nil {
133				return nil, err
134			}
135			b = appendVarint(b, wiretag)
136			b = appendVarint(b, uint64(siz))
137			b = append(b, buf...)
138			return b, nil
139		}
140}
141
142func makeTimeMarshaler(u *marshalInfo) (sizer, marshaler) {
143	return func(ptr pointer, tagsize int) int {
144			t := ptr.asPointerTo(u.typ).Interface().(*time.Time)
145			ts, err := timestampProto(*t)
146			if err != nil {
147				return 0
148			}
149			siz := Size(ts)
150			return tagsize + SizeVarint(uint64(siz)) + siz
151		}, func(b []byte, ptr pointer, wiretag uint64, deterministic bool) ([]byte, error) {
152			t := ptr.asPointerTo(u.typ).Interface().(*time.Time)
153			ts, err := timestampProto(*t)
154			if err != nil {
155				return nil, err
156			}
157			buf, err := Marshal(ts)
158			if err != nil {
159				return nil, err
160			}
161			b = appendVarint(b, wiretag)
162			b = appendVarint(b, uint64(len(buf)))
163			b = append(b, buf...)
164			return b, nil
165		}
166}
167
168func makeTimePtrMarshaler(u *marshalInfo) (sizer, marshaler) {
169	return func(ptr pointer, tagsize int) int {
170			if ptr.isNil() {
171				return 0
172			}
173			t := ptr.asPointerTo(reflect.PtrTo(u.typ)).Elem().Interface().(*time.Time)
174			ts, err := timestampProto(*t)
175			if err != nil {
176				return 0
177			}
178			siz := Size(ts)
179			return tagsize + SizeVarint(uint64(siz)) + siz
180		}, func(b []byte, ptr pointer, wiretag uint64, deterministic bool) ([]byte, error) {
181			if ptr.isNil() {
182				return b, nil
183			}
184			t := ptr.asPointerTo(reflect.PtrTo(u.typ)).Elem().Interface().(*time.Time)
185			ts, err := timestampProto(*t)
186			if err != nil {
187				return nil, err
188			}
189			buf, err := Marshal(ts)
190			if err != nil {
191				return nil, err
192			}
193			b = appendVarint(b, wiretag)
194			b = appendVarint(b, uint64(len(buf)))
195			b = append(b, buf...)
196			return b, nil
197		}
198}
199
200func makeTimeSliceMarshaler(u *marshalInfo) (sizer, marshaler) {
201	return func(ptr pointer, tagsize int) int {
202			s := ptr.getSlice(u.typ)
203			n := 0
204			for i := 0; i < s.Len(); i++ {
205				elem := s.Index(i)
206				t := elem.Interface().(time.Time)
207				ts, err := timestampProto(t)
208				if err != nil {
209					return 0
210				}
211				siz := Size(ts)
212				n += siz + SizeVarint(uint64(siz)) + tagsize
213			}
214			return n
215		},
216		func(b []byte, ptr pointer, wiretag uint64, deterministic bool) ([]byte, error) {
217			s := ptr.getSlice(u.typ)
218			for i := 0; i < s.Len(); i++ {
219				elem := s.Index(i)
220				t := elem.Interface().(time.Time)
221				ts, err := timestampProto(t)
222				if err != nil {
223					return nil, err
224				}
225				siz := Size(ts)
226				buf, err := Marshal(ts)
227				if err != nil {
228					return nil, err
229				}
230				b = appendVarint(b, wiretag)
231				b = appendVarint(b, uint64(siz))
232				b = append(b, buf...)
233			}
234
235			return b, nil
236		}
237}
238
239func makeTimePtrSliceMarshaler(u *marshalInfo) (sizer, marshaler) {
240	return func(ptr pointer, tagsize int) int {
241			s := ptr.getSlice(reflect.PtrTo(u.typ))
242			n := 0
243			for i := 0; i < s.Len(); i++ {
244				elem := s.Index(i)
245				t := elem.Interface().(*time.Time)
246				ts, err := timestampProto(*t)
247				if err != nil {
248					return 0
249				}
250				siz := Size(ts)
251				n += siz + SizeVarint(uint64(siz)) + tagsize
252			}
253			return n
254		},
255		func(b []byte, ptr pointer, wiretag uint64, deterministic bool) ([]byte, error) {
256			s := ptr.getSlice(reflect.PtrTo(u.typ))
257			for i := 0; i < s.Len(); i++ {
258				elem := s.Index(i)
259				t := elem.Interface().(*time.Time)
260				ts, err := timestampProto(*t)
261				if err != nil {
262					return nil, err
263				}
264				siz := Size(ts)
265				buf, err := Marshal(ts)
266				if err != nil {
267					return nil, err
268				}
269				b = appendVarint(b, wiretag)
270				b = appendVarint(b, uint64(siz))
271				b = append(b, buf...)
272			}
273
274			return b, nil
275		}
276}
277
278func makeDurationMarshaler(u *marshalInfo) (sizer, marshaler) {
279	return func(ptr pointer, tagsize int) int {
280			d := ptr.asPointerTo(u.typ).Interface().(*time.Duration)
281			dur := durationProto(*d)
282			siz := Size(dur)
283			return tagsize + SizeVarint(uint64(siz)) + siz
284		}, func(b []byte, ptr pointer, wiretag uint64, deterministic bool) ([]byte, error) {
285			d := ptr.asPointerTo(u.typ).Interface().(*time.Duration)
286			dur := durationProto(*d)
287			buf, err := Marshal(dur)
288			if err != nil {
289				return nil, err
290			}
291			b = appendVarint(b, wiretag)
292			b = appendVarint(b, uint64(len(buf)))
293			b = append(b, buf...)
294			return b, nil
295		}
296}
297
298func makeDurationPtrMarshaler(u *marshalInfo) (sizer, marshaler) {
299	return func(ptr pointer, tagsize int) int {
300			if ptr.isNil() {
301				return 0
302			}
303			d := ptr.asPointerTo(reflect.PtrTo(u.typ)).Elem().Interface().(*time.Duration)
304			dur := durationProto(*d)
305			siz := Size(dur)
306			return tagsize + SizeVarint(uint64(siz)) + siz
307		}, func(b []byte, ptr pointer, wiretag uint64, deterministic bool) ([]byte, error) {
308			if ptr.isNil() {
309				return b, nil
310			}
311			d := ptr.asPointerTo(reflect.PtrTo(u.typ)).Elem().Interface().(*time.Duration)
312			dur := durationProto(*d)
313			buf, err := Marshal(dur)
314			if err != nil {
315				return nil, err
316			}
317			b = appendVarint(b, wiretag)
318			b = appendVarint(b, uint64(len(buf)))
319			b = append(b, buf...)
320			return b, nil
321		}
322}
323
324func makeDurationSliceMarshaler(u *marshalInfo) (sizer, marshaler) {
325	return func(ptr pointer, tagsize int) int {
326			s := ptr.getSlice(u.typ)
327			n := 0
328			for i := 0; i < s.Len(); i++ {
329				elem := s.Index(i)
330				d := elem.Interface().(time.Duration)
331				dur := durationProto(d)
332				siz := Size(dur)
333				n += siz + SizeVarint(uint64(siz)) + tagsize
334			}
335			return n
336		},
337		func(b []byte, ptr pointer, wiretag uint64, deterministic bool) ([]byte, error) {
338			s := ptr.getSlice(u.typ)
339			for i := 0; i < s.Len(); i++ {
340				elem := s.Index(i)
341				d := elem.Interface().(time.Duration)
342				dur := durationProto(d)
343				siz := Size(dur)
344				buf, err := Marshal(dur)
345				if err != nil {
346					return nil, err
347				}
348				b = appendVarint(b, wiretag)
349				b = appendVarint(b, uint64(siz))
350				b = append(b, buf...)
351			}
352
353			return b, nil
354		}
355}
356
357func makeDurationPtrSliceMarshaler(u *marshalInfo) (sizer, marshaler) {
358	return func(ptr pointer, tagsize int) int {
359			s := ptr.getSlice(reflect.PtrTo(u.typ))
360			n := 0
361			for i := 0; i < s.Len(); i++ {
362				elem := s.Index(i)
363				d := elem.Interface().(*time.Duration)
364				dur := durationProto(*d)
365				siz := Size(dur)
366				n += siz + SizeVarint(uint64(siz)) + tagsize
367			}
368			return n
369		},
370		func(b []byte, ptr pointer, wiretag uint64, deterministic bool) ([]byte, error) {
371			s := ptr.getSlice(reflect.PtrTo(u.typ))
372			for i := 0; i < s.Len(); i++ {
373				elem := s.Index(i)
374				d := elem.Interface().(*time.Duration)
375				dur := durationProto(*d)
376				siz := Size(dur)
377				buf, err := Marshal(dur)
378				if err != nil {
379					return nil, err
380				}
381				b = appendVarint(b, wiretag)
382				b = appendVarint(b, uint64(siz))
383				b = append(b, buf...)
384			}
385
386			return b, nil
387		}
388}
389