Hi, it's my first day learning Zig. I'm going through the Introduction to Zig book (https://pedropark99.github.io/zig-book), and while making the base64 encoder/decoder I was wondering how I would build the decode look-up table correctly. I have around 7 years of experience in Rust and a couple in C and C++, so explanations with references to those languages would be helpful!
Here is what I came up with after some experimentation:
const Base64 = struct {
_table: *const [64]u8, // this was part of the tutorial
_rev_table: *const [128]u8, // my addition
pub fn init() Base64 {
// this is how they built the encoding LUT in the tutorial:
const upper = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
const lower = "abcdefghijklmnopqrstuvwxyz";
const numbers_symb = "0123456789+/";
const table = upper ++ lower ++ numbers_symb;
// what I came up with for the inverse LUT:
const rev_table = comptime build_rev_table(table);
return Base64{
._table = table,
._rev_table = &rev_table, // will this not result in use after free?
};
}
fn build_rev_table(table: *const [64]u8) [128]u8 {
var rev_table: [128]u8 = undefined;
@memset(rev_table[0..], 0xff);
for (table, 0..) |c, i| {
rev_table[c] = @intCast(i);
}
return rev_table;
}
// ...
}
My questions:
- Is this safe? I have not read the
comptimesection yet so maybe there is some rule about things not being freed at the end of scope if they are computed at compile time or maybe I misunderstanding it entirely. - I tried using a
comptimeblock at first (instead of a function), but I couldn't figure out how to return something from the block without returning from a function. Is there something like that in Zig? (returning just from the current scope) - How would you make a LUT? Feel free to use advanced features, I can google things if needed. 🙂