diff --git a/src/io.zig b/src/io.zig index 88e1caa..58a3c38 100644 --- a/src/io.zig +++ b/src/io.zig @@ -10,7 +10,7 @@ pub const Writer = struct { writeContext: fn (*anyopaque, []const u8) usize, /// - /// + /// Radices supported by [writeInt]. /// pub const Radix = enum { binary, @@ -79,39 +79,45 @@ pub const Writer = struct { const Int = @TypeOf(value); const type_info = @typeInfo(Int); - if (type_info != .Int) @compileError("value must be of type int"); + switch (type_info) { + .Int => { + if (value == 0) return writer.writeByte('0'); - if (value == 0) return writer.writeByte('0'); + // TODO: Unhardcode this as it will break with large ints. + var buffer = std.mem.zeroes([28]u8); + var buffer_count = @as(usize, 0); + var n1 = value; - // TODO: Unhardcode this as it will break with large ints. - var buffer = std.mem.zeroes([28]u8); - var buffer_count = @as(usize, 0); - var n1 = value; + if ((type_info.Int.signedness == .signed) and (value < 0)) { + // Negative value. + n1 = -value; + buffer[0] = '-'; + buffer_count += 1; + } - if ((type_info.Int.signedness == .signed) and (value < 0)) { - // Negative value. - n1 = -value; - buffer[0] = '-'; - buffer_count += 1; + while (n1 != 0) { + const base = @enumToInt(radix); + + buffer[buffer_count] = @intCast(u8, (n1 % base) + '0'); + n1 = (n1 / base); + buffer_count += 1; + } + + for (buffer[0 .. (buffer_count / 2)]) |_, i| + std.mem.swap(u8, &buffer[i], &buffer[buffer_count - i - 1]); + + return (writer.write(buffer[0 .. buffer_count]) == buffer_count); + }, + + // Cast comptime int into known-size integer and try again. + .ComptimeInt => return writer. + writeInt(radix, @intCast(std.math.IntFittingRange(value, value), value)), + + else => @compileError("value must be of type int"), } - - while (n1 != 0) { - const base = @enumToInt(radix); - - buffer[buffer_count] = @intCast(u8, (n1 % base) + '0'); - n1 = (n1 / base); - buffer_count += 1; - } - - for (buffer[0 .. (buffer_count / 2)]) |_, i| - std.mem.swap(u8, &buffer[i], &buffer[buffer_count - i - 1]); - - return (writer.write(buffer[0 .. buffer_count]) == buffer_count); } }; -var null_context = @as(usize, 0); - /// /// Writer that silently throws consumed data away and never fails. /// @@ -119,13 +125,10 @@ var null_context = @as(usize, 0); /// sent somewhere for whatever reason. /// pub const null_writer = Writer{ - .context = (&null_context), - - .operation = struct { - fn write(context: *anyopaque, buffer: []const u8) usize { - // Validate context canary value. - std.debug.assert(@ptrCast(*usize, @alignCast(@alignOf(usize), context)).* == 0); + .context = undefined, + .writeContext = struct { + fn write(_: *anyopaque, buffer: []const u8) usize { return buffer.len; } }.write, @@ -137,9 +140,9 @@ test { { const sequence = "foo"; - testing.expectEqual(null_writer.write(sequence), sequence.len); + try testing.expectEqual(null_writer.write(sequence), sequence.len); } - testing.expect(null_writer.writeByte(0)); - testing.expect(null_writer.writeInt(.decimal, 420)); + try testing.expect(null_writer.writeByte(0)); + try testing.expect(null_writer.writeInt(.decimal, 420)); }