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 }