podman

Форк
0
242 строки · 7.4 Кб
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
// Package messageset encodes and decodes the obsolete MessageSet wire format.
6
package messageset
7

8
import (
9
	"math"
10

11
	"google.golang.org/protobuf/encoding/protowire"
12
	"google.golang.org/protobuf/internal/errors"
13
	"google.golang.org/protobuf/reflect/protoreflect"
14
)
15

16
// The MessageSet wire format is equivalent to a message defined as follows,
17
// where each Item defines an extension field with a field number of 'type_id'
18
// and content of 'message'. MessageSet extensions must be non-repeated message
19
// fields.
20
//
21
//	message MessageSet {
22
//		repeated group Item = 1 {
23
//			required int32 type_id = 2;
24
//			required string message = 3;
25
//		}
26
//	}
27
const (
28
	FieldItem    = protowire.Number(1)
29
	FieldTypeID  = protowire.Number(2)
30
	FieldMessage = protowire.Number(3)
31
)
32

33
// ExtensionName is the field name for extensions of MessageSet.
34
//
35
// A valid MessageSet extension must be of the form:
36
//
37
//	message MyMessage {
38
//		extend proto2.bridge.MessageSet {
39
//			optional MyMessage message_set_extension = 1234;
40
//		}
41
//		...
42
//	}
43
const ExtensionName = "message_set_extension"
44

45
// IsMessageSet returns whether the message uses the MessageSet wire format.
46
func IsMessageSet(md protoreflect.MessageDescriptor) bool {
47
	xmd, ok := md.(interface{ IsMessageSet() bool })
48
	return ok && xmd.IsMessageSet()
49
}
50

51
// IsMessageSetExtension reports this field properly extends a MessageSet.
52
func IsMessageSetExtension(fd protoreflect.FieldDescriptor) bool {
53
	switch {
54
	case fd.Name() != ExtensionName:
55
		return false
56
	case !IsMessageSet(fd.ContainingMessage()):
57
		return false
58
	case fd.FullName().Parent() != fd.Message().FullName():
59
		return false
60
	}
61
	return true
62
}
63

64
// SizeField returns the size of a MessageSet item field containing an extension
65
// with the given field number, not counting the contents of the message subfield.
66
func SizeField(num protowire.Number) int {
67
	return 2*protowire.SizeTag(FieldItem) + protowire.SizeTag(FieldTypeID) + protowire.SizeVarint(uint64(num))
68
}
69

70
// Unmarshal parses a MessageSet.
71
//
72
// It calls fn with the type ID and value of each item in the MessageSet.
73
// Unknown fields are discarded.
74
//
75
// If wantLen is true, the item values include the varint length prefix.
76
// This is ugly, but simplifies the fast-path decoder in internal/impl.
77
func Unmarshal(b []byte, wantLen bool, fn func(typeID protowire.Number, value []byte) error) error {
78
	for len(b) > 0 {
79
		num, wtyp, n := protowire.ConsumeTag(b)
80
		if n < 0 {
81
			return protowire.ParseError(n)
82
		}
83
		b = b[n:]
84
		if num != FieldItem || wtyp != protowire.StartGroupType {
85
			n := protowire.ConsumeFieldValue(num, wtyp, b)
86
			if n < 0 {
87
				return protowire.ParseError(n)
88
			}
89
			b = b[n:]
90
			continue
91
		}
92
		typeID, value, n, err := ConsumeFieldValue(b, wantLen)
93
		if err != nil {
94
			return err
95
		}
96
		b = b[n:]
97
		if typeID == 0 {
98
			continue
99
		}
100
		if err := fn(typeID, value); err != nil {
101
			return err
102
		}
103
	}
104
	return nil
105
}
106

107
// ConsumeFieldValue parses b as a MessageSet item field value until and including
108
// the trailing end group marker. It assumes the start group tag has already been parsed.
109
// It returns the contents of the type_id and message subfields and the total
110
// item length.
111
//
112
// If wantLen is true, the returned message value includes the length prefix.
113
func ConsumeFieldValue(b []byte, wantLen bool) (typeid protowire.Number, message []byte, n int, err error) {
114
	ilen := len(b)
115
	for {
116
		num, wtyp, n := protowire.ConsumeTag(b)
117
		if n < 0 {
118
			return 0, nil, 0, protowire.ParseError(n)
119
		}
120
		b = b[n:]
121
		switch {
122
		case num == FieldItem && wtyp == protowire.EndGroupType:
123
			if wantLen && len(message) == 0 {
124
				// The message field was missing, which should never happen.
125
				// Be prepared for this case anyway.
126
				message = protowire.AppendVarint(message, 0)
127
			}
128
			return typeid, message, ilen - len(b), nil
129
		case num == FieldTypeID && wtyp == protowire.VarintType:
130
			v, n := protowire.ConsumeVarint(b)
131
			if n < 0 {
132
				return 0, nil, 0, protowire.ParseError(n)
133
			}
134
			b = b[n:]
135
			if v < 1 || v > math.MaxInt32 {
136
				return 0, nil, 0, errors.New("invalid type_id in message set")
137
			}
138
			typeid = protowire.Number(v)
139
		case num == FieldMessage && wtyp == protowire.BytesType:
140
			m, n := protowire.ConsumeBytes(b)
141
			if n < 0 {
142
				return 0, nil, 0, protowire.ParseError(n)
143
			}
144
			if message == nil {
145
				if wantLen {
146
					message = b[:n:n]
147
				} else {
148
					message = m[:len(m):len(m)]
149
				}
150
			} else {
151
				// This case should never happen in practice, but handle it for
152
				// correctness: The MessageSet item contains multiple message
153
				// fields, which need to be merged.
154
				//
155
				// In the case where we're returning the length, this becomes
156
				// quite inefficient since we need to strip the length off
157
				// the existing data and reconstruct it with the combined length.
158
				if wantLen {
159
					_, nn := protowire.ConsumeVarint(message)
160
					m0 := message[nn:]
161
					message = nil
162
					message = protowire.AppendVarint(message, uint64(len(m0)+len(m)))
163
					message = append(message, m0...)
164
					message = append(message, m...)
165
				} else {
166
					message = append(message, m...)
167
				}
168
			}
169
			b = b[n:]
170
		default:
171
			// We have no place to put it, so we just ignore unknown fields.
172
			n := protowire.ConsumeFieldValue(num, wtyp, b)
173
			if n < 0 {
174
				return 0, nil, 0, protowire.ParseError(n)
175
			}
176
			b = b[n:]
177
		}
178
	}
179
}
180

181
// AppendFieldStart appends the start of a MessageSet item field containing
182
// an extension with the given number. The caller must add the message
183
// subfield (including the tag).
184
func AppendFieldStart(b []byte, num protowire.Number) []byte {
185
	b = protowire.AppendTag(b, FieldItem, protowire.StartGroupType)
186
	b = protowire.AppendTag(b, FieldTypeID, protowire.VarintType)
187
	b = protowire.AppendVarint(b, uint64(num))
188
	return b
189
}
190

191
// AppendFieldEnd appends the trailing end group marker for a MessageSet item field.
192
func AppendFieldEnd(b []byte) []byte {
193
	return protowire.AppendTag(b, FieldItem, protowire.EndGroupType)
194
}
195

196
// SizeUnknown returns the size of an unknown fields section in MessageSet format.
197
//
198
// See AppendUnknown.
199
func SizeUnknown(unknown []byte) (size int) {
200
	for len(unknown) > 0 {
201
		num, typ, n := protowire.ConsumeTag(unknown)
202
		if n < 0 || typ != protowire.BytesType {
203
			return 0
204
		}
205
		unknown = unknown[n:]
206
		_, n = protowire.ConsumeBytes(unknown)
207
		if n < 0 {
208
			return 0
209
		}
210
		unknown = unknown[n:]
211
		size += SizeField(num) + protowire.SizeTag(FieldMessage) + n
212
	}
213
	return size
214
}
215

216
// AppendUnknown appends unknown fields to b in MessageSet format.
217
//
218
// For historic reasons, unresolved items in a MessageSet are stored in a
219
// message's unknown fields section in non-MessageSet format. That is, an
220
// unknown item with typeID T and value V appears in the unknown fields as
221
// a field with number T and value V.
222
//
223
// This function converts the unknown fields back into MessageSet form.
224
func AppendUnknown(b, unknown []byte) ([]byte, error) {
225
	for len(unknown) > 0 {
226
		num, typ, n := protowire.ConsumeTag(unknown)
227
		if n < 0 || typ != protowire.BytesType {
228
			return nil, errors.New("invalid data in message set unknown fields")
229
		}
230
		unknown = unknown[n:]
231
		_, n = protowire.ConsumeBytes(unknown)
232
		if n < 0 {
233
			return nil, errors.New("invalid data in message set unknown fields")
234
		}
235
		b = AppendFieldStart(b, num)
236
		b = protowire.AppendTag(b, FieldMessage, protowire.BytesType)
237
		b = append(b, unknown[:n]...)
238
		b = AppendFieldEnd(b)
239
		unknown = unknown[n:]
240
	}
241
	return b, nil
242
}
243

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.