#How to correctly build a look-up table at compile time?

1 messages · Page 1 of 1 (latest)

near stirrup
#

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:

  1. Is this safe? I have not read the comptime section 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.
  2. I tried using a comptime block 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)
  3. How would you make a LUT? Feel free to use advanced features, I can google things if needed. 🙂
patent sigil
#

answering questions 1 and 2:

  1. no, there will be no use after free, as comptime-known constants have static lifetime, the relevant section in the langref is this. this is akin to Rust, where this expression: &[1, 2, 3] will have type &'static [i32; 3].
  2. returning a value out of a block is possible, and is done with the following syntax:
const result = block_label: {
  // some computation...
  break :block_label computed;
};
```read more about that [here](https://ziglang.org/documentation/master/#toc-Blocks)
near stirrup
patent sigil
#

btw, instead of initialising rev_table to undefined and then @memseting it - you can use @splat:

var rev_table: [128]u8 = @splat(0xff);