@@ -420,6 +420,89 @@ static PyMethodDef vec_methods[] = {
420420 {NULL , NULL , 0 , NULL }, /* Sentinel */
421421};
422422
423+ // Iterator type for nested vecs
424+
425+ typedef struct {
426+ PyObject_HEAD
427+ VecNested vec ; // Unboxed vec (keeps buffer alive via buf reference)
428+ Py_ssize_t index ; // Current iteration index
429+ } VecNestedIterObject ;
430+
431+ PyTypeObject VecNestedIterType ;
432+
433+ static PyObject * VecNested_iter (PyObject * self ) {
434+ VecNestedIterObject * it = PyObject_GC_New (VecNestedIterObject , & VecNestedIterType );
435+ if (it == NULL )
436+ return NULL ;
437+ it -> vec = ((VecNestedObject * )self )-> vec ;
438+ Py_INCREF (it -> vec .buf );
439+ it -> index = 0 ;
440+ PyObject_GC_Track (it );
441+ return (PyObject * )it ;
442+ }
443+
444+ static int
445+ VecNestedIter_traverse (VecNestedIterObject * self , visitproc visit , void * arg )
446+ {
447+ Py_VISIT (self -> vec .buf );
448+ return 0 ;
449+ }
450+
451+ static int
452+ VecNestedIter_clear (VecNestedIterObject * self )
453+ {
454+ Py_CLEAR (self -> vec .buf );
455+ return 0 ;
456+ }
457+
458+ static void VecNestedIter_dealloc (VecNestedIterObject * self ) {
459+ PyObject_GC_UnTrack (self );
460+ Py_XDECREF (self -> vec .buf );
461+ PyObject_GC_Del (self );
462+ }
463+
464+ static PyObject * VecNestedIter_next (VecNestedIterObject * self ) {
465+ if (self -> vec .buf == NULL )
466+ return NULL ;
467+ if (self -> index < self -> vec .len ) {
468+ PyObject * item = box_vec_item_by_index (self -> vec , self -> index );
469+ if (item == NULL )
470+ return NULL ;
471+ self -> index ++ ;
472+ return item ;
473+ }
474+ Py_CLEAR (self -> vec .buf );
475+ return NULL ; // StopIteration
476+ }
477+
478+ static PyObject * VecNestedIter_len (VecNestedIterObject * self , PyObject * Py_UNUSED (ignored )) {
479+ if (self -> vec .buf == NULL )
480+ return PyLong_FromSsize_t (0 );
481+ Py_ssize_t remaining = self -> vec .len - self -> index ;
482+ if (remaining < 0 )
483+ remaining = 0 ;
484+ return PyLong_FromSsize_t (remaining );
485+ }
486+
487+ static PyMethodDef VecNestedIter_methods [] = {
488+ {"__length_hint__" , (PyCFunction )VecNestedIter_len , METH_NOARGS , NULL },
489+ {NULL , NULL , 0 , NULL },
490+ };
491+
492+ PyTypeObject VecNestedIterType = {
493+ PyVarObject_HEAD_INIT (NULL , 0 )
494+ .tp_name = "vec_nested_iterator" ,
495+ .tp_basicsize = sizeof (VecNestedIterObject ),
496+ .tp_itemsize = 0 ,
497+ .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC ,
498+ .tp_traverse = (traverseproc )VecNestedIter_traverse ,
499+ .tp_clear = (inquiry )VecNestedIter_clear ,
500+ .tp_dealloc = (destructor )VecNestedIter_dealloc ,
501+ .tp_iter = PyObject_SelfIter ,
502+ .tp_iternext = (iternextfunc )VecNestedIter_next ,
503+ .tp_methods = VecNestedIter_methods ,
504+ };
505+
423506PyTypeObject VecNestedBufType = {
424507 PyVarObject_HEAD_INIT (NULL , 0 )
425508 .tp_name = "vecbuf" ,
@@ -447,6 +530,7 @@ PyTypeObject VecNestedType = {
447530 .tp_dealloc = (destructor )VecNested_dealloc ,
448531 //.tp_free = PyObject_GC_Del,
449532 .tp_repr = (reprfunc )vec_repr ,
533+ .tp_iter = VecNested_iter ,
450534 .tp_as_sequence = & VecNestedSequence ,
451535 .tp_as_mapping = & VecNestedMapping ,
452536 .tp_richcompare = vec_richcompare ,
0 commit comments