1 // Protocol Buffers - Google's data interchange format 2 // Copyright 2023 Google LLC. 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 #ifndef PYUPB_DESCRIPTOR_CONTAINERS_H__ 9 #define PYUPB_DESCRIPTOR_CONTAINERS_H__ 10 11 // This file defines immutable Python containiner types whose data comes from 12 // an underlying descriptor (def). 13 // 14 // Because there are many instances of these types that vend different kinds of 15 // data (fields, oneofs, enums, etc) these types accept a "vtable" of function 16 // pointers. This saves us from having to define numerous distinct Python types 17 // for each kind of data we want to vend. 18 // 19 // The underlying upb APIs follow a consistent pattern that allows us to use 20 // those functions directly inside these vtables, greatly reducing the amount of 21 // "adaptor" code we need to write. 22 23 #include <stdbool.h> 24 25 #include "protobuf.h" 26 #include "upb/reflection/def.h" 27 28 // ----------------------------------------------------------------------------- 29 // PyUpb_GenericSequence 30 // ----------------------------------------------------------------------------- 31 32 // A Python object that vends a sequence of descriptors. 33 34 typedef struct { 35 // Returns the number of elements in the map. 36 int (*get_elem_count)(const void* parent); 37 // Returns an element by index. 38 const void* (*index)(const void* parent, int idx); 39 // Returns a Python object wrapping this element, caller owns a ref. 40 PyObject* (*get_elem_wrapper)(const void* elem); 41 } PyUpb_GenericSequence_Funcs; 42 43 // Returns a new GenericSequence. The vtable `funcs` must outlive this object 44 // (generally it should be static). The GenericSequence will take a ref on 45 // `parent_obj`, which must be sufficient to keep `parent` alive. The object 46 // `parent` will be passed as an argument to the functions in `funcs`. 47 PyObject* PyUpb_GenericSequence_New(const PyUpb_GenericSequence_Funcs* funcs, 48 const void* parent, PyObject* parent_obj); 49 50 // ----------------------------------------------------------------------------- 51 // PyUpb_ByNameMap 52 // ----------------------------------------------------------------------------- 53 54 // A Python object that vends a name->descriptor map. 55 56 typedef struct { 57 PyUpb_GenericSequence_Funcs base; 58 // Looks up by name and returns either a pointer to the element or NULL. 59 const void* (*lookup)(const void* parent, const char* key); 60 // Returns the name associated with this element. 61 const char* (*get_elem_name)(const void* elem); 62 } PyUpb_ByNameMap_Funcs; 63 64 // Returns a new ByNameMap. The vtable `funcs` must outlive this object 65 // (generally it should be static). The ByNameMap will take a ref on 66 // `parent_obj`, which must be sufficient to keep `parent` alive. The object 67 // `parent` will be passed as an argument to the functions in `funcs`. 68 PyObject* PyUpb_ByNameMap_New(const PyUpb_ByNameMap_Funcs* funcs, 69 const void* parent, PyObject* parent_obj); 70 71 // ----------------------------------------------------------------------------- 72 // PyUpb_ByNumberMap 73 // ----------------------------------------------------------------------------- 74 75 // A Python object that vends a number->descriptor map. 76 77 typedef struct { 78 PyUpb_GenericSequence_Funcs base; 79 // Looks up by name and returns either a pointer to the element or NULL. 80 const void* (*lookup)(const void* parent, int num); 81 // Returns the name associated with this element. 82 int (*get_elem_num)(const void* elem); 83 } PyUpb_ByNumberMap_Funcs; 84 85 // Returns a new ByNumberMap. The vtable `funcs` must outlive this object 86 // (generally it should be static). The ByNumberMap will take a ref on 87 // `parent_obj`, which must be sufficient to keep `parent` alive. The object 88 // `parent` will be passed as an argument to the functions in `funcs`. 89 PyObject* PyUpb_ByNumberMap_New(const PyUpb_ByNumberMap_Funcs* funcs, 90 const void* parent, PyObject* parent_obj); 91 92 bool PyUpb_InitDescriptorContainers(PyObject* m); 93 94 #endif // PYUPB_DESCRIPTOR_CONTAINERS_H__ 95