Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 4 additions & 7 deletions examples/my_php_extension/src/api/big_integer.zig
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,10 @@ const BigInteger = struct {
}

/// PHP: MyPHPExt\BigInteger::__construct(int|string $value = 0): void
pub fn __construct(ctx: phpz.Ctx) !BigInteger {
const args = try ctx.call.expectArgs(&.{
.{ .mixed = .{ .optional = true, .one_of = &.{ .int, .string } } },
}, {});
pub fn __construct(initial: ?phpz.Mixed(&.{ .int, .string })) !BigInteger {
var self = try init();
errdefer self.deinit();
if (args[0]) |input| switch (input) {
if (initial) |input| switch (input) {
.int => |n| try self.integer.set(n),
.string => |text| {
// Managed.setString permits separators and empty input; the
Expand All @@ -47,10 +44,10 @@ const BigInteger = struct {
}

/// PHP: MyPHPExt\BigInteger::value(): string
pub fn value(self: *const BigInteger, ctx: phpz.Ctx) !void {
pub fn value(self: *const BigInteger) !*phpz.zend.String {
const text = try self.integer.toString(allocator, 10, .lower);
defer allocator.free(text);
ctx.retval.set(.string, text);
return phpz.zend.String.init(text, false);
}

const ops = struct {
Expand Down
85 changes: 24 additions & 61 deletions examples/my_php_extension/src/api/collection.zig
Original file line number Diff line number Diff line change
Expand Up @@ -32,67 +32,41 @@ const Collection = struct {
}

/// PHP: MyPHPExt\Collection::__construct(array $values = [])
pub fn __construct(ctx: phpz.Ctx) !Collection {
const args = try ctx.call.expectArgs(&.{
.{ .array = .{ .optional = true } },
}, {});

pub fn __construct(values: ?*phpz.zend.Array) Collection {
var self = init();
if (args[0]) |values| {
self.data.copy(values);
if (values) |provided| {
self.data.copy(provided);
}
return self;
}

/// PHP: MyPHPExt\Collection::toArray(): array
pub fn toArray(self: *const Collection, ctx: phpz.Ctx) void {
ctx.retval.set(.array, self.data.dupe());
pub fn toArray(self: *const Collection) *phpz.zend.Array {
return self.data.dupe();
}

/// PHP: MyPHPExt\Collection::offsetExists(mixed $offset): bool
pub fn offsetExists(self: *Collection, ctx: phpz.Ctx) !void {
const args = try ctx.call.expectArgs(&.{
.{ .mixed = .{} },
}, {});
const offset = args[0];

ctx.retval.set(.bool, switch (offset.kind()) {
pub fn offsetExists(self: *Collection, offset: *Zval) bool {
return switch (offset.kind()) {
.int => self.data.hasIndex(@intCast(offset.asUnchecked(.int))),
.string => self.data.has(offset.asUnchecked(.string)),
else => false,
});
};
}

/// PHP: MyPHPExt\Collection::offsetGet(mixed $offset): mixed
pub fn offsetGet(self: *Collection, ctx: phpz.Ctx) !void {
const args = try ctx.call.expectArgs(&.{
.{ .mixed = .{} },
}, {});
const offset = args[0];

pub fn offsetGet(self: *Collection, offset: *Zval) ?*Zval {
const value = switch (offset.kind()) {
.int => self.data.findIndex(@intCast(offset.asUnchecked(.int))),
.string => self.data.find(offset.asUnchecked(.string)),
else => null,
};

if (value) |found| {
Zval.raw.tryAddref(found);
ctx.retval.set(.mixed, found);
} else {
ctx.retval.set(.null, {});
}
return if (value) |found| .from(found) else null;
}

/// PHP: MyPHPExt\Collection::offsetSet(mixed $offset, mixed $value): void
pub fn offsetSet(self: *Collection, ctx: phpz.Ctx) !void {
const args = try ctx.call.expectArgs(&.{
.{ .mixed = .{} },
.{ .mixed = .{} },
}, {});
const offset = args[0];
const value = args[1];

pub fn offsetSet(self: *Collection, offset: *Zval, value: *Zval) void {
switch (offset.kind()) {
.int => {
value.tryAddref();
Expand All @@ -119,12 +93,7 @@ const Collection = struct {
}

/// PHP: MyPHPExt\Collection::offsetUnset(mixed $offset): void
pub fn offsetUnset(self: *Collection, ctx: phpz.Ctx) !void {
const args = try ctx.call.expectArgs(&.{
.{ .mixed = .{} },
}, {});
const offset = args[0];

pub fn offsetUnset(self: *Collection, offset: *Zval) void {
switch (offset.kind()) {
.int => self.data.deleteIndex(
@intCast(offset.asUnchecked(.int)),
Expand All @@ -139,30 +108,24 @@ const Collection = struct {
}

/// PHP: MyPHPExt\Collection::count(): int
pub fn count(self: *const Collection, ctx: phpz.Ctx) void {
ctx.retval.set(.int, @intCast(self.data.len()));
pub fn count(self: *const Collection) usize {
return self.data.len();
}

/// PHP: MyPHPExt\Collection::current(): mixed
pub fn current(self: *Collection, ctx: phpz.Ctx) void {
if (self.iterator.currentValue()) |value| {
Zval.raw.tryAddref(value);
ctx.retval.set(.mixed, value);
} else {
ctx.retval.set(.null, {});
}
pub fn current(self: *Collection) ?*Zval {
return if (self.iterator.currentValue()) |value| .from(value) else null;
}

/// PHP: MyPHPExt\Collection::key(): mixed
pub fn key(self: *Collection, ctx: phpz.Ctx) void {
pub fn key(self: *Collection) phpz.Mixed(&.{ .int, .string, .null }) {
if (self.iterator.currentKey()) |key_value| {
switch (key_value) {
.int => |index| ctx.retval.set(.int, index),
.string => |key_name| ctx.retval.set(.string, key_name),
}
} else {
ctx.retval.set(.null, {});
return switch (key_value) {
.int => |index| .{ .int = index },
.string => |key_name| .{ .string = key_name },
};
}
return .null;
}

/// PHP: MyPHPExt\Collection::next(): void
Expand All @@ -176,8 +139,8 @@ const Collection = struct {
}

/// PHP: MyPHPExt\Collection::valid(): bool
pub fn valid(self: *Collection, ctx: phpz.Ctx) void {
ctx.retval.set(.bool, self.iterator.current() != null);
pub fn valid(self: *Collection) bool {
return self.iterator.current() != null;
}
};

Expand Down
17 changes: 8 additions & 9 deletions examples/my_php_extension/src/api/config.zig
Original file line number Diff line number Diff line change
@@ -1,25 +1,24 @@
const phpz = @import("phpz");

const ini = @import("../ini.zig");

/// PHP: MyPHPExt\Config::greeting(): string
pub fn greeting(ctx: phpz.Ctx) !void {
ctx.retval.set(.string, try ini.greeting.get());
pub fn greeting() ![]const u8 {
return try ini.greeting.get();
}

/// PHP: MyPHPExt\Config::maxUsers(): int
pub fn maxUsers(ctx: phpz.Ctx) !void {
ctx.retval.set(.int, try ini.max_users.get());
pub fn maxUsers() !i64 {
return try ini.max_users.get();
}

/// PHP: MyPHPExt\Config::debugEnabled(): bool
pub fn debugEnabled(ctx: phpz.Ctx) !void {
ctx.retval.set(.bool, try ini.debug.get());
pub fn debugEnabled() !bool {
return try ini.debug.get();
}

/// PHP: MyPHPExt\Config::mode(): string
pub fn mode(ctx: phpz.Ctx) !void {
ctx.retval.set(.string, @tagName(try ini.mode.get()));
pub fn mode() ![]const u8 {
return @tagName(try ini.mode.get());
}

pub const Class = phpz.Class("MyPHPExt\\Config", @This(), .{});
36 changes: 12 additions & 24 deletions examples/my_php_extension/src/api/counter.zig
Original file line number Diff line number Diff line change
Expand Up @@ -2,42 +2,30 @@ const Counter = struct {
current_value: i64,

/// PHP: MyPHPExt\Counter::__construct(int $value = 0): void
pub fn __construct(ctx: phpz.Ctx) !Counter {
const args = try ctx.call.expectArgs(&.{
.{ .int = .{ .optional = true } },
}, {});
return .{ .current_value = args[0] orelse 0 };
pub fn __construct(initial: ?i64) Counter {
return .{ .current_value = initial orelse 0 };
}

/// PHP: MyPHPExt\Counter::increment(int $by = 1): int
pub fn increment(self: *Counter, ctx: phpz.Ctx) !void {
const args = try ctx.call.expectArgs(&.{
.{ .int = .{ .optional = true } },
}, {});
self.current_value +|= args[0] orelse 1;
ctx.retval.set(.int, self.current_value);
pub fn increment(self: *Counter, by: ?i64) i64 {
self.current_value +|= by orelse 1;
return self.current_value;
}

/// PHP: MyPHPExt\Counter::decrement(int $by = 1): int
pub fn decrement(self: *Counter, ctx: phpz.Ctx) !void {
const args = try ctx.call.expectArgs(&.{
.{ .int = .{ .optional = true } },
}, {});
self.current_value -|= args[0] orelse 1;
ctx.retval.set(.int, self.current_value);
pub fn decrement(self: *Counter, by: ?i64) i64 {
self.current_value -|= by orelse 1;
return self.current_value;
}

/// PHP: MyPHPExt\Counter::value(): int
pub fn value(self: *const Counter, ctx: phpz.Ctx) void {
ctx.retval.set(.int, self.current_value);
pub fn value(self: *const Counter) i64 {
return self.current_value;
}

/// PHP: MyPHPExt\Counter::reset(int $value = 0): void
pub fn reset(self: *Counter, ctx: phpz.Ctx) !void {
const args = try ctx.call.expectArgs(&.{
.{ .int = .{ .optional = true } },
}, {});
self.current_value = args[0] orelse 0;
pub fn reset(self: *Counter, initial: ?i64) void {
self.current_value = initial orelse 0;
}
};

Expand Down
12 changes: 4 additions & 8 deletions examples/my_php_extension/src/api/entity.zig
Original file line number Diff line number Diff line change
Expand Up @@ -3,23 +3,19 @@ fn register(register_fn: anytype) *phpz.ClassEntry {
}

/// PHP: MyPHPExt\Entity::__construct(int $id): void
pub fn __construct(ctx: phpz.Ctx) !void {
const args = try ctx.call.expectArgs(&.{
.{ .int = .{} },
}, {});

pub fn __construct(ctx: phpz.Ctx, id: i64) !void {
const entity = ctx.call.this().?;
try entity.setProperty(.int, "id", args[0]);
try entity.setProperty(.int, "id", id);
}

/// PHP: MyPHPExt\Entity::getId(): int
pub fn getId(ctx: phpz.Ctx) !void {
pub fn getId(ctx: phpz.Ctx) !i64 {
const entity = ctx.call.this().?;
var scratch = phpz.Zval.raw.undef;
defer phpz.Zval.raw.tryRelease(&scratch);

const id = try entity.property("id", false, &scratch);
ctx.retval.set(.int, phpz.Zval.raw.asUnchecked(id.ptr(), .int));
return phpz.Zval.raw.asUnchecked(id.ptr(), .int);
}

pub const Class = phpz.Class("MyPHPExt\\Entity", @This(), .{ .register = register });
Expand Down
7 changes: 1 addition & 6 deletions examples/my_php_extension/src/api/tag.zig
Original file line number Diff line number Diff line change
@@ -1,10 +1,5 @@
/// PHP: MyPHPExt\Tag::__construct(string $name, ?string $description = null): void
pub fn __construct(ctx: phpz.Ctx) !void {
const name, const description = try ctx.call.expectArgs(&.{
.{ .string = .{} },
.{ .string = .{ .optional = true, .nullable = true } },
}, {});

pub fn __construct(ctx: phpz.Ctx, name: []const u8, description: ?phpz.Nullable([]const u8)) !void {
const tag = ctx.call.this().?;
try tag.setProperty(.string, "name", name);
if (description) |provided| {
Expand Down
4 changes: 2 additions & 2 deletions examples/my_php_extension/src/api/user.zig
Original file line number Diff line number Diff line change
Expand Up @@ -40,13 +40,13 @@ pub fn __construct(ctx: phpz.Ctx) !void {

/// PHP: MyPHPExt\User::label(): string
/// PHP: MyPHPExt\User::__toString(): string
pub fn label(ctx: phpz.Ctx) !void {
pub fn label(ctx: phpz.Ctx) !*phpz.zend.String {
const user = ctx.call.this().?;
var scratch = phpz.Zval.raw.undef;
defer phpz.Zval.raw.tryRelease(&scratch);

const name = try user.property("name", false, &scratch);
ctx.retval.set(.string, phpz.Zval.raw.asUnchecked(name.ptr(), .string));
return name.asUnchecked(.str).copy();
}

pub const Class = phpz.Class("MyPHPExt\\User", @This(), .{ .register = register });
Expand Down
24 changes: 8 additions & 16 deletions examples/my_php_extension/src/closures.zig
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,8 @@ const phpz = @import("phpz");
const Zval = phpz.Zval;

/// PHP: {closure}(...$args) — accepts two integers and returns their sum.
fn sum(ctx: phpz.Ctx) !void {
const args = try ctx.call.expectArgs(&.{ .{ .int = .{} }, .{ .int = .{} } }, {});
ctx.retval.set(.int, args[0] +| args[1]);
fn sum(a: i64, b: i64) i64 {
return a +| b;
}

/// PHP: MyPHPExt\makeSumClosure(): Closure
Expand All @@ -23,12 +22,9 @@ const Counter = struct {
}

/// PHP: MyPHPExt\ClosureCounter::__invoke(int $step = 1): int
pub fn __invoke(self: *Counter, ctx: phpz.Ctx) !void {
const args = try ctx.call.expectArgs(&.{
.{ .int = .{ .optional = true } },
}, {});
self.value +|= args[0] orelse 1;
ctx.retval.set(.int, self.value);
pub fn __invoke(self: *Counter, step: ?i64) i64 {
self.value +|= step orelse 1;
return self.value;
}

fn deinit(self: *Counter) void {
Expand All @@ -47,16 +43,12 @@ pub const CounterClass = phpz.Class("MyPHPExt\\ClosureCounter", Counter, .{
});

/// PHP: MyPHPExt\makeCounter(int $start = 0, mixed $held = null): Closure
pub fn makeCounter(ctx: phpz.Ctx) !void {
const args = try ctx.call.expectArgs(&.{
.{ .int = .{ .optional = true } },
.{ .mixed = .{ .optional = true } },
}, {});
pub fn makeCounter(ctx: phpz.Ctx, start: ?i64, held: ?*Zval) !void {
const owner = try CounterClass.create();
defer owner.object().release();
const backing = owner.backing().?;
backing.value = args[0] orelse 0;
if (args[1]) |held| Zval.raw.copy(&backing.held, held.ptr());
backing.value = start orelse 0;
if (held) |value| Zval.raw.copy(&backing.held, value.ptr());
const invoke = phpz.zend.Function.findMethod(CounterClass.entry, "__invoke").?;
try invoke.toClosure(ctx.retval, .{ .object = owner.object() });
}
Expand Down
Loading
Loading