1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2008 Google Inc. All rights reserved.
3 //
4 // Use of this source code is governed by a BSD-style
5 // license that can be found in the LICENSE file or at
6 // https://developers.google.com/open-source/licenses/bsd
7
8 #include "google/protobuf/pyext/unknown_field_set.h"
9
10 #define PY_SSIZE_T_CLEAN
11 #include <Python.h>
12
13 #include <memory>
14 #include <set>
15
16 #include "google/protobuf/message.h"
17 #include "google/protobuf/unknown_field_set.h"
18 #include "google/protobuf/pyext/message.h"
19 #include "google/protobuf/pyext/scoped_pyobject_ptr.h"
20 #include "google/protobuf/wire_format_lite.h"
21
22 namespace google {
23 namespace protobuf {
24 namespace python {
25
26 namespace unknown_field_set {
27
Len(PyObject * pself)28 static Py_ssize_t Len(PyObject* pself) {
29 PyUnknownFieldSet* self = reinterpret_cast<PyUnknownFieldSet*>(pself);
30 if (self->fields == nullptr) {
31 PyErr_Format(PyExc_ValueError, "UnknownFieldSet does not exist. ");
32 return -1;
33 }
34 return self->fields->field_count();
35 }
36
37 PyObject* NewPyUnknownField(PyUnknownFieldSet* parent, Py_ssize_t index);
38
Item(PyObject * pself,Py_ssize_t index)39 static PyObject* Item(PyObject* pself, Py_ssize_t index) {
40 PyUnknownFieldSet* self = reinterpret_cast<PyUnknownFieldSet*>(pself);
41 if (self->fields == nullptr) {
42 PyErr_Format(PyExc_ValueError, "UnknownFieldSet does not exist. ");
43 return nullptr;
44 }
45 Py_ssize_t total_size = self->fields->field_count();
46 if (index < 0) {
47 index = total_size + index;
48 }
49 if (index < 0 || index >= total_size) {
50 PyErr_Format(PyExc_IndexError, "index (%zd) out of range", index);
51 return nullptr;
52 }
53 return unknown_field_set::NewPyUnknownField(self, index);
54 }
55
New(PyTypeObject * type,PyObject * args,PyObject * kwargs)56 PyObject* New(PyTypeObject* type, PyObject* args, PyObject* kwargs) {
57 if (args == nullptr || PyTuple_Size(args) != 1) {
58 PyErr_SetString(PyExc_TypeError,
59 "Must provide a message to create UnknownFieldSet");
60 return nullptr;
61 }
62
63 PyObject* c_message;
64 if (!PyArg_ParseTuple(args, "O", &c_message)) {
65 PyErr_SetString(PyExc_TypeError,
66 "Must provide a message to create UnknownFieldSet");
67 return nullptr;
68 }
69
70 if (!PyObject_TypeCheck(c_message, CMessage_Type)) {
71 PyErr_Format(PyExc_TypeError,
72 "Parameter to UnknownFieldSet() must be a message "
73 "got %s.",
74 Py_TYPE(c_message)->tp_name);
75 return nullptr;
76 }
77
78 PyUnknownFieldSet* self = reinterpret_cast<PyUnknownFieldSet*>(
79 PyType_GenericAlloc(&PyUnknownFieldSet_Type, 0));
80 if (self == nullptr) {
81 return nullptr;
82 }
83
84 // Top UnknownFieldSet should set parent nullptr.
85 self->parent = nullptr;
86
87 // Copy c_message's UnknownFieldSet.
88 Message* message = reinterpret_cast<CMessage*>(c_message)->message;
89 const Reflection* reflection = message->GetReflection();
90 self->fields = new google::protobuf::UnknownFieldSet;
91 self->fields->MergeFrom(reflection->GetUnknownFields(*message));
92 return reinterpret_cast<PyObject*>(self);
93 }
94
NewPyUnknownField(PyUnknownFieldSet * parent,Py_ssize_t index)95 PyObject* NewPyUnknownField(PyUnknownFieldSet* parent, Py_ssize_t index) {
96 PyUnknownField* self = reinterpret_cast<PyUnknownField*>(
97 PyType_GenericAlloc(&PyUnknownField_Type, 0));
98 if (self == nullptr) {
99 return nullptr;
100 }
101
102 Py_INCREF(parent);
103 self->parent = parent;
104 self->index = index;
105
106 return reinterpret_cast<PyObject*>(self);
107 }
108
Dealloc(PyObject * pself)109 static void Dealloc(PyObject* pself) {
110 PyUnknownFieldSet* self = reinterpret_cast<PyUnknownFieldSet*>(pself);
111 if (self->parent == nullptr) {
112 delete self->fields;
113 } else {
114 Py_CLEAR(self->parent);
115 }
116 auto* py_type = Py_TYPE(pself);
117 self->~PyUnknownFieldSet();
118 py_type->tp_free(pself);
119 }
120
121 static PySequenceMethods SqMethods = {
122 Len, /* sq_length */
123 nullptr, /* sq_concat */
124 nullptr, /* sq_repeat */
125 Item, /* sq_item */
126 nullptr, /* sq_slice */
127 nullptr, /* sq_ass_item */
128 };
129
130 } // namespace unknown_field_set
131
132 PyTypeObject PyUnknownFieldSet_Type = {
133 PyVarObject_HEAD_INIT(&PyType_Type, 0) FULL_MODULE_NAME
134 ".PyUnknownFieldSet", // tp_name
135 sizeof(PyUnknownFieldSet), // tp_basicsize
136 0, // tp_itemsize
137 unknown_field_set::Dealloc, // tp_dealloc
138 #if PY_VERSION_HEX < 0x03080000
139 nullptr, // tp_print
140 #else
141 0, // tp_vectorcall_offset
142 #endif
143 nullptr, // tp_getattr
144 nullptr, // tp_setattr
145 nullptr, // tp_compare
146 nullptr, // tp_repr
147 nullptr, // tp_as_number
148 &unknown_field_set::SqMethods, // tp_as_sequence
149 nullptr, // tp_as_mapping
150 PyObject_HashNotImplemented, // tp_hash
151 nullptr, // tp_call
152 nullptr, // tp_str
153 nullptr, // tp_getattro
154 nullptr, // tp_setattro
155 nullptr, // tp_as_buffer
156 Py_TPFLAGS_DEFAULT, // tp_flags
157 "unknown field set", // tp_doc
158 nullptr, // tp_traverse
159 nullptr, // tp_clear
160 nullptr, // tp_richcompare
161 0, // tp_weaklistoffset
162 nullptr, // tp_iter
163 nullptr, // tp_iternext
164 nullptr, // tp_methods
165 nullptr, // tp_members
166 nullptr, // tp_getset
167 nullptr, // tp_base
168 nullptr, // tp_dict
169 nullptr, // tp_descr_get
170 nullptr, // tp_descr_set
171 0, // tp_dictoffset
172 nullptr, // tp_init
173 nullptr, // tp_alloc
174 unknown_field_set::New, // tp_new
175 };
176
177 namespace unknown_field {
PyUnknownFieldSet_FromUnknownFieldSet(PyUnknownFieldSet * parent,const UnknownFieldSet & fields)178 static PyObject* PyUnknownFieldSet_FromUnknownFieldSet(
179 PyUnknownFieldSet* parent, const UnknownFieldSet& fields) {
180 PyUnknownFieldSet* self = reinterpret_cast<PyUnknownFieldSet*>(
181 PyType_GenericAlloc(&PyUnknownFieldSet_Type, 0));
182 if (self == nullptr) {
183 return nullptr;
184 }
185
186 Py_INCREF(parent);
187 self->parent = parent;
188 self->fields = const_cast<UnknownFieldSet*>(&fields);
189
190 return reinterpret_cast<PyObject*>(self);
191 }
192
GetUnknownField(PyUnknownField * self)193 const UnknownField* GetUnknownField(PyUnknownField* self) {
194 const UnknownFieldSet* fields = self->parent->fields;
195 if (fields == nullptr) {
196 PyErr_Format(PyExc_ValueError, "UnknownField does not exist. ");
197 return nullptr;
198 }
199 Py_ssize_t total_size = fields->field_count();
200 if (self->index >= total_size) {
201 PyErr_Format(PyExc_ValueError, "UnknownField does not exist. ");
202 return nullptr;
203 }
204 return &fields->field(self->index);
205 }
206
GetFieldNumber(PyUnknownField * self,void * closure)207 static PyObject* GetFieldNumber(PyUnknownField* self, void* closure) {
208 const UnknownField* unknown_field = GetUnknownField(self);
209 if (unknown_field == nullptr) {
210 return nullptr;
211 }
212 return PyLong_FromLong(unknown_field->number());
213 }
214
215 using internal::WireFormatLite;
GetWireType(PyUnknownField * self,void * closure)216 static PyObject* GetWireType(PyUnknownField* self, void* closure) {
217 const UnknownField* unknown_field = GetUnknownField(self);
218 if (unknown_field == nullptr) {
219 return nullptr;
220 }
221
222 // Assign a default value to suppress may-uninitialized warnings (errors
223 // when built in some places).
224 WireFormatLite::WireType wire_type = WireFormatLite::WIRETYPE_VARINT;
225 switch (unknown_field->type()) {
226 case UnknownField::TYPE_VARINT:
227 wire_type = WireFormatLite::WIRETYPE_VARINT;
228 break;
229 case UnknownField::TYPE_FIXED32:
230 wire_type = WireFormatLite::WIRETYPE_FIXED32;
231 break;
232 case UnknownField::TYPE_FIXED64:
233 wire_type = WireFormatLite::WIRETYPE_FIXED64;
234 break;
235 case UnknownField::TYPE_LENGTH_DELIMITED:
236 wire_type = WireFormatLite::WIRETYPE_LENGTH_DELIMITED;
237 break;
238 case UnknownField::TYPE_GROUP:
239 wire_type = WireFormatLite::WIRETYPE_START_GROUP;
240 break;
241 }
242 return PyLong_FromLong(wire_type);
243 }
244
GetData(PyUnknownField * self,void * closure)245 static PyObject* GetData(PyUnknownField* self, void* closure) {
246 const UnknownField* field = GetUnknownField(self);
247 if (field == nullptr) {
248 return nullptr;
249 }
250 PyObject* data = nullptr;
251 switch (field->type()) {
252 case UnknownField::TYPE_VARINT:
253 data = PyLong_FromUnsignedLongLong(field->varint());
254 break;
255 case UnknownField::TYPE_FIXED32:
256 data = PyLong_FromUnsignedLong(field->fixed32());
257 break;
258 case UnknownField::TYPE_FIXED64:
259 data = PyLong_FromUnsignedLongLong(field->fixed64());
260 break;
261 case UnknownField::TYPE_LENGTH_DELIMITED:
262 data = PyBytes_FromStringAndSize(field->length_delimited().data(),
263 field->GetLengthDelimitedSize());
264 break;
265 case UnknownField::TYPE_GROUP:
266 data =
267 PyUnknownFieldSet_FromUnknownFieldSet(self->parent, field->group());
268 break;
269 }
270 return data;
271 }
272
Dealloc(PyObject * pself)273 static void Dealloc(PyObject* pself) {
274 PyUnknownField* self = reinterpret_cast<PyUnknownField*>(pself);
275 Py_CLEAR(self->parent);
276 }
277
278 static PyGetSetDef Getters[] = {
279 {"field_number", (getter)GetFieldNumber, nullptr},
280 {"wire_type", (getter)GetWireType, nullptr},
281 {"data", (getter)GetData, nullptr},
282 {nullptr},
283 };
284
285 } // namespace unknown_field
286
287 PyTypeObject PyUnknownField_Type = {
288 PyVarObject_HEAD_INIT(&PyType_Type, 0) FULL_MODULE_NAME
289 ".PyUnknownField", // tp_name
290 sizeof(PyUnknownField), // tp_basicsize
291 0, // tp_itemsize
292 unknown_field::Dealloc, // tp_dealloc
293 #if PY_VERSION_HEX < 0x03080000
294 nullptr, // tp_print
295 #else
296 0, // tp_vectorcall_offset
297 #endif
298 nullptr, // tp_getattr
299 nullptr, // tp_setattr
300 nullptr, // tp_compare
301 nullptr, // tp_repr
302 nullptr, // tp_as_number
303 nullptr, // tp_as_sequence
304 nullptr, // tp_as_mapping
305 PyObject_HashNotImplemented, // tp_hash
306 nullptr, // tp_call
307 nullptr, // tp_str
308 nullptr, // tp_getattro
309 nullptr, // tp_setattro
310 nullptr, // tp_as_buffer
311 Py_TPFLAGS_DEFAULT, // tp_flags
312 "unknown field", // tp_doc
313 nullptr, // tp_traverse
314 nullptr, // tp_clear
315 nullptr, // tp_richcompare
316 0, // tp_weaklistoffset
317 nullptr, // tp_iter
318 nullptr, // tp_iternext
319 nullptr, // tp_methods
320 nullptr, // tp_members
321 unknown_field::Getters, // tp_getset
322 nullptr, // tp_base
323 nullptr, // tp_dict
324 nullptr, // tp_descr_get
325 nullptr, // tp_descr_set
326 0, // tp_dictoffset
327 nullptr, // tp_init
328 };
329
330 } // namespace python
331 } // namespace protobuf
332 } // namespace google
333