#cast problam
1 messages · Page 1 of 1 (latest)
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;
}
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...
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;
}
this seems correct, does it compile?
no
what's the error message?
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);
}
is it a compilation error or a runtime crash?
runtime crash
thread 3908 panic: attempt to cast negative value to unsigned integer
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?
It is true that you edited them
But now I have the error
you annotated that readByte returns a !i8; I can't be sure without more context, but if you're working with raw bytes you should probably return a !u8; unsigned, not signed
pub fn readByte(self: Self) !i8 {
const integer: []u8 = try self.read(1);
const int: i8 = @bitCast(integer[0]);
return int;
}
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];
}
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;
}
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.
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];
}
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?
In fact, I need its packet to read the text
https://learn.microsoft.com/en-us/dotnet/api/system.io.binarywriter.write7bitencodedint?view=net-8.0
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
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
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?
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
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
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
the problem is still there; try to pass writeStrL a string with length bigger than 255
why?
try it and see what happens, I am pretty sure the program will crash
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

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.
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?
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;
}
||
The saw is solved