DzLox

:)
git clone https://git.sr.ht/~ashymad/DzLox
Log | Files | Refs | Submodules | LICENSE

lib::utils.zig (4759B)


      1 const std = @import("std");
      2 
      3 pub fn sign(v: anytype) @TypeOf(v) {
      4     return if (v >= 0) 1 else -1;
      5 }
      6 
      7 pub fn with_size(T: type, comptime size: std.lang.Type.Pointer.Size) type {
      8     return mod_ptr_t(T, "size", size);
      9 }
     10 
     11 pub fn copy_const(T: type, U: type) type {
     12     return mod_ptr_t(U, "const", is_const(T));
     13 }
     14 
     15 pub fn optional(val: anytype) if (is_type(@TypeOf(val), "optional")) @TypeOf(val) else ?@TypeOf(val) {
     16     return val;
     17 }
     18 
     19 pub fn log_return(val: anytype) @TypeOf(val) {
     20     if (@TypeOf(val) == type)
     21         @compileLog("Returning: " ++ @typeName(val))
     22     else
     23         @compileLog("Returning: " ++ @typeName(@TypeOf(val)));
     24     return val;
     25 }
     26 
     27 pub fn mod_ptr_t(T: type, comptime field: []const u8, comptime val: anytype) type {
     28     const is_optional = is_type(T, "optional");
     29 
     30     const old = if (is_optional) @typeInfo(T).optional.child else T;
     31 
     32     comptime var new = @typeInfo(old).pointer;
     33 
     34     if (@hasField(std.lang.Type.Pointer.Attributes, field)) {
     35         @field(new.attrs, field) = val;
     36     } else {
     37         @field(new, field) = val;
     38     }
     39 
     40     const ret = @Pointer(
     41         new.size,
     42         new.attrs,
     43         new.child,
     44         std.lang.Type.Pointer.sentinel(new),
     45     );
     46 
     47     return if (is_optional) ?ret else ret;
     48 }
     49 
     50 pub fn enum_len(T: type) usize {
     51     return @typeInfo(T).@"enum".field_names.len;
     52 }
     53 
     54 pub fn is_type(T: type, comptime name: []const u8) bool {
     55     return @as(std.meta.Tag(std.lang.Type), @typeInfo(T)) == @field(std.meta.Tag(std.lang.Type), name);
     56 }
     57 
     58 pub fn is_const(T: type) bool {
     59     return @typeInfo(T).pointer.attrs.@"const";
     60 }
     61 
     62 pub fn typeFromTag(T: type, comptime tag: std.meta.Tag(T)) type {
     63     return @TypeOf(@field(@unionInit(T, @tagName(tag), undefined), @tagName(tag)));
     64 }
     65 
     66 pub fn tagFromType(T: type, U: type) std.meta.Tag(T) {
     67     const info = @typeInfo(T).@"union";
     68     inline for (info.field_types, info.field_names) |field_type, field_name| {
     69         if (U == field_type) {
     70             return @field(T, field_name);
     71         }
     72     }
     73     @compileError("No matching tag for type " ++ @typeName(U) ++ " in Union " ++ @typeName(T));
     74 }
     75 
     76 pub fn fn_error(comptime fun: anytype) ?type {
     77     const return_type = @typeInfo(@TypeOf(fun)).@"fn".return_type.?;
     78 
     79     return if (is_type(return_type, "error_union")) @typeInfo(return_type).error_union.error_set else null;
     80 }
     81 
     82 pub fn param_type(comptime fun: anytype, idx: comptime_int) type {
     83     return @TypeOf(fun).@"fn".params[idx].type.?;
     84 }
     85 
     86 pub fn if_not_null(comptime fun: anytype) fn (?param_type(fun, 0)) void {
     87     return struct {
     88         pub fn function(arg: ?param_type(fun, 0)) void {
     89             if (arg) |a| {
     90                 _ = fun(a);
     91             }
     92         }
     93     }.function;
     94 }
     95 
     96 pub fn pack_t(s: type) type {
     97     const info = @typeInfo(s).@"struct";
     98     const Attributes = std.lang.Type.Struct.FieldAttributes;
     99 
    100     return @Struct(
    101         std.lang.Type.ContainerLayout.@"packed",
    102         info.backing_integer,
    103         info.field_names,
    104         info.field_types,
    105         &@as(
    106             [info.field_attrs.len]Attributes,
    107             @splat(Attributes{
    108                 .@"align" = null,
    109                 .@"comptime" = false,
    110             }),
    111         ),
    112     );
    113 }
    114 
    115 pub fn add_field(orig: type, name: []const u8, tp: type, default: ?tp) type {
    116     const info = @typeInfo(orig).@"struct";
    117     const Attributes = std.lang.Type.Struct.FieldAttributes;
    118 
    119     return @Struct(
    120         info.layout,
    121         info.backing_integer,
    122         info.field_names ++ &.{name},
    123         info.field_types ++ &.{tp},
    124         info.field_attrs ++ &.{Attributes{
    125             .default_value_ptr = default,
    126         }},
    127     );
    128 }
    129 
    130 pub fn pack(s: anytype) pack_t(@TypeOf(s)) {
    131     const T = @TypeOf(s);
    132     const fields = @typeInfo(T).@"struct".field_names;
    133     var packed_struct: pack_t(T) = undefined;
    134 
    135     inline for (fields) |field| {
    136         @field(packed_struct, field) = @field(s, field);
    137     }
    138 
    139     return packed_struct;
    140 }
    141 
    142 pub fn enumFromStruct(str: type, backing: type) type {
    143     const field_names = @typeInfo(str).@"struct".field_names;
    144 
    145     comptime var field_values: [field_names.len]backing = undefined;
    146 
    147     for (&field_values, 0..) |*pt, i|
    148         pt.* = i;
    149 
    150     return @Enum(
    151         backing,
    152         std.lang.Type.Enum.Mode.exhaustive,
    153         field_names,
    154         &field_values,
    155     );
    156 }
    157 
    158 pub fn zero(ptr: anytype) void {
    159     @memset(@as([*]u8, @ptrCast(ptr))[0..@sizeOf(@TypeOf(ptr))], 0);
    160 }
    161 
    162 pub fn zeroed(typ: type) typ {
    163     var ret: typ = undefined;
    164     zero(&ret);
    165     return ret;
    166 }
    167 
    168 pub fn typepun(Ret: type, val: anytype) Ret {
    169     if (@alignOf(@TypeOf(val)) < @alignOf(Ret)) {
    170         var ret = zeroed(Ret);
    171         @as(*@TypeOf(val), @ptrCast(&ret)).* = val;
    172         return ret;
    173     } else {
    174         return @as(*const Ret, @ptrCast(&val)).*;
    175     }
    176 }