summaryrefslogtreecommitdiff
path: root/src/dict/Watcher.zig
blob: 317a269c599608c7f49e838bca0a86ca0b66450e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
const std = @import("std");
const c = @import("c");
const zpy = @import("../root.zig");

const Self = @This();

id: c_int,

pub const Event = enum(u32) {
    added = c.PyDict_EVENT_ADDED,
    modified = c.PyDict_EVENT_MODIFIED,
    deleted = c.PyDict_EVENT_DELETED,
    cloned = c.PyDict_EVENT_CLONED,
    cleared = c.PyDict_EVENT_CLEARED,
    deallocated = c.PyDict_EVENT_DEALLOCATED,
};

pub const Callback = fn (Event, *zpy.Dict, *zpy.Object, *zpy.Object) error{Exception}!void;

pub fn add(callback: Callback) !Self {
    const wrapper = struct {
        pub fn wrapper(
            event: c_uint,
            dict: [*c]c.PyObject,
            key: [*c]c.PyObject,
            value: [*c]c.PyObject,
        ) callconv(.c) c_int {
            return if (std.meta.isError(callback(
                @enumFromInt(event),
                @ptrCast(dict),
                @ptrCast(key),
                @ptrCast(value),
            ))) -1 else 0;
        }
    }.wrapper;

    const result = c.PyDict_AddWatcher(&wrapper);

    if (result == -1) {
        return error.Exception;
    }

    return .{ .id = result };
}

pub fn clear(self: Self) !void {
    if (c.PyDict_Clear(self.id) == -1) {
        return error.Exception;
    }
}

pub fn watch(self: Self, dict: *zpy.Dict) !void {
    if (c.PyDict_Watch(self.id, @ptrCast(dict)) == -1) {
        return error.Exception;
    }
}

pub fn unwatch(self: Self, dict: *zpy.Dict) !void {
    if (c.PyDict_Unwatch(self.id, @ptrCast(dict)) == -1) {
        return error.Exception;
    }
}