1 /* 2 * Copyright (c) 2009-2021, Google LLC 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are met: 7 * * Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * * Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * * Neither the name of Google LLC nor the 13 * names of its contributors may be used to endorse or promote products 14 * derived from this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL Google LLC BE LIABLE FOR ANY DIRECT, 20 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 */ 27 28 #ifndef PYUPB_DESCRIPTOR_CONTAINERS_H__ 29 #define PYUPB_DESCRIPTOR_CONTAINERS_H__ 30 31 // This file defines immutable Python containiner types whose data comes from 32 // an underlying descriptor (def). 33 // 34 // Because there are many instances of these types that vend different kinds of 35 // data (fields, oneofs, enums, etc) these types accept a "vtable" of function 36 // pointers. This saves us from having to define numerous distinct Python types 37 // for each kind of data we want to vend. 38 // 39 // The underlying upb APIs follow a consistent pattern that allows us to use 40 // those functions directly inside these vtables, greatly reducing the amount of 41 // "adaptor" code we need to write. 42 43 #include <stdbool.h> 44 45 #include "protobuf.h" 46 #include "upb/reflection/def.h" 47 48 // ----------------------------------------------------------------------------- 49 // PyUpb_GenericSequence 50 // ----------------------------------------------------------------------------- 51 52 // A Python object that vends a sequence of descriptors. 53 54 typedef struct { 55 // Returns the number of elements in the map. 56 int (*get_elem_count)(const void* parent); 57 // Returns an element by index. 58 const void* (*index)(const void* parent, int idx); 59 // Returns a Python object wrapping this element, caller owns a ref. 60 PyObject* (*get_elem_wrapper)(const void* elem); 61 } PyUpb_GenericSequence_Funcs; 62 63 // Returns a new GenericSequence. The vtable `funcs` must outlive this object 64 // (generally it should be static). The GenericSequence will take a ref on 65 // `parent_obj`, which must be sufficient to keep `parent` alive. The object 66 // `parent` will be passed as an argument to the functions in `funcs`. 67 PyObject* PyUpb_GenericSequence_New(const PyUpb_GenericSequence_Funcs* funcs, 68 const void* parent, PyObject* parent_obj); 69 70 // ----------------------------------------------------------------------------- 71 // PyUpb_ByNameMap 72 // ----------------------------------------------------------------------------- 73 74 // A Python object that vends a name->descriptor map. 75 76 typedef struct { 77 PyUpb_GenericSequence_Funcs base; 78 // Looks up by name and returns either a pointer to the element or NULL. 79 const void* (*lookup)(const void* parent, const char* key); 80 // Returns the name associated with this element. 81 const char* (*get_elem_name)(const void* elem); 82 } PyUpb_ByNameMap_Funcs; 83 84 // Returns a new ByNameMap. The vtable `funcs` must outlive this object 85 // (generally it should be static). The ByNameMap will take a ref on 86 // `parent_obj`, which must be sufficient to keep `parent` alive. The object 87 // `parent` will be passed as an argument to the functions in `funcs`. 88 PyObject* PyUpb_ByNameMap_New(const PyUpb_ByNameMap_Funcs* funcs, 89 const void* parent, PyObject* parent_obj); 90 91 // ----------------------------------------------------------------------------- 92 // PyUpb_ByNumberMap 93 // ----------------------------------------------------------------------------- 94 95 // A Python object that vends a number->descriptor map. 96 97 typedef struct { 98 PyUpb_GenericSequence_Funcs base; 99 // Looks up by name and returns either a pointer to the element or NULL. 100 const void* (*lookup)(const void* parent, int num); 101 // Returns the name associated with this element. 102 int (*get_elem_num)(const void* elem); 103 } PyUpb_ByNumberMap_Funcs; 104 105 // Returns a new ByNumberMap. The vtable `funcs` must outlive this object 106 // (generally it should be static). The ByNumberMap will take a ref on 107 // `parent_obj`, which must be sufficient to keep `parent` alive. The object 108 // `parent` will be passed as an argument to the functions in `funcs`. 109 PyObject* PyUpb_ByNumberMap_New(const PyUpb_ByNumberMap_Funcs* funcs, 110 const void* parent, PyObject* parent_obj); 111 112 bool PyUpb_InitDescriptorContainers(PyObject* m); 113 114 #endif // PYUPB_DESCRIPTOR_CONTAINERS_H__ 115