summaryrefslogtreecommitdiff
path: root/src/util.zig
blob: e6191af8a8bff75212de64cd18ebaffbf528bd74 (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
// SPDX-FileCopyrightText: 2021 Yoran Heling <projects@yorhel.nl>
// SPDX-License-Identifier: MIT

const std = @import("std");

// Cast any integer type to the target type, clamping the value to the supported maximum if necessary.
pub fn castClamp(comptime T: type, x: anytype) T {
    // (adapted from std.math.cast)
    if (std.math.maxInt(@TypeOf(x)) > std.math.maxInt(T) and x > std.math.maxInt(T)) {
        return std.math.maxInt(T);
    } else if (std.math.minInt(@TypeOf(x)) < std.math.minInt(T) and x < std.math.minInt(T)) {
        return std.math.minInt(T);
    } else {
        return @intCast(T, x);
    }
}

// Cast any integer type to the target type, truncating if necessary.
pub fn castTruncate(comptime T: type, x: anytype) T {
    const Ti = @typeInfo(T).Int;
    const Xi = @typeInfo(@TypeOf(x)).Int;
    const nx = if (Xi.signedness != Ti.signedness) @bitCast(std.meta.Int(Ti.signedness, Xi.bits), x) else x;
    return if (Xi.bits > Ti.bits) @truncate(T, nx) else nx;
}

// Multiplies by 512, saturating.
pub fn blocksToSize(b: u64) u64 {
    return if (b & 0xFF80000000000000 > 0) std.math.maxInt(u64) else b << 9;
}

// Ensure the given arraylist buffer gets zero-terminated and returns a slice
// into the buffer. The returned buffer is invalidated whenever the arraylist
// is freed or written to.
pub fn arrayListBufZ(buf: *std.ArrayList(u8)) [:0]const u8 {
    buf.append(0) catch unreachable;
    defer buf.items.len -= 1;
    return buf.items[0..buf.items.len-1:0];
}