I’m writing a parser that keeps current character position as i
of the type usize
. Later I realized that I need to shift it sometimes. Shifting forward is no brainer – the shift: usize
is added with saturation +|
to i
. However, when I changed shift
to the type isize
and tired to add it to usize
, I obviously got an error of incompatible types.
var i: usize = 100;
const shift: isize = -20;
// i + shift magic
expect(i == 80)
expect(@TypeOf(i) == usize)
Tinkering with @as
didn’t give me a result and I’m left with the fact that I don’t know how to add negative integers to unsigned ones.
Update:
While writing this post, I got the solution:
var i: usize = 100;
const shift: isize = -20;
// magic
const i_shifted: usize = @max(0, @as(isize, @intCast(i)) + shift);
// works fine
assert(i == 80)
assert(@TypeOf(i) == usize)
However,
(1) I’m unsure whether it is the right way to do it (just in case, shift and i should be assumed subjects to runtime changes).
(2) I’m unsure about my type choices. Let me explain.
My current stream of bytes is represented as a string literal in the source code but I plan to move to reading from file. With a bit of C background, I get used to the idea (not sure where I get it) that usize
represents the “maximum size of addressable memory” and it is suitable for generic “indexing”. In its turn, isize
em… its signed counterpart? Basically, using usize
put you in a “safe zone” — if a platform supports only 16bit size integers, your program will be allegedly switched to that amount and keep working.
However, after looking at zig/lib/std/fs/File.zig
, I noticed that types used for specifying seeking offsets are u64
and i64
. Now, I wonder whether Zig is limited to only 64bit platforms and filesystems when it comes to handling files in a generic platform-independent way.