aboutsummaryrefslogtreecommitdiff
path: root/src/lib.zig
blob: 8e99ad3f5e1e4ea8d53948cf5a7627a2208c19ce (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
63
64
65
66
67
68
69
70
71
72
73
const std = @import("std");

/// Compose two single argument functions
pub fn compose(
    comptime outerFunc: anytype,
    comptime innerFunc: anytype
) blk:{
    const outerFuncType = @TypeOf(outerFunc);
    const outerFuncTypeInfo = @typeInfo(outerFuncType);
    if(outerFuncTypeInfo != .@"fn")
        @compileError("Expected function, found " ++ @typeName(outerFuncType));
    const innerFuncType = @TypeOf(innerFunc);
    const innerFuncTypeInfo = @typeInfo(innerFuncType);
    if(innerFuncTypeInfo != .@"fn")
        @compileError("Expected function, found " ++ @typeName(innerFuncType));
    const out = @typeInfo(@TypeOf(outerFunc)).@"fn".return_type.?;
    const in = @typeInfo(@TypeOf(innerFunc)).@"fn".params[0].type.?;
    break :blk fn(in) out;
} {
    const out = @typeInfo(@TypeOf(outerFunc)).@"fn".return_type.?;
    const in = @typeInfo(@TypeOf(innerFunc)).@"fn".params[0].type.?;
    return struct {
        fn func(input: in) out {
            return outerFunc(innerFunc(input));
        }
    }.func;
}

pub fn mapAlloc(
    allocator: std.mem.Allocator,
    func: anytype,
    items: anytype,
) error{OutOfMemory}!blk:{
    const itemsType = @TypeOf(items);
    const itemsTypeInfo = @typeInfo(itemsType);
    const funcType = @TypeOf(func);
    const funcTypeInfo = @typeInfo(funcType);
    if(funcTypeInfo != .@"fn")
        @compileError("Expected function, found " ++ @typeName(funcType));
    if(itemsTypeInfo != .array and itemsTypeInfo != .pointer) {
        @compileError("Expected array or slice, found " ++ @typeName(itemsType));
    }

    break :blk []funcTypeInfo.@"fn".return_type.?;
} {
    const funcType = @TypeOf(func);
    const funcTypeInfo = @typeInfo(funcType);
    var result = try allocator.alloc(funcTypeInfo.@"fn".return_type.?, items.len);
    for(items, 0..) |item, i|
        result[i] = func(item);
    return result;
}

pub fn map(
    func: anytype,
    items: anytype,
    buffer: anytype,
) void {
    const funcType = @TypeOf(func);
    const bufferType = @TypeOf(buffer);
    const itemsType = @TypeOf(items);
    const funcTypeInfo = @typeInfo(funcType);
    const bufferTypeInfo = @typeInfo(bufferType);
    const itemsTypeInfo = @typeInfo(itemsType);
    if(funcTypeInfo != .@"fn")
        @compileError("Expected function, found " ++ @typeName(funcType));
    if(itemsTypeInfo != .array and itemsTypeInfo != .pointer)
        @compileError("Expected array, found " ++ @typeName(itemsType));
    if(bufferTypeInfo != .array and bufferTypeInfo != .pointer)
        @compileError("Expected array, found " ++ @typeName(bufferType));
    for (items, 0..) |item, i|
        buffer.*[i] = func(item);
}