aboutsummaryrefslogtreecommitdiff
path: root/src/Clip.zig
blob: 8d264c870e9b0c7c5eb1c8bf2d5cb31300598ee9 (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
pub const OSC52 = @import("Clip/OSC52.zig");

// I am not sure if this is super idiomatic Zig or if this is bad practice, but
// by ensuring that all Clip backends implement the same methods, we are able
// to use the `anytype` type and we are able to have an interface that is able
// to dispatch statically

/// Check if a function with the given name and type exists.
/// `@compileError` if not
fn assertFn(comptime T: type, comptime name: []const u8, comptime Sig: type) void {
    if (!@import("std").meta.hasFn(T, name))
        @compileError(@typeName(T) ++ " missing fn " ++ name);
    if (@TypeOf(@field(T, name)) != Sig)
        @compileError(@typeName(T) ++ "." ++ name ++ " must be " ++ @typeName(Sig));
}

test {
    inline for (@typeInfo(@This()).@"struct".decls) |decl| {
        // Only grab types of structs
        const T = @field(@This(), decl.name);
        if (@TypeOf(T) != type) continue;
        if (@typeInfo(T) != .@"struct") continue;

        // ==============================
        // === Interface Requirements ===
        // ==============================
        assertFn(T, "writeCopyBuffer", fn (*T, []const u8) anyerror!void);
        assertFn(T, "writePasteboard", fn (*T) anyerror!void);
    }
}