Protocol Buffers - Google's data interchange format (grpc依赖)
https://developers.google.com/protocol-buffers/
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
254 lines
8.8 KiB
254 lines
8.8 KiB
/* |
|
* Copyright (c) 2009-2021, Google LLC |
|
* All rights reserved. |
|
* |
|
* Redistribution and use in source and binary forms, with or without |
|
* modification, are permitted provided that the following conditions are met: |
|
* * Redistributions of source code must retain the above copyright |
|
* notice, this list of conditions and the following disclaimer. |
|
* * Redistributions in binary form must reproduce the above copyright |
|
* notice, this list of conditions and the following disclaimer in the |
|
* documentation and/or other materials provided with the distribution. |
|
* * Neither the name of Google LLC nor the |
|
* names of its contributors may be used to endorse or promote products |
|
* derived from this software without specific prior written permission. |
|
* |
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
|
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
|
* ARE DISCLAIMED. IN NO EVENT SHALL Google LLC BE LIABLE FOR ANY DIRECT, |
|
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
|
*/ |
|
|
|
#include "python/descriptor_pool.h" |
|
|
|
#include "python/descriptor.h" |
|
#include "python/protobuf.h" |
|
#include "upb/def.h" |
|
|
|
// ----------------------------------------------------------------------------- |
|
// DescriptorPool |
|
// ----------------------------------------------------------------------------- |
|
|
|
typedef struct { |
|
PyObject_HEAD |
|
upb_symtab* symtab; |
|
PyObject* db; |
|
} PyUpb_DescriptorPool; |
|
|
|
PyObject* PyUpb_DescriptorPool_GetDefaultPool() { |
|
PyUpb_ModuleState* s = PyUpb_ModuleState_Get(); |
|
return s->default_pool; |
|
} |
|
|
|
static PyObject* PyUpb_DescriptorPool_DoCreateWithCache(PyTypeObject* type, |
|
PyObject* db, |
|
PyUpb_WeakMap *obj_cache) { |
|
PyUpb_DescriptorPool* pool = (void*)PyType_GenericAlloc(type, 0); |
|
pool->symtab = upb_symtab_new(); |
|
pool->db = db; |
|
Py_XINCREF(pool->db); |
|
PyUpb_WeakMap_Add(obj_cache, pool->symtab, &pool->ob_base); |
|
return &pool->ob_base; |
|
} |
|
|
|
static PyObject* PyUpb_DescriptorPool_DoCreate(PyTypeObject* type, |
|
PyObject* db) { |
|
return PyUpb_DescriptorPool_DoCreateWithCache(type, db, |
|
PyUpb_ObjCache_Instance()); |
|
} |
|
|
|
upb_symtab* PyUpb_DescriptorPool_GetSymtab(PyObject* pool) { |
|
return ((PyUpb_DescriptorPool*)pool)->symtab; |
|
} |
|
|
|
static int PyUpb_DescriptorPool_Traverse(PyUpb_DescriptorPool* self, |
|
visitproc visit, void* arg) { |
|
Py_VISIT(self->db); |
|
return 0; |
|
} |
|
|
|
static int PyUpb_DescriptorPool_Clear(PyUpb_DescriptorPool* self) { |
|
Py_CLEAR(self->db); |
|
return 0; |
|
} |
|
|
|
PyObject* PyUpb_DescriptorPool_Get(const upb_symtab* symtab) { |
|
PyObject* pool = PyUpb_ObjCache_Get(symtab); |
|
assert(pool); |
|
return pool; |
|
} |
|
|
|
static void PyUpb_DescriptorPool_Dealloc(PyUpb_DescriptorPool* self) { |
|
upb_symtab_free(self->symtab); |
|
PyUpb_DescriptorPool_Clear(self); |
|
PyUpb_ObjCache_Delete(self->symtab); |
|
PyUpb_Dealloc(self); |
|
} |
|
|
|
/* |
|
* DescriptorPool.__new__() |
|
* |
|
* Implements: |
|
* DescriptorPool(descriptor_db=None) |
|
*/ |
|
static PyObject* PyUpb_DescriptorPool_New(PyTypeObject* type, PyObject* args, |
|
PyObject* kwargs) { |
|
char* kwlist[] = {"descriptor_db", 0}; |
|
PyObject* db = NULL; |
|
|
|
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|O", kwlist, &db)) { |
|
return NULL; |
|
} |
|
|
|
return PyUpb_DescriptorPool_DoCreate(type, db); |
|
} |
|
|
|
/* |
|
* PyUpb_DescriptorPool_AddSerializedFile() |
|
* |
|
* Implements: |
|
* DescriptorPool.AddSerializedFile(self, serialized_file_descriptor) |
|
* |
|
* Adds the given serialized FileDescriptorProto to the pool. |
|
*/ |
|
static PyObject* PyUpb_DescriptorPool_AddSerializedFile( |
|
PyObject* _self, PyObject* serialized_pb) { |
|
PyUpb_DescriptorPool* self = (PyUpb_DescriptorPool*)_self; |
|
char* buf; |
|
Py_ssize_t size; |
|
upb_arena* arena = upb_arena_new(); |
|
if (!arena) PYUPB_RETURN_OOM; |
|
PyObject* result = NULL; |
|
|
|
if (self->db) { |
|
PyErr_SetString( |
|
PyExc_ValueError, |
|
"Cannot call Add on a DescriptorPool that uses a DescriptorDatabase. " |
|
"Add your file to the underlying database."); |
|
goto done; |
|
} |
|
|
|
if (PyBytes_AsStringAndSize(serialized_pb, &buf, &size) < 0) { |
|
goto done; |
|
} |
|
|
|
google_protobuf_FileDescriptorProto* proto = |
|
google_protobuf_FileDescriptorProto_parse(buf, size, arena); |
|
if (!proto) { |
|
PyErr_SetString(PyExc_TypeError, "Couldn't parse file content!"); |
|
goto done; |
|
} |
|
|
|
upb_status status; |
|
upb_status_clear(&status); |
|
|
|
const upb_filedef* filedef = upb_symtab_addfile(self->symtab, proto, &status); |
|
if (!filedef) { |
|
PyErr_Format(PyExc_TypeError, |
|
"Couldn't build proto file into descriptor pool: %s", |
|
upb_status_errmsg(&status)); |
|
goto done; |
|
} |
|
|
|
result = PyUpb_FileDescriptor_Get(filedef); |
|
|
|
done: |
|
upb_arena_free(arena); |
|
return result; |
|
} |
|
|
|
/* |
|
* PyUpb_DescriptorPool_FindExtensionByName() |
|
* |
|
* Implements: |
|
* DescriptorPool.FindExtensionByName(self, name) |
|
*/ |
|
static PyObject* PyUpb_DescriptorPool_FindExtensionByName(PyObject* _self, |
|
PyObject* arg) { |
|
PyUpb_DescriptorPool* self = (PyUpb_DescriptorPool*)_self; |
|
|
|
const char* name = PyUpb_GetStrData(arg); |
|
if (!name) return NULL; |
|
|
|
const upb_fielddef* field = upb_symtab_lookupext(self->symtab, name); |
|
if (field == NULL) { |
|
return PyErr_Format(PyExc_KeyError, "Couldn't find extension %.200s", name); |
|
} |
|
|
|
return PyUpb_FieldDescriptor_Get(field); |
|
} |
|
|
|
static PyMethodDef PyUpb_DescriptorPool_Methods[] = { |
|
/* |
|
TODO: implement remaining methods. |
|
{ "Add", Add, METH_O, |
|
"Adds the FileDescriptorProto and its types to this pool." }, |
|
*/ |
|
{"AddSerializedFile", PyUpb_DescriptorPool_AddSerializedFile, METH_O, |
|
"Adds a serialized FileDescriptorProto to this pool."}, |
|
/* |
|
{ "FindFileByName", FindFileByName, METH_O, |
|
"Searches for a file descriptor by its .proto name." }, |
|
{ "FindMessageTypeByName", FindMessageByName, METH_O, |
|
"Searches for a message descriptor by full name." }, |
|
{ "FindFieldByName", FindFieldByNameMethod, METH_O, |
|
"Searches for a field descriptor by full name." }, |
|
*/ |
|
{"FindExtensionByName", PyUpb_DescriptorPool_FindExtensionByName, METH_O, |
|
"Searches for extension descriptor by full name."}, |
|
/* |
|
{ "FindEnumTypeByName", FindEnumTypeByNameMethod, METH_O, |
|
"Searches for enum type descriptor by full name." }, |
|
{ "FindOneofByName", FindOneofByNameMethod, METH_O, |
|
"Searches for oneof descriptor by full name." }, |
|
{ "FindServiceByName", FindServiceByName, METH_O, |
|
"Searches for service descriptor by full name." }, |
|
{ "FindMethodByName", FindMethodByName, METH_O, |
|
"Searches for method descriptor by full name." }, |
|
{ "FindFileContainingSymbol", FindFileContainingSymbol, METH_O, |
|
"Gets the FileDescriptor containing the specified symbol." }, |
|
{ "FindExtensionByNumber", FindExtensionByNumber, METH_VARARGS, |
|
"Gets the extension descriptor for the given number." }, |
|
{ "FindAllExtensions", FindAllExtensions, METH_O, |
|
"Gets all known extensions of the given message descriptor." }, |
|
*/ |
|
{NULL}}; |
|
|
|
static PyType_Slot PyUpb_DescriptorPool_Slots[] = { |
|
{Py_tp_clear, PyUpb_DescriptorPool_Clear}, |
|
{Py_tp_dealloc, PyUpb_DescriptorPool_Dealloc}, |
|
{Py_tp_methods, PyUpb_DescriptorPool_Methods}, |
|
{Py_tp_new, PyUpb_DescriptorPool_New}, |
|
{Py_tp_traverse, PyUpb_DescriptorPool_Traverse}, |
|
{0, NULL}}; |
|
|
|
static PyType_Spec PyUpb_DescriptorPool_Spec = { |
|
PYUPB_MODULE_NAME ".DescriptorPool", |
|
sizeof(PyUpb_DescriptorPool), |
|
0, // tp_itemsize |
|
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, |
|
PyUpb_DescriptorPool_Slots, |
|
}; |
|
|
|
// ----------------------------------------------------------------------------- |
|
// Top Level |
|
// ----------------------------------------------------------------------------- |
|
|
|
bool PyUpb_InitDescriptorPool(PyObject* m) { |
|
PyUpb_ModuleState *state = PyUpb_ModuleState_GetFromModule(m); |
|
PyTypeObject* descriptor_pool_type = |
|
AddObject(m, "DescriptorPool", &PyUpb_DescriptorPool_Spec); |
|
|
|
if (!descriptor_pool_type) return false; |
|
|
|
state->default_pool = PyUpb_DescriptorPool_DoCreateWithCache( |
|
descriptor_pool_type, NULL, state->obj_cache); |
|
return state->default_pool && |
|
PyModule_AddObject(m, "default_pool", state->default_pool) == 0; |
|
}
|
|
|