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

/*
* 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;
}