@@ -1019,6 +1019,12 @@ pub const Int = extern struct {
10191019 return c .PyLong_CheckExact (@as ([* c ]c .PyObject , @constCast (@ptrCast (obj )))) != 0 ;
10201020 }
10211021
1022+ // Returns 1 if o is an index integer (has the nb_index slot of the tp_as_number structure filled in), and 0 otherwise.
1023+ // This function always succeeds.
1024+ pub inline fn checkIndex (obj : * const Object ) bool {
1025+ return c .PyIndex_Check (@as ([* c ]c .PyObject , @constCast (@ptrCast (obj )))) != 0 ;
1026+ }
1027+
10221028 // Convert to the given zig type
10231029 pub inline fn as (self : * Int , comptime T : type ) ! T {
10241030 comptime var error_value = -1 ;
@@ -1276,6 +1282,34 @@ pub const Bytes = extern struct {
12761282 // TODO: finish
12771283};
12781284
1285+ pub const Slice = extern struct {
1286+ // The underlying python structure
1287+ impl : c.PySliceObject ,
1288+
1289+ // Import the object protocol
1290+ pub usingnamespace ObjectProtocol (@This ());
1291+
1292+ // Return true if ob is a slice object; ob must not be NULL. This function always succeeds.
1293+ pub inline fn check (obj : * const Object ) bool {
1294+ return c .PySlice_Check (@as ([* c ]c .PyObject , @constCast (@ptrCast (obj )))) != 0 ;
1295+ }
1296+
1297+ // Return a new slice object with the given values.
1298+ // The start, stop, and step parameters are used as the values of the slice object attributes of the same names.
1299+ // Any of the values may be NULL, in which case the None will be used for the corresponding attribute.
1300+ // Returns new reference
1301+ pub inline fn new (start : ? * Object , stop : ? * Object , step : ? * Object ) ! * Slice {
1302+ if (newUnchecked (start , stop , step )) | r | {
1303+ return @ptrCast (r );
1304+ }
1305+ return error .PyError ;
1306+ }
1307+
1308+ pub inline fn newUnchecked (start : ? * Object , stop : ? * Object , step : ? * Object ) ? * Object {
1309+ return @ptrCast (c .PySlice_New (@ptrCast (start ), @ptrCast (stop ), @ptrCast (step )));
1310+ }
1311+ };
1312+
12791313pub const Tuple = extern struct {
12801314 // The underlying python structure
12811315 impl : c.PyTupleObject ,
@@ -1378,10 +1412,10 @@ pub const Tuple = extern struct {
13781412 const r = try Tuple .new (n1 + n2 );
13791413 errdefer r .decref ();
13801414 for (0.. n1 ) | i | {
1381- try r . set (i , a .getUnsafe (i ).? .newref ());
1415+ r . setUnsafe (i , a .getUnsafe (i ).? .newref ());
13821416 }
13831417 for (0.. n2 ) | i | {
1384- try r . set (i + n1 , b .getUnsafe (i ).? .newref ());
1418+ r . setUnsafe (i + n1 , b .getUnsafe (i ).? .newref ());
13851419 }
13861420 return r ;
13871421 }
@@ -1394,9 +1428,9 @@ pub const Tuple = extern struct {
13941428 const n = try self .size ();
13951429 const r = try Tuple .new (n + 1 );
13961430 errdefer r .decref ();
1397- try r . set (0 , obj .newref ());
1431+ r . setUnsafe (0 , obj .newref ());
13981432 for (0.. n ) | i | {
1399- try r . set (i + 1 , self .getUnsafe (i ).? .newref ());
1433+ r . setUnsafe (i + 1 , self .getUnsafe (i ).? .newref ());
14001434 }
14011435 return r ;
14021436 }
@@ -1409,9 +1443,9 @@ pub const Tuple = extern struct {
14091443 const r = try Tuple .new (n + 1 );
14101444 errdefer r .decref ();
14111445 for (0.. n ) | i | {
1412- try r . set (i , self .getUnsafe (i ).? .newref ());
1446+ r . setUnsafe (i , self .getUnsafe (i ).? .newref ());
14131447 }
1414- try r . set (n , obj .newref ());
1448+ r . setUnsafe (n , obj .newref ());
14151449 return r ;
14161450 }
14171451
@@ -1439,9 +1473,13 @@ pub const Tuple = extern struct {
14391473 return error .PyError ;
14401474 }
14411475
1476+ // Returns borrowed reference with no error checking
14421477 pub inline fn getUnsafe (self : * Tuple , pos : usize ) ? * Object {
1443- // TODO: fix PyTuple_GET_ITEM
1444- return @ptrCast (c .PyTuple_GetItem (@ptrCast (self ), @intCast (pos )));
1478+ std .debug .assert (Tuple .check (@ptrCast (self )));
1479+ // Weird casting is because zig (correctly) thinks it goes OOB
1480+ // becaues it's defined as a single item array
1481+ const items : [* ]* Object = @ptrCast (& self .impl .ob_item );
1482+ return items [pos ];
14451483 }
14461484
14471485 // Insert a _stolen_ reference to object o at position pos of the tuple pointed to by p.
@@ -1459,9 +1497,10 @@ pub const Tuple = extern struct {
14591497 // any reference in the tuple at position pos will be leaked.
14601498 pub inline fn setUnsafe (self : * Tuple , pos : usize , obj : * Object ) void {
14611499 // The tuple struct only has one item so zig (correctly) thinks this is writing
1462- // out of bounds. This is marked unsafe for a reason.
1463- const r = c .PyTuple_SetItem (@ptrCast (self ), @intCast (pos ), @ptrCast (obj ));
1464- std .debug .assert (r >= 0 );
1500+ // out of bounds. Hence the weird cast
1501+ std .debug .assert (Tuple .check (@ptrCast (self )));
1502+ const items : [* ]* Object = @ptrCast (& self .impl .ob_item );
1503+ items [pos ] = @ptrCast (obj );
14651504 }
14661505
14671506 // Return the slice of the tuple pointed to by p between low and high,
@@ -1557,8 +1596,9 @@ pub const List = extern struct {
15571596
15581597 // Get borrowed refernce to list item at index without type or bounds checking
15591598 // Calls PyList_GET_ITEM(self, index).
1560- pub inline fn getUnsafe (self : * List , index : isize ) ? * Object {
1561- return c .PyList_GET_ITEM (@ptrCast (self ), index );
1599+ pub inline fn getUnsafe (self : * List , index : usize ) ? * Object {
1600+ std .debug .assert (List .check (@ptrCast (self )));
1601+ return @ptrCast (self .impl .ob_item [index ]);
15621602 }
15631603
15641604 // Set the item at index index in list to item. Return 0 on success.
@@ -1582,8 +1622,9 @@ pub const List = extern struct {
15821622 // content. This macro “steals” a reference to item, and, unlike PyList_SetItem(),
15831623 // does not discard a reference to any item that is being replaced;
15841624 // any reference in list at position i will be leaked.
1585- pub inline fn setUnsafe (self : * List , index : isize , item : * Object ) c_int {
1586- return c .PyList_SET_ITEM (@ptrCast (self ), index , item );
1625+ pub inline fn setUnsafe (self : * List , index : isize , item : * Object ) void {
1626+ std .debug .assert (List .check (@ptrCast (self )));
1627+ self .impl .ob_item [index ] = @ptrCast (item );
15871628 }
15881629
15891630 // Insert the item item into list list in front of index index.
@@ -1950,6 +1991,16 @@ pub const Set = extern struct {
19501991 return c .PySet_CheckExact (@as ([* c ]c .PyObject , @constCast (@ptrCast (obj )))) != 0 ;
19511992 }
19521993
1994+ // Return true if p is a set object, a frozenset object, or an instance of a subtype. This function always succeeds.
1995+ pub inline fn checkAny (obj : * const Object ) bool {
1996+ return c .PyAnySet_Check (@as ([* c ]c .PyObject , @constCast (@ptrCast (obj ))));
1997+ }
1998+
1999+ // Return true if p is a set object or a frozenset object but not an instance of a subtype. This function always succeeds.
2000+ pub inline fn checkAnyExact (obj : * const Object ) bool {
2001+ return c .PyAnySet_CheckExact (@as ([* c ]c .PyObject , @constCast (@ptrCast (obj ))));
2002+ }
2003+
19532004 // Return a new set containing objects returned by the iterable.
19542005 // The iterable may be NULL to create a new empty set.
19552006 // Raise TypeError if iterable is not actually iterable.
@@ -2210,7 +2261,7 @@ pub const Method = extern struct {
22102261
22112262 // Return true if o is a method object (has type PyMethod_Type).
22122263 // The parameter must not be NULL. This function always succeeds.
2213- pub fn check (obj : * Object ) bool {
2264+ pub fn check (obj : * const Object ) bool {
22142265 return c .PyMethod_Check (@as ([* c ]c .PyObject , @constCast (@ptrCast (obj )))) != 0 ;
22152266 }
22162267
0 commit comments