Skip to content
Chung Leong edited this page Feb 15, 2024 · 7 revisions

In Zig, there are two varieties of integers: signed and unsigned. The former has the prefix i and is used when negative values are possible. The latter has the prefix u and is used when a variable is always positive. Integers in Zig have arbitrary bit-size (up to 65535). Ones that are 32-bit or smaller are represented in JavaScript as number. Those larger than 32-bit are represented as bigint.

pub fn getInt32(number: i32) i32 {
    return number;
}

pub fn getInt33(number: i33) i33 {
    return number;
}
import { getInt32, getInt33 } from './int-example-1.zig';

console.log(typeof getInt32(1234));
console.log(typeof getInt33(1234));
number
bigint

Two special integer types, isize and usize, can be either number or bigint in JavaScript depending on whether their values exceed MAX_SAFE_INTEGER.

pub fn getIntSize(number: isize) isize {
    return number;
}

pub fn getUintSize(number: usize) usize {
    return number;
}
import { getIntSize, getUintSize } from './int-example-2.zig';

console.log(typeof getIntSize(0x7FFF_FFFF_FFFF_FFFFn));
console.log(typeof getIntSize(0x001F_FFFF_FFFF_FFFFn));
console.log(typeof getUintSize(0xFFFF_FFFF_FFFF_FFFFn));
console.log(typeof getUintSize(1));
bigint
number
bigint
number

Range checking

When runtime safety is active (i.e. when optimize is Debug or ReleaseSafe), values exceeding a type's range will cause an error to be thrown on the JavaScript side.

const std = @import("std");

pub fn print8(number: i8) void {
    std.debug.print("number = {d}\n", .{number});
}
import { print8 } from './int-example-3.zig&optimize=Debug';

try {
   print8(128);
} catch (err) {
   console.log(err.message);
}
print8(args[0]): Int8 cannot represent the value given: 128

When runtime safety is off, an integer overflow would not cause an error. Te value would simply wrap around.

import { print8 } from './int-example-3.zig&optimize=ReleaseSmall';

print8(128);
-128

In packed struct

Integers smaller than 8-bit like u2 or u4 are typically only used in packed struct. Using only as many bits as necessary for the range required helps reduce the size of data structures.

pub const UserPreferences = packed struct {
    option1: bool = false,
    option2: u2 = 0,
    option3: u3 = 0,
    option4: u4 = 0,
    option5: bool = false,
    option6: bool = false,
    option7: u2 = 0,
    option8: u2 = 0,
};
import { UserPreferences } from './int-example-4.zig';

const pref = new UserPreferences({ 
    option2: 2,
    option3: 7,
    option4: 15,
    option7: 1,
    option8: 3,
});
console.log(pref.valueOf());
console.log(`size = ${pref.dataView.byteLength}`);
{
  option1: false,
  option2: 2,
  option3: 7,
  option4: 15,
  option5: false,
  option6: false,
  option7: 1,
  option8: 3
}
size = 2