Skip to content

Commit 953d8ae

Browse files
committed
Add Tuple.next, Str.format, and inline a few fns
1 parent 17f993c commit 953d8ae

File tree

1 file changed

+42
-17
lines changed

1 file changed

+42
-17
lines changed

py.zig

Lines changed: 42 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -93,12 +93,7 @@ pub inline fn errorFormat(exc: *Object, format: []const u8, args: anytype) Error
9393
c.PyErr_SetString(@ptrCast(exc), @ptrCast(format));
9494
return error.PyError;
9595
}
96-
const data = std.fmt.allocPrint(allocator, format, args) catch {
97-
return memoryError(); // TODO: This squashes the error
98-
};
99-
defer allocator.free(data);
100-
// TODO: is there a way to avoid a copy?
101-
const msg = try Str.fromSlice(data); // TODO: This squashes the error
96+
const msg = try Str.format(format, args); // TODO: This squashes the error
10297
defer msg.decref();
10398
c.PyErr_SetObject(@ptrCast(exc), @ptrCast(msg));
10499
return error.PyError;
@@ -900,7 +895,7 @@ pub const Iter = struct {
900895
// Import the iterarator
901896
pub usingnamespace IteratorProtocol(@This());
902897

903-
pub fn check(obj: *const Object) bool {
898+
pub inline fn check(obj: *const Object) bool {
904899
return c.PyIter_Check(@constCast(@ptrCast(obj))) != 0;
905900
}
906901
};
@@ -1256,6 +1251,20 @@ pub const Str = extern struct {
12561251
return error.PyError;
12571252
}
12581253

1254+
// Format a string using zig alloc print.
1255+
pub inline fn format(comptime msg: []const u8, args: anytype) Error!*Str {
1256+
return formatAlloc(allocator, msg, args);
1257+
}
1258+
1259+
pub inline fn formatAlloc(alloc: std.mem.Allocator, comptime msg: []const u8, args: anytype) Error!*Str {
1260+
const str = std.fmt.allocPrint(alloc, msg, args) catch {
1261+
try memoryError(); // TODO: This squashes the error
1262+
};
1263+
defer allocator.free(str);
1264+
// TODO: is there a way to avoid a copy?
1265+
return try Str.fromSlice(str);
1266+
}
1267+
12591268
// A combination of PyUnicode_FromString() and PyUnicode_InternInPlace(),
12601269
// meant for statically allocated strings.
12611270
// Return a new (“owned”) reference to either a new Unicode string object
@@ -1273,12 +1282,12 @@ pub const Str = extern struct {
12731282
}
12741283

12751284
// Return data as utf8
1276-
pub inline fn asString(self: *Str) [:0]const u8 {
1285+
pub inline fn data(self: *Str) [:0]const u8 {
12771286
return std.mem.span(c.PyUnicode_AsUTF8(@ptrCast(self)));
12781287
}
12791288

1280-
// Alias to asString
1281-
pub const data = asString;
1289+
// Alias to data
1290+
pub const asString = data;
12821291
};
12831292

12841293
pub const Bytes = extern struct {
@@ -1357,7 +1366,7 @@ pub const Tuple = extern struct {
13571366
// Eg var arg: *Str: undefined
13581367
// then &arg is **Str
13591368
const ArgType = @typeInfo(@typeInfo(T).Pointer.child).Pointer.child;
1360-
const obj = try self.get(i);
1369+
const obj = self.getUnsafe(i).?;
13611370
if (!ArgType.check(obj)) {
13621371
return typeError("Argument at {} must be {}", .{ i, ArgType });
13631372
}
@@ -1477,9 +1486,10 @@ pub const Tuple = extern struct {
14771486
return @intCast(r);
14781487
}
14791488

1480-
pub inline fn sizeUnchecked(self: *Tuple) isize {
1489+
pub inline fn sizeUnsafe(self: *Tuple) isize {
14811490
return c.PyTuple_GET_SIZE(@ptrCast(self));
14821491
}
1492+
pub const sizeUnchecked = sizeUnsafe;
14831493

14841494
// Return the object at position pos in the tuple pointed to by p.
14851495
// If pos is negative or out of bounds,
@@ -1496,7 +1506,7 @@ pub const Tuple = extern struct {
14961506
pub inline fn getUnsafe(self: *Tuple, pos: usize) ?*Object {
14971507
std.debug.assert(Tuple.check(@ptrCast(self)));
14981508
// Weird casting is because zig (correctly) thinks it goes OOB
1499-
// becaues it's defined as a single item array
1509+
// because it's defined as a single item array
15001510
const items: [*]*Object = @ptrCast(&self.impl.ob_item);
15011511
return items[pos];
15021512
}
@@ -1545,6 +1555,21 @@ pub const Tuple = extern struct {
15451555
const end = try self.size();
15461556
return try self.slice(0, end);
15471557
}
1558+
1559+
// Iterate over tuple items inplace.
1560+
// Assumes the self has been checked that is is indeed a tuple
1561+
// This is likely slower than using for(0..n) |item|
1562+
// Returns a borrowed reference to the item
1563+
pub inline fn next(self: *Tuple, pos: *usize) ?*Object {
1564+
// Zig will safety check this for -1 in release safe
1565+
const n: usize = @intCast(self.sizeUnsafe());
1566+
const i = pos.*;
1567+
if (i < n) {
1568+
pos.* = i + 1;
1569+
return self.getUnsafe(i).?;
1570+
}
1571+
return null;
1572+
}
15481573
};
15491574

15501575
// TODO: Create a ListProtocol()
@@ -1599,7 +1624,7 @@ pub const List = extern struct {
15991624

16001625
pub inline fn sizeUnsafe(self: *List) isize {
16011626
std.debug.assert(List.check(@ptrCast(self)));
1602-
return self.impl.ob_size;
1627+
return c.PyList_GET_SIZE(@ptrCast(self));
16031628
}
16041629

16051630
// Get a borrowed reference to the list item.
@@ -2200,7 +2225,7 @@ pub const Code = extern struct {
22002225
pub usingnamespace ObjectProtocol(@This());
22012226

22022227
// Return true if co is a code object. This function always succeeds.
2203-
pub fn check(obj: *const Object) bool {
2228+
pub inline fn check(obj: *const Object) bool {
22042229
return c.PyCode_Check(@as([*c]c.PyObject, @constCast(@ptrCast(obj)))) != 0;
22052230
}
22062231
};
@@ -2213,7 +2238,7 @@ pub const Function = extern struct {
22132238

22142239
// Return true if o is a function object (has type PyFunction_Type).
22152240
// The parameter must not be NULL. This function always succeeds.
2216-
pub fn check(obj: *const Object) bool {
2241+
pub inline fn check(obj: *const Object) bool {
22172242
return c.PyFunction_Check(@as([*c]c.PyObject, @constCast(@ptrCast(obj)))) != 0;
22182243
}
22192244

@@ -2319,7 +2344,7 @@ pub const Method = extern struct {
23192344

23202345
// Return true if o is a method object (has type PyMethod_Type).
23212346
// The parameter must not be NULL. This function always succeeds.
2322-
pub fn check(obj: *const Object) bool {
2347+
pub inline fn check(obj: *const Object) bool {
23232348
return c.PyMethod_Check(@as([*c]c.PyObject, @constCast(@ptrCast(obj)))) != 0;
23242349
}
23252350

0 commit comments

Comments
 (0)