Convert comptime_int to a slice of u8

I’m writing two functions hexFromBinary() and binaryFromHex(), and I found that std.zig.parseNumberLiteral() accepts a slice of u8 (bytes: []const u8) to iterate, so I want to reuse the logic or to copy part of that, meaning I might need to convert comptime_int to []const u8, so I chose the @as builtin:

fn binaryFromHex(hex: comptime_int) !u32 {
    const bytes = @as([]const u8, hex);
    _ = bytes;
}

but it seemed it’s not the expected usage of @as.

expected type '[]const u8', found 'comptime_int'

The doc said the operand of @as must be unambiguous, or should I choose u32 or whater for the type of parameter “hex” here, but I would like to let compiler to infer the type because maybe the hex would be really big, say const long_hex_num = F << 20? Anyway, is it possble to convert comptime_int to []const u8 or not?

@as only does coercion, in other words, it only does what you can do with const b: T = a;

fortunately comptime_int does coerce to u8, so you can just do &[_]u8{hex} (which is actually a pointer to an array, but that will coerce to a slice)

It seemed that hex is treated as the placeholder of u8 here. I get the idea to convert comptime_int to an array of u8 which will be converted to a slice implictly. But I think the hex, say 0xabcd, would like to be an array .{ '0', 'x', 'a', 'b', 'c', 'd' } because I want to check whether it is a hex number or binary one from the function argument. Maybe we can to get the raw string of that comptime_int and then convert it to an array of u8?

Hex isn’t a different kind of number, it is a visual format for representing number values; integers in Zig, and every other language, are only values not visual formats.

it doesn’t matter if it’s a comptime_int or an explicitly sized integer, you don’t get any info about the format the programmer wrote it in. You don’t even know if it was written manually or the result of some math or logic.

If you want text you should ask for text, that is a []const u8. Zig doesn’t have a string/text type for the same reason Zig doesn’t have a hex/decimal integer types, there are many formats/encodings; though Zig only supports one for what programmers can manually write.

I should specify the format in a Io.Writer.print(), like {X}, {b} to get the different format of the same integer value. As for binaryFromHex(), it should be a wrapper of that formatting function. That makes sense, and since format are not encoded as integer type information, I should rename these two functions into toFmtBinary(num: comptime_int) and toFmtHex(num: comptime_int) no matter paramater num is of format hex or whatever. Yeah it should be that. Thanks vulpesx!

Hi, I’ve just come across this but I don’t really understand how int to u8 slice coercion works. After reading this I would try to do something like this:

var ebx: u32 = undefined;
// ... ebx variable is loaded in code here
var genuine = @as([]const u8, &[_]u8{ebx});

However this produces this error in the compiler:

src/bootloader/arch/x86_64/page.zig:249:43: error: expected type 'u8', found 'u32'
    var genuine= @as([]const u8, &[_]u8{ebx});
                                          ^~~
src/bootloader/arch/x86_64/page.zig:249:43: note: unsigned 8-bit int cannot represent all possible unsigned 32-bit values

The error makes sense to me, but I do not know how to specify the compiler that is not an u32 but an array of 4 u8

Look into std.mem.readInt and writeInt, and their tests

I think what you’re looking for is:

var genuine: [4]u8 = undefined;
std.mem.writeInt(u32, &genuine, ebx, .little);

(And you can of course use @bitCast directly instead of writeInt, if you’d prefer)

Awesome, @bitCast was exactly what I wanted, thank you so much

There is std.mem.toBytes which gives a copy of the bytes as an array,

or asBytes which gives a pointer to the same bytes

These will include padding bytes/bits, @bitCast will not (and is always a copy)