The efficient `Strs_init` path initializing from PyArrow array capsules.
| 6848 | |
| 6849 | // The efficient `Strs_init` path initializing from PyArrow array capsules. |
| 6850 | static int Strs_init_from_pyarrow(Strs *self, PyObject *sequence_obj, int view) { |
| 6851 | // Handle Arrow array |
| 6852 | PyObject *capsules = PyObject_CallMethod(sequence_obj, "__arrow_c_array__", NULL); |
| 6853 | if (!capsules || !PyTuple_Check(capsules) || PyTuple_Size(capsules) != 2) { |
| 6854 | Py_XDECREF(capsules); |
| 6855 | PyErr_SetString(PyExc_ValueError, "__arrow_c_array__ must return a tuple of 2 capsules"); |
| 6856 | return -1; |
| 6857 | } |
| 6858 | |
| 6859 | PyObject *schema_capsule = PyTuple_GET_ITEM(capsules, 0); |
| 6860 | PyObject *array_capsule = PyTuple_GET_ITEM(capsules, 1); |
| 6861 | |
| 6862 | if (!PyCapsule_CheckExact(schema_capsule) || !PyCapsule_CheckExact(array_capsule)) { |
| 6863 | Py_DECREF(capsules); |
| 6864 | PyErr_SetString(PyExc_ValueError, "Expected PyCapsule objects from __arrow_c_array__"); |
| 6865 | return -1; |
| 6866 | } |
| 6867 | |
| 6868 | struct ArrowSchema *schema = (struct ArrowSchema *)PyCapsule_GetPointer(schema_capsule, "arrow_schema"); |
| 6869 | struct ArrowArray *array = (struct ArrowArray *)PyCapsule_GetPointer(array_capsule, "arrow_array"); |
| 6870 | |
| 6871 | if (!schema || !array) { |
| 6872 | Py_DECREF(capsules); |
| 6873 | PyErr_SetString(PyExc_ValueError, "Failed to extract Arrow C structures"); |
| 6874 | return -1; |
| 6875 | } |
| 6876 | |
| 6877 | // Validate string array layout |
| 6878 | if (!schema->format || (strcmp(schema->format, "u") != 0 && strcmp(schema->format, "U") != 0 && |
| 6879 | strcmp(schema->format, "z") != 0 && strcmp(schema->format, "Z") != 0)) { |
| 6880 | Py_DECREF(capsules); |
| 6881 | PyErr_SetString(PyExc_ValueError, "Arrow array must be string layout"); |
| 6882 | return -1; |
| 6883 | } |
| 6884 | |
| 6885 | if (array->n_buffers != 3) { |
| 6886 | Py_DECREF(capsules); |
| 6887 | PyErr_SetString(PyExc_ValueError, "String Arrow array must have 3 buffers"); |
| 6888 | return -1; |
| 6889 | } |
| 6890 | |
| 6891 | // Determine if 32-bit or 64-bit offsets |
| 6892 | int use_64bit = (strcmp(schema->format, "U") == 0 || strcmp(schema->format, "Z") == 0); |
| 6893 | void const **buffers = (void const **)array->buffers; |
| 6894 | sz_u8_t const *validity = (sz_u8_t const *)buffers[0]; // May be NULL |
| 6895 | sz_cptr_t data_buffer = (sz_cptr_t)buffers[2]; |
| 6896 | sz_size_t length = array->length; |
| 6897 | |
| 6898 | // Zero-copy mode for Arrow arrays |
| 6899 | if (view) { |
| 6900 | if (use_64bit) { |
| 6901 | sz_i64_t const *offsets_64 = (sz_i64_t const *)buffers[1]; |
| 6902 | self->layout = STRS_U64_TAPE_VIEW; |
| 6903 | self->data.u64_tape_view.count = length; |
| 6904 | self->data.u64_tape_view.parent = capsules; |
| 6905 | self->data.u64_tape_view.data = data_buffer; |
| 6906 | self->data.u64_tape_view.offsets = (sz_u64_t *)offsets_64; |
| 6907 | Py_INCREF(capsules); |
no test coverage detected
searching dependent graphs…