#cast problam

1 messages · Page 1 of 1 (latest)

warm pumice
#

binary.zig:46:78: error: expected type 'u6', found 'usize'
value |= @as(usize, @intCast(b)) & @as(usize, @intCast(0x7F)) << @as(usize, @intCast(shift));
^~~~~~~~~~~~~~~~~~~~~~~~~~~

#
pub fn read7BitEncodedInt(self: Self) !usize {
        var value: usize = 0;
        var shift: usize = 0;

        while (true) {
            const b = try self.readByte();
            value |= @as(usize, @intCast(b)) & @as(usize, @intCast(0x7F)) << @as(usize, @intCast(shift));

            shift += 7;
            if (b & 0x80 == 0) {
                break;
            }
        }

        return value;
    }
stone fjord
#

the right-hand-side of a << or >> is a number with bit count equal to log2 of the number of bits of the type in the left-hand-side

#

for example, if the left-hand-side has type u64 the right-hand-side needs to have type u6

#

further, << has higher precedence than &, so you might want to parenthesise some stuff there...

warm pumice
#

0x371b0b in read7BitEncodedInt (binary.exe.obj)
value |= (@as(usize, @intCast(b)) & @as(usize, @intCast(0x7F))) << @as(u6, @intCast(shift));

pub fn read7BitEncodedInt(self: Self) !usize {
        var value: usize = 0;
        var shift: usize = 0;

        while (true) {
            const b = try self.readByte(); // i8
            value |= (@as(usize, @intCast(b)) & @as(usize, @intCast(0x7F))) << @as(u6, @intCast(shift));

            shift += 7;
            if (@as(usize, @intCast(b)) & @as(usize, @intCast(0x80)) == 0) {
                break;
            }
        }

        return value;
    }
stone fjord
#

this seems correct, does it compile?

warm pumice
stone fjord
#

what's the error message?

warm pumice
#

I get an error when I type with spaces
Otherwise it compiles without problems
for example
"Test" // no problem

"Test test" // error

 pub fn main() !void {
    var binary = binarystream{ .buff = std.ArrayList(u8).init(std.heap.page_allocator), .offset = 0 };
    try binary.writeByte(1);
    try binary.writeStrL(@constCast("Test test")); // error

    print("Hello your slice bytes .{any}", .{binary.buff.items});
    _ = try binary.readByte();
    const str: []u8 = try binary.readStringL();
    print("your text {}\n", .{std.unicode.fmtUtf8(str)});
}
#
pub fn writeStrL(self: Self, value: []u8) !void {
        const arraybyte: []u8 = value[0..];
        print("DEBUG : str length is {any}\n", .{arraybyte.len});
        try self.write7BitEncodedInt(@as(u8, @intCast(arraybyte.len)));
        try self.write(arraybyte[0..]);
    }
#
    pub fn write(self: Self, value: []const u8) !void {
        try self.buff.appendSlice(value);
    }
stone fjord
#

is it a compilation error or a runtime crash?

warm pumice
#

thread 3908 panic: attempt to cast negative value to unsigned integer

stone fjord
#

so you probably have some faulty logic somewhere...
skimming the code I do find a couple of weird things, for example you're @constCasting a string literal - writing to that pointer is illegal behaviour! do you really need it mutable, or can you change the type of the value argument in writeStrL to be []const u8?

warm pumice
#

But now I have the error

stone fjord
warm pumice
stone fjord
#

why the @bitCast? why not simply return integer[0]?
so:

pub fn readByte(self: Self) !u8 {
    const integer: []u8 = try self.read(1);
    return integer[0];
}

or even more terse:

pub fn readByte(self: Self) !u8 {
    return (try self.read(1))[0];
}
warm pumice
#

DEBUG : str length is 9
.{ 1, 137, 84, 101, 115, 116, 32, 116, 101, 115, 116 }
thread 9304 panic: index out of bounds: index 10764, len 11

in read (binary.exe.obj)
const buffer: []u8 = self.buff.items[self.offset .. self.offset + size];
0xed1cfd in main (binary.exe.obj)
const str: []u8 = try binary.readStringL();

pub fn read(self: Self, size: usize) ![]u8 {
        const buffer: []u8 = self.buff.items[self.offset .. self.offset + size];
        self.offset += size;
        return buffer;
    }
stone fjord
#

your slicing is going out-of-bounds, so either size, self.offset, or the addition of the two is too large. without more context I can't help you much.

warm pumice
#
pub fn writeByte(self: Self, value: u8) !void {
        const arraybyte: [1]u8 = [_]u8{value};
        try self.write(arraybyte[0..1]);
    }
    pub fn writeStrL(self: Self, value: []const u8) !void {
        const arraybyte: []const u8 = value[0..];
        print("DEBUG : str length is {any}\n", .{arraybyte.len});
        try self.write7BitEncodedInt(@as(u8, @intCast(arraybyte.len)));
        try self.write(arraybyte[0..]);
    }
    pub fn write(self: Self, value: []const u8) !void {
        try self.buff.appendSlice(value);
    }
    pub fn write7BitEncodedInt(self: Self, value: u8) !void {
        while (true) {
            const a = value & 0x7F;
            const b = value << 7;
            if (b == 0) {
                try self.writeByte(a);
                break;
            } else {
                try self.writeByte(a | 0x80);
                break;
            }
        }
    }
    pub fn read(self: Self, size: usize) ![]u8 {
        const buffer: []u8 = self.buff.items[self.offset .. self.offset + size];
        self.offset += size;
        return buffer;
    }
#
pub fn read7BitEncodedInt(self: Self) !usize {
        var value: usize = 0;
        var shift: usize = 0;

        while (true) {
            const b = try self.readByte();
            value |= (@as(usize, @intCast(b)) & @as(usize, @intCast(0x7F))) << @as(u6, @intCast(shift));
            shift += 7;
            if (@as(usize, @intCast(b)) & @as(usize, @intCast(0x80)) == 0) {
                break;
            }
        }
        return value;
    }
    pub fn readStringL(self: Self) ![]u8 {
        const length = try self.read7BitEncodedInt();
        const buff = try self.read(length);
        return buff;
    }
    pub fn readByte(self: Self) !u8 {
        return (try self.read(1))[0];
    }
stone fjord
#

I think you may have a problem with the logic of your (write|read)7BitEncodedInt...
it looks like you're trying to serialise a slice of bytes into some buffer, and you store the length metadata as this series of bytes, with an indicator for the last byte in the metadata.
why not just always use 8 bytes, and store the length there?

stone fjord
#

I see, so you need it for compatibility with existing code...
your write7BitEncodedInt function takes in a u8 as a value - I think this is a mistake, and you actually want a bigger type

warm pumice
#
 
public static void write7BitEncodedInt(int i, ByteBuf buf) {
        int num;
        for(num = i; num >= 128; num >>= 7) {
            buf.writeByte((byte)(num | 0x80));
        }
        buf.writeByte((byte)num);
    }

#

This is in Java

stone fjord
#

this looks correct

#

your translation to Zig is incorrect - do you want to have a look at it yourself, or should I spoil the answer for you?

warm pumice
#

pub fn write7BitEncodedInt(self: Self, value: u8) !void {
var num = value;
while (num >= 128) {
try self.writeByte((num | 0x80));
num >>= 7;
}
}
not work

#

The same error as before

stone fjord
#

that's because the code is incorrect.

#

first, notice that your value argument has type u8, it should probably have type usize...
and after the while loop is over you still need to write out the last byte, which you are not doing

warm pumice
#

pub fn write7BitEncodedInt(self: Self, value: u8) !void {
while (true) {
var b: u8 = value & 0x7F;
var value2 = value;
value2 >>= 7;
if (value2 == 0) {
try self.writeByte(b);
break;
} else {
b |= 0x80;
try self.writeByte(b);
}
}
}
The problem was solved

#

thx

stone fjord
#

the problem is still there; try to pass writeStrL a string with length bigger than 255

stone fjord
#

try it and see what happens, I am pretty sure the program will crash

warm pumice
#

pub fn main() !void {
var binary = binarystream{ .buff = std.ArrayList(u8).init(std.heap.page_allocator), .offset = 0 };
try binary.writeByte(1);
try binary.writeStrL("Hello World sss sss sdaddddddddddddddddddddddddddddddddddddddddddddddddddddddsdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd");
print(".{any}\n", .{binary.buff.items});
_ = try binary.readByte();
const str: []u8 = try binary.readStringL();
print("your text {}\n", .{std.unicode.fmtUtf8(str)});
}

yes The program is stuck in a loop

#

I added break
The program did not stop in the loop anymore, it completely crashed

stone fjord
#

as I said, the value you pass into write7BitEncodedInt should not be of type u8, but of type usize.
you want to encode the length of the slice, which is of type usize.

warm pumice
#

pub fn write7BitEncodedInt(self: Self, value: usize) !void {
while (true) {
var b: u8 = @as(u8, @intCast(value)) & @as(u8, @intCast(0x7F));
var value2 = value;
value2 >>= 7;
if (value2 == 0) {
try self.writeByte(b);
break;
} else {
b |= 0x80;
try self.writeByte(b);
break;
}
}
}
The program crashed while reading the string

#

oh u8 problam?

stone fjord
#

you're @intCasting your value into a u8. @intCast makes sure the value is within bounds of the result type, and crashes otherwise. you want to use @truncate, which chops off the high bits of the input - this is equivalent to Java's (byte)num

#

here are my implementations of the read/write functions, try to come up with a solution yourself before looking at this!
||

pub fn write7BitEncodedInt(self: Self, value: usize) !void {
    var num = value;
    while (num > 127) : (num >>= 7) {
        try self.writeByte(@as(u8, @truncate(num)) | 0x80);
    }
    try self.writeByte(@as(u8, @truncate(num)));
}

pub fn read7BitEncodedInt(self: Self) !usize {
    var num: usize = 0;
    var shift: u6 = 0;

    while (true) {
        const read = try self.readByte();
        num |= @as(usize, read & 0x7F) << shift;
        shift += 7;
        if (read <= 127) break;
    }
    return num;
}

||

warm pumice
#

The saw is solved