#Correct way to parse and cast integers from an Io.Reader

1 messages · Page 1 of 1 (latest)

sudden hedge
#

I'm trying to read some serialized data. The dst variable is a pointer to some integer. Tag is an enum { u64, u32 }. The following code works:

    switch (tag) {
        .u64 => dst.* = @intCast(try self.raw.takeInt(u64, .little)),
        .u32 => dst.* = @intCast(try self.raw.takeInt(u32, .little)),
        else => return error.GarbageData,
    }

However, if dst happens to be u32 and the tag is u64, and the value is too big, this would panic. I would like to return an error in that case. But if I try to use std.math.cast, I get compilation errors because the tag isn't compile time known...

west mulch
#

in Zig, a pointer will be to a specific type, but you've said dst points to an integer without saying exactly what kind of integer it is pointing to. We'd need to see more of your code to understand just what you're trying to do.

sudden hedge
#

The function takes dst: anytype and then switches on the @typeinfo . In this case the prong is .int. I want to handle the case where e.g. dst is 32 bit but src is 64 bit without crashing, but still allow the cast if it fits

wanton pecan
#

Sorry, can you show the code you attempted with std.math.cast?

sudden hedge
#
    switch (tag) {
        .u64 => dst.* = std.math.cast(u64, try self.raw.takeInt(u64, .little)) orelse return error.Cast,
        .u32 => dst.* = @intCast(try self.raw.takeInt(u32, .little)),
        else => return error.GarbageData,
    }
error: expected type 'u32', found 'u64'
                    .u64 => dst.* = std.math.cast(u64, try self.raw.takeInt(u64, .little)) orelse return error.Cast,
                                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~
src/ser.zig:477:92: note: unsigned 32-bit int cannot represent all possible unsigned 64-bit values
#

I guess I could wrap it in yet another @intcast but I feel like I'm doing it wrong 😅

wanton pecan
#

Perhaps I'm not undertanding you correctly. But shouldn't that be std.math.cast(u32, try self.raw.takeInt(u64, .little)?

#

Or, actually, now that I think about it, shouldn't the cast be to the dst type, not always one or the other?

#

.u64 => dst.* = std.math.cast(u64, try self.raw.takeInt(u64, .little)) orelse return error.Cast
As in, this is failing because dst is a pointer to a u32, yes?

sudden hedge
#

Oh crap I swapped them, you're right

#

Yeah now it works