Text string - chung-leong/zigar GitHub Wiki

There is no specialized string type in the Zig language. Text strings are usually stored in []u8 using UTF-8 encoding. Since the same data type is used to store raw binary data, the Zigar runtime does not automatically interpret []u8 as text. You have to instead access a special property to obtain a string:

This is not a huge burden usually. It does prevent valueOf() from returning sensible results in a situation like the following:

pub const Avenger = struct {
    real_name: []const u8,
    superhero_name: []const u8,
    age: u32,
};

pub const spiderman: Avenger = .{
    .real_name = "Peter Parker",
    .superhero_name = "Spiderman",
    .age = 17,
};
import { spiderman } from './string-example-1.zig';

console.log(spiderman.valueOf());
{
  real_name: [
     80, 101, 116, 101, 114,
     32,  80,  97, 114, 107,
    101, 114
  ],
  superhero_name: [
     83, 112, 105, 100,
    101, 114, 109,  97,
    110
  ],
  age: 17
}

This also affects the output from JSON.stringify(). To deal with this rather annoying issue, Zigar gives you a way of flagging particular fields as being strings. It involves a namespace with a special name:

pub const Avenger = struct {
    real_name: []const u8,
    superhero_name: []const u8,
    age: u32,
};

pub const spiderman: Avenger = .{
    .real_name = "Peter Parker",
    .superhero_name = "Spiderman",
    .age = 17,
};

pub const @"meta(zigar)" = struct {
    pub fn isFieldString(comptime T: type, comptime field_name: []const u8) bool {
        _ = field_name;
        return switch (T) {
            Avenger => true,
            else => false,
        };
    }
};
import { spiderman } from './string-example-2.zig';

console.log(spiderman.real_name);
console.log(spiderman.superhero_name);
console.log(spiderman.valueOf());
Peter Parker
Spiderman
{ real_name: 'Peter Parker', superhero_name: 'Spiderman', age: 17 }

The namespace @"meta(zigar)" must be declared in the root module. A declaration by that name in an imported module would have zero effect. Zigar wouldn't even have access to it.

You can also make the return value of a function a string:

const std = @import("std");
pub const allocUpperString = std.ascii.allocUpperString;

pub const @"meta(zigar)" = struct {
    pub fn isRetvalString(comptime func: anytype) bool {
        const list = .{
            std.ascii.allocUpperString,
        };
        return inline for (list) |f| {
            if (@TypeOf(func) == @TypeOf(f) and func == f) break true;
        } else false;
    }
};
import { allocUpperString } from './string-example-3.zig';

console.log(allocUpperString('hello world'));
HELLO WORLD

Note the type comparison, which keeps a mismatched function type error from occurring.

Arguments to callback functions can also be flagged:

pub const Callback = fn ([]const u8) error{Unexpected}!void;

pub fn call(cb: *const Callback) !void {
    try cb("Hello world!");
}

pub const @"meta(zigar)" = struct {
    pub fn isArgumentString(comptime FT: type, comptime arg_index: usize) bool {
        _ = arg_index;
        return switch (FT) {
            Callback => true,
            else => false,
        };
    }
};
import { call } from './string-example-4.zig';

call(s => console.log(s));
Hello world!