| author | |
| committer | |
| log | bb956f2cf60cf5983309a22f1f88facda0a04a16 |
| tree | 2df82220662c44bac353d120f30feae25296efb8 |
| parent | 2cb1b3d619b10f4ad2c870f0359adb0c6129ca67 |
| signature |
13 files changed, 67 insertions(+), 95 deletions(-)
README.md+1-1| ... | @@ -3,7 +3,7 @@ | ... | @@ -3,7 +3,7 @@ |
| 3 |  | 3 |  |
| 4 | [](https://github.com/nektro/zig-extras/blob/master/LICENSE) | 4 | [](https://github.com/nektro/zig-extras/blob/master/LICENSE) |
| 5 | [](https://github.com/sponsors/nektro) | 5 | [](https://github.com/sponsors/nektro) |
| 6 | [](https://ziglang.org/) | 6 | [](https://ziglang.org/) |
| 7 | [](https://github.com/nektro/zigmod) | 7 | [](https://github.com/nektro/zigmod) |
| 8 | 8 | ||
| 9 | An assortment of random utility functions that aren't in std and don't deserve their own package. | 9 | An assortment of random utility functions that aren't in std and don't deserve their own package. |
src/FieldUnion.zig+9-14| ... | @@ -4,22 +4,17 @@ const extras = @import("./lib.zig"); | ... | @@ -4,22 +4,17 @@ const extras = @import("./lib.zig"); |
| 4 | const expectSimilarType = extras.expectSimilarType; | 4 | const expectSimilarType = extras.expectSimilarType; |
| 5 | 5 | ||
| 6 | pub fn FieldUnion(comptime T: type) type { | 6 | pub fn FieldUnion(comptime T: type) type { |
| 7 | const infos = std.meta.fields(T); | 7 | const fields = std.meta.fields(T); |
| 8 | var names: [fields.fields.len][]const u8 = undefined; | ||
| 9 | var types: [fields.fields.len]type = undefined; | ||
| 10 | var attrs: [fields.fields.len]std.builtin.Type.UnionField.Attributes = undefined; | ||
| 8 | 11 | ||
| 9 | var fields: [infos.len]std.builtin.Type.UnionField = undefined; | 12 | inline for (fields, 0..) |field, i| { |
| 10 | inline for (infos, 0..) |field, i| { | 13 | names[i] = field.name; |
| 11 | fields[i] = .{ | 14 | types[i] = field.type; |
| 12 | .name = field.name, | 15 | attrs[i] = .{ .@"align" = field.alignment }; |
| 13 | .type = field.type, | ||
| 14 | .alignment = field.alignment, | ||
| 15 | }; | ||
| 16 | } | 16 | } |
| 17 | return @Type(std.builtin.Type{ .@"union" = .{ | 17 | return @Union(.auto, std.meta.FieldEnum(T), &names, &types, &attrs); |
| 18 | .layout = .auto, | ||
| 19 | .tag_type = std.meta.FieldEnum(T), | ||
| 20 | .fields = &fields, | ||
| 21 | .decls = &.{}, | ||
| 22 | } }); | ||
| 23 | } | 18 | } |
| 24 | 19 | ||
| 25 | test { | 20 | test { |
src/FlippedInt.zig+8-6| ... | @@ -3,12 +3,14 @@ const string = []const u8; | ... | @@ -3,12 +3,14 @@ const string = []const u8; |
| 3 | const extras = @import("./lib.zig"); | 3 | const extras = @import("./lib.zig"); |
| 4 | 4 | ||
| 5 | pub fn FlippedInt(comptime T: type) type { | 5 | pub fn FlippedInt(comptime T: type) type { |
| 6 | var info = @typeInfo(T); | 6 | const info = @typeInfo(T).int; |
| 7 | info.int.signedness = switch (info.int.signedness) { | 7 | return @Int( |
| 8 | .signed => .unsigned, | 8 | switch (info.signedness) { |
| 9 | .unsigned => .signed, | 9 | .signed => .unsigned, |
| 10 | }; | 10 | .unsigned => .signed, |
| 11 | return @Type(info); | 11 | }, |
| 12 | info.signedness, | ||
| 13 | ); | ||
| 12 | } | 14 | } |
| 13 | 15 | ||
| 14 | test { | 16 | test { |
src/LoggingReader.zig+1-1| ... | @@ -2,7 +2,7 @@ const std = @import("std"); | ... | @@ -2,7 +2,7 @@ const std = @import("std"); |
| 2 | const string = []const u8; | 2 | const string = []const u8; |
| 3 | const extras = @import("./lib.zig"); | 3 | const extras = @import("./lib.zig"); |
| 4 | 4 | ||
| 5 | pub fn LoggingReader(comptime T: type, comptime scope: @Type(.EnumLiteral)) type { | 5 | pub fn LoggingReader(comptime T: type, comptime scope: @EnumLiteral()) type { |
| 6 | return struct { | 6 | return struct { |
| 7 | child_stream: T, | 7 | child_stream: T, |
| 8 | 8 |
src/LoggingWriter.zig+1-1| ... | @@ -2,7 +2,7 @@ const std = @import("std"); | ... | @@ -2,7 +2,7 @@ const std = @import("std"); |
| 2 | const string = []const u8; | 2 | const string = []const u8; |
| 3 | const extras = @import("./lib.zig"); | 3 | const extras = @import("./lib.zig"); |
| 4 | 4 | ||
| 5 | pub fn LoggingWriter(comptime T: type, comptime scope: @Type(.EnumLiteral)) type { | 5 | pub fn LoggingWriter(comptime T: type, comptime scope: @EnumLiteral()) type { |
| 6 | return struct { | 6 | return struct { |
| 7 | child_stream: T, | 7 | child_stream: T, |
| 8 | 8 |
src/OneBiggerInt.zig+2-3| ... | @@ -3,9 +3,8 @@ const string = []const u8; | ... | @@ -3,9 +3,8 @@ const string = []const u8; |
| 3 | const extras = @import("./lib.zig"); | 3 | const extras = @import("./lib.zig"); |
| 4 | 4 | ||
| 5 | pub fn OneBiggerInt(comptime T: type) type { | 5 | pub fn OneBiggerInt(comptime T: type) type { |
| 6 | var info = @typeInfo(T); | 6 | const info = @typeInfo(T).int; |
| 7 | info.int.bits += 1; | 7 | return @Int(info.signedness, info.bits + 1); |
| 8 | return @Type(info); | ||
| 9 | } | 8 | } |
| 10 | 9 | ||
| 11 | test { | 10 | test { |
src/OneSmallerInt.zig+2-3| ... | @@ -3,9 +3,8 @@ const string = []const u8; | ... | @@ -3,9 +3,8 @@ const string = []const u8; |
| 3 | const extras = @import("./lib.zig"); | 3 | const extras = @import("./lib.zig"); |
| 4 | 4 | ||
| 5 | pub fn OneSmallerInt(comptime T: type) type { | 5 | pub fn OneSmallerInt(comptime T: type) type { |
| 6 | var info = @typeInfo(T); | 6 | const info = @typeInfo(T).int; |
| 7 | info.int.bits -= 1; | 7 | return @Int(info.signedness, info.bits - 1); |
| 8 | return @Type(info); | ||
| 9 | } | 8 | } |
| 10 | 9 | ||
| 11 | test { | 10 | test { |
src/Partial.zig+9-17| ... | @@ -6,24 +6,16 @@ const expectSimilarType = extras.expectSimilarType; | ... | @@ -6,24 +6,16 @@ const expectSimilarType = extras.expectSimilarType; |
| 6 | /// Creates a new version of struct T where all fields are optional. | 6 | /// Creates a new version of struct T where all fields are optional. |
| 7 | /// Name inspried by https://www.typescriptlang.org/docs/handbook/utility-types.html#partialtype. | 7 | /// Name inspried by https://www.typescriptlang.org/docs/handbook/utility-types.html#partialtype. |
| 8 | pub fn Partial(comptime T: type) type { | 8 | pub fn Partial(comptime T: type) type { |
| 9 | const fields_before = std.meta.fields(T); | 9 | const fields = std.meta.fields(T); |
| 10 | var fields_after: [fields_before.len]std.builtin.Type.StructField = undefined; | 10 | var names: [fields.len][]const u8 = undefined; |
| 11 | inline for (fields_before, 0..) |item, i| { | 11 | var types: [fields.len]type = undefined; |
| 12 | fields_after[i] = std.builtin.Type.StructField{ | 12 | var attrs: [fields.len]std.builtin.Type.StructField.Attributes = undefined; |
| 13 | .name = item.name, | 13 | for (fields, 0..) |item, i| { |
| 14 | .type = ?item.type, | 14 | names[i] = item.name; |
| 15 | .default_value_ptr = &@as(?item.type, null), | 15 | types[i] = ?item.type; |
| 16 | .is_comptime = false, | 16 | attrs[i] = .{ .default_value_ptr = &@as(?item.type, null) }; |
| 17 | .alignment = @alignOf(?item.type), | ||
| 18 | }; | ||
| 19 | } | 17 | } |
| 20 | return @Type(@unionInit(std.builtin.Type, "struct", .{ | 18 | return @Struct(.auto, null, &names, &types, &attrs); |
| 21 | .layout = .auto, | ||
| 22 | .backing_integer = null, | ||
| 23 | .fields = &fields_after, | ||
| 24 | .decls = &.{}, | ||
| 25 | .is_tuple = false, | ||
| 26 | })); | ||
| 27 | } | 19 | } |
| 28 | 20 | ||
| 29 | test { | 21 | test { |
src/ReverseFields.zig+6-5| ... | @@ -4,14 +4,15 @@ const extras = @import("./lib.zig"); | ... | @@ -4,14 +4,15 @@ const extras = @import("./lib.zig"); |
| 4 | const expectSimilarType = extras.expectSimilarType; | 4 | const expectSimilarType = extras.expectSimilarType; |
| 5 | 5 | ||
| 6 | pub fn ReverseFields(comptime T: type) type { | 6 | pub fn ReverseFields(comptime T: type) type { |
| 7 | var info = @typeInfo(T).@"struct"; | 7 | const info = @typeInfo(T).@"struct"; |
| 8 | const len = info.fields.len; | 8 | const len = info.fields.len; |
| 9 | var fields: [len]std.builtin.Type.StructField = undefined; | 9 | var names: [len][]const u8 = undefined; |
| 10 | var types: [len]type = undefined; | ||
| 10 | for (0..len) |i| { | 11 | for (0..len) |i| { |
| 11 | fields[i] = info.fields[len - 1 - i]; | 12 | names[i] = info.fields[len - 1 - i].name; |
| 13 | types[i] = info.fields[len - 1 - i].type; | ||
| 12 | } | 14 | } |
| 13 | info.fields = &fields; | 15 | return @Struct(.auto, null, &names, &types, &@splat(.{})); |
| 14 | return @Type(.{ .@"struct" = info }); | ||
| 15 | } | 16 | } |
| 16 | 17 | ||
| 17 | test { | 18 | test { |
src/StructOfArrays.zig+5-16| ... | @@ -6,24 +6,13 @@ const expectSimilarType = extras.expectSimilarType; | ... | @@ -6,24 +6,13 @@ const expectSimilarType = extras.expectSimilarType; |
| 6 | pub fn StructOfArrays(len: usize, T: type) type { | 6 | pub fn StructOfArrays(len: usize, T: type) type { |
| 7 | const info = @typeInfo(T).@"struct"; | 7 | const info = @typeInfo(T).@"struct"; |
| 8 | const fields = info.fields; | 8 | const fields = info.fields; |
| 9 | var new_fields: [fields.len]std.builtin.Type.StructField = undefined; | 9 | var names: [fields.len][]const u8 = undefined; |
| 10 | var types: [fields.len]type = undefined; | ||
| 10 | for (fields, 0..) |item, i| { | 11 | for (fields, 0..) |item, i| { |
| 11 | new_fields[i] = .{ | 12 | names[i] = item.name; |
| 12 | .name = item.name, | 13 | types[i] = [len]item.type; |
| 13 | .type = [len]item.type, | ||
| 14 | .default_value_ptr = null, | ||
| 15 | .is_comptime = false, | ||
| 16 | .alignment = @alignOf([len]item.type), | ||
| 17 | }; | ||
| 18 | } | 14 | } |
| 19 | const result = new_fields[0..fields.len]; | 15 | return @Struct(.auto, null, &names, &types, &@splat(.{})); |
| 20 | return @Type(@unionInit(std.builtin.Type, "struct", .{ | ||
| 21 | .layout = .auto, | ||
| 22 | .backing_integer = null, | ||
| 23 | .fields = result, | ||
| 24 | .decls = &.{}, | ||
| 25 | .is_tuple = info.is_tuple, | ||
| 26 | })); | ||
| 27 | } | 16 | } |
| 28 | 17 | ||
| 29 | test { | 18 | test { |
src/StructOfSlices.zig+5-16| ... | @@ -6,24 +6,13 @@ const expectSimilarType = extras.expectSimilarType; | ... | @@ -6,24 +6,13 @@ const expectSimilarType = extras.expectSimilarType; |
| 6 | pub fn StructOfSlices(T: type) type { | 6 | pub fn StructOfSlices(T: type) type { |
| 7 | const info = @typeInfo(T).@"struct"; | 7 | const info = @typeInfo(T).@"struct"; |
| 8 | const fields = info.fields; | 8 | const fields = info.fields; |
| 9 | var new_fields: [fields.len]std.builtin.Type.StructField = undefined; | 9 | var names: [fields.len][]const u8 = undefined; |
| 10 | var types: [fields.len]type = undefined; | ||
| 10 | for (fields, 0..) |item, i| { | 11 | for (fields, 0..) |item, i| { |
| 11 | new_fields[i] = .{ | 12 | names[i] = item.name; |
| 12 | .name = item.name, | 13 | types[i] = []const item.type; |
| 13 | .type = []const item.type, | ||
| 14 | .default_value_ptr = null, | ||
| 15 | .is_comptime = false, | ||
| 16 | .alignment = @alignOf([]const item.type), | ||
| 17 | }; | ||
| 18 | } | 14 | } |
| 19 | const result = new_fields[0..fields.len]; | 15 | return @Struct(.auto, null, &names, &types, &@splat(.{})); |
| 20 | return @Type(@unionInit(std.builtin.Type, "struct", .{ | ||
| 21 | .layout = .auto, | ||
| 22 | .backing_integer = null, | ||
| 23 | .fields = result, | ||
| 24 | .decls = &.{}, | ||
| 25 | .is_tuple = info.is_tuple, | ||
| 26 | })); | ||
| 27 | } | 16 | } |
| 28 | 17 | ||
| 29 | test { | 18 | test { |
src/join.zig+5-9| ... | @@ -14,17 +14,13 @@ pub fn join(input: anytype) Join(@TypeOf(input)) { | ... | @@ -14,17 +14,13 @@ pub fn join(input: anytype) Join(@TypeOf(input)) { |
| 14 | } | 14 | } |
| 15 | 15 | ||
| 16 | pub fn Join(comptime T: type) type { | 16 | pub fn Join(comptime T: type) type { |
| 17 | var fields: []const std.builtin.Type.StructField = &.{}; | 17 | var names: [][]const u8 = &.{}; |
| 18 | var types: []type = &.{}; | ||
| 18 | inline for (std.meta.fields(T)) |item| { | 19 | inline for (std.meta.fields(T)) |item| { |
| 19 | inline for (std.meta.fields(item.type)) |f| { | 20 | inline for (std.meta.fields(item.type)) |f| { |
| 20 | fields = fields ++ &[_]std.builtin.Type.StructField{.{ | 21 | names = names ++ &[_][]const u8{f.name}; |
| 21 | .name = f.name, | 22 | types = types ++ &[_]type{f.type}; |
| 22 | .type = f.type, | ||
| 23 | .default_value_ptr = null, | ||
| 24 | .is_comptime = false, | ||
| 25 | .alignment = @alignOf(f.type), | ||
| 26 | }}; | ||
| 27 | } | 23 | } |
| 28 | } | 24 | } |
| 29 | return @Type(.{ .@"struct" = .{ .layout = .auto, .fields = fields, .decls = &.{}, .is_tuple = false } }); | 25 | return @Struct(.auto, null, &names, &types, &@splat(.{})); |
| 30 | } | 26 | } |
src/omit.zig+13-3| ... | @@ -14,12 +14,22 @@ pub fn omit(value: anytype, comptime field_name: []const u8) Omit(@TypeOf(value) | ... | @@ -14,12 +14,22 @@ pub fn omit(value: anytype, comptime field_name: []const u8) Omit(@TypeOf(value) |
| 14 | 14 | ||
| 15 | pub fn Omit(T: type, field_name: []const u8) type { | 15 | pub fn Omit(T: type, field_name: []const u8) type { |
| 16 | const fields_original = std.meta.fields(T); | 16 | const fields_original = std.meta.fields(T); |
| 17 | var fields: [fields_original.len - 1]std.builtin.Type.StructField = undefined; | 17 | const len = fields_original.len - 1; |
| 18 | var names: [len][]const u8 = undefined; | ||
| 19 | var types: [len]type = undefined; | ||
| 20 | var attrs: [len]std.builtin.Type.StructField.Attributes = undefined; | ||
| 18 | var i: usize = 0; | 21 | var i: usize = 0; |
| 19 | for (fields_original) |f| { | 22 | for (fields_original) |f| { |
| 20 | if (std.mem.eql(u8, f.name, field_name)) continue; | 23 | if (std.mem.eql(u8, f.name, field_name)) continue; |
| 21 | fields[i] = f; | 24 | names[i] = f.name; |
| 25 | types[i] = f.type; | ||
| 26 | attrs[i] = .{ | ||
| 27 | .@"comptime" = f.is_comptime, | ||
| 28 | .@"align" = f.alignment, | ||
| 29 | .default_value_ptr = f.default_value_ptr, | ||
| 30 | }; | ||
| 22 | i += 1; | 31 | i += 1; |
| 23 | } | 32 | } |
| 24 | return @Type(.{ .@"struct" = .{ .layout = .auto, .fields = &fields, .decls = &.{}, .is_tuple = false } }); | 33 | return @Struct(.auto, null, &names, &types, &attrs); |
| 34 | // return @Type(.{ .@"struct" = .{ .layout = .auto, .fields = &fields, .decls = &.{}, .is_tuple = false } }); | ||
| 25 | } | 35 | } |