2018-10-26 19:59:58 +01:00
|
|
|
const std = @import("std");
|
2019-02-21 03:40:41 +00:00
|
|
|
const builtin = @import("builtin");
|
2019-02-08 23:18:47 +00:00
|
|
|
const expect = std.testing.expect;
|
2020-04-23 17:44:16 +01:00
|
|
|
const expectEqual = std.testing.expectEqual;
|
2018-10-26 19:59:58 +01:00
|
|
|
const maxInt = std.math.maxInt;
|
2021-04-29 23:18:40 +01:00
|
|
|
const native_endian = builtin.target.cpu.arch.endian();
|
2017-06-08 03:56:57 +01:00
|
|
|
|
|
|
|
test "@bitCast i32 -> u32" {
|
2021-05-04 19:23:22 +01:00
|
|
|
try testBitCast_i32_u32();
|
|
|
|
comptime try testBitCast_i32_u32();
|
2017-06-08 03:56:57 +01:00
|
|
|
}
|
|
|
|
|
2021-05-04 19:23:22 +01:00
|
|
|
fn testBitCast_i32_u32() !void {
|
|
|
|
try expect(conv(-1) == maxInt(u32));
|
|
|
|
try expect(conv2(maxInt(u32)) == -1);
|
2017-06-08 03:56:57 +01:00
|
|
|
}
|
|
|
|
|
2018-05-01 01:35:54 +01:00
|
|
|
fn conv(x: i32) u32 {
|
|
|
|
return @bitCast(u32, x);
|
|
|
|
}
|
|
|
|
fn conv2(x: u32) i32 {
|
|
|
|
return @bitCast(i32, x);
|
|
|
|
}
|
2018-09-18 20:00:14 +01:00
|
|
|
|
2021-06-13 20:27:27 +01:00
|
|
|
test "@bitCast enum to its integer type" {
|
|
|
|
const SOCK = enum(c_int) {
|
2018-09-18 20:00:14 +01:00
|
|
|
A,
|
|
|
|
B,
|
|
|
|
|
2021-05-04 19:23:22 +01:00
|
|
|
fn testBitCastExternEnum() !void {
|
2018-09-18 20:00:14 +01:00
|
|
|
var SOCK_DGRAM = @This().B;
|
|
|
|
var sock_dgram = @bitCast(c_int, SOCK_DGRAM);
|
2021-05-04 19:23:22 +01:00
|
|
|
try expect(sock_dgram == 1);
|
2018-09-18 20:00:14 +01:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2021-05-04 19:23:22 +01:00
|
|
|
try SOCK.testBitCastExternEnum();
|
|
|
|
comptime try SOCK.testBitCastExternEnum();
|
2018-09-18 20:00:14 +01:00
|
|
|
}
|
2019-02-21 03:40:41 +00:00
|
|
|
|
|
|
|
test "@bitCast packed structs at runtime and comptime" {
|
|
|
|
const Full = packed struct {
|
|
|
|
number: u16,
|
|
|
|
};
|
|
|
|
const Divided = packed struct {
|
|
|
|
half1: u8,
|
|
|
|
quarter3: u4,
|
|
|
|
quarter4: u4,
|
|
|
|
};
|
|
|
|
const S = struct {
|
2021-05-04 19:23:22 +01:00
|
|
|
fn doTheTest() !void {
|
2019-02-21 03:40:41 +00:00
|
|
|
var full = Full{ .number = 0x1234 };
|
|
|
|
var two_halves = @bitCast(Divided, full);
|
2021-04-29 23:18:40 +01:00
|
|
|
switch (native_endian) {
|
|
|
|
.Big => {
|
2021-05-04 19:23:22 +01:00
|
|
|
try expect(two_halves.half1 == 0x12);
|
|
|
|
try expect(two_halves.quarter3 == 0x3);
|
|
|
|
try expect(two_halves.quarter4 == 0x4);
|
2019-02-21 03:40:41 +00:00
|
|
|
},
|
2021-04-29 23:18:40 +01:00
|
|
|
.Little => {
|
2021-05-04 19:23:22 +01:00
|
|
|
try expect(two_halves.half1 == 0x34);
|
|
|
|
try expect(two_halves.quarter3 == 0x2);
|
|
|
|
try expect(two_halves.quarter4 == 0x1);
|
2019-02-21 03:40:41 +00:00
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
2021-05-04 19:23:22 +01:00
|
|
|
try S.doTheTest();
|
|
|
|
comptime try S.doTheTest();
|
2019-02-21 03:40:41 +00:00
|
|
|
}
|
2019-02-21 13:46:43 +00:00
|
|
|
|
|
|
|
test "@bitCast extern structs at runtime and comptime" {
|
|
|
|
const Full = extern struct {
|
|
|
|
number: u16,
|
|
|
|
};
|
|
|
|
const TwoHalves = extern struct {
|
|
|
|
half1: u8,
|
|
|
|
half2: u8,
|
|
|
|
};
|
|
|
|
const S = struct {
|
2021-05-04 19:23:22 +01:00
|
|
|
fn doTheTest() !void {
|
2019-02-21 13:46:43 +00:00
|
|
|
var full = Full{ .number = 0x1234 };
|
|
|
|
var two_halves = @bitCast(TwoHalves, full);
|
2021-04-29 23:18:40 +01:00
|
|
|
switch (native_endian) {
|
|
|
|
.Big => {
|
2021-05-04 19:23:22 +01:00
|
|
|
try expect(two_halves.half1 == 0x12);
|
|
|
|
try expect(two_halves.half2 == 0x34);
|
2019-02-21 13:46:43 +00:00
|
|
|
},
|
2021-04-29 23:18:40 +01:00
|
|
|
.Little => {
|
2021-05-04 19:23:22 +01:00
|
|
|
try expect(two_halves.half1 == 0x34);
|
|
|
|
try expect(two_halves.half2 == 0x12);
|
2019-02-21 13:46:43 +00:00
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
2021-05-04 19:23:22 +01:00
|
|
|
try S.doTheTest();
|
|
|
|
comptime try S.doTheTest();
|
2019-02-21 13:46:43 +00:00
|
|
|
}
|
2019-02-22 13:49:27 +00:00
|
|
|
|
2019-06-14 01:24:10 +01:00
|
|
|
test "bitcast packed struct to integer and back" {
|
|
|
|
const LevelUpMove = packed struct {
|
|
|
|
move_id: u9,
|
|
|
|
level: u7,
|
|
|
|
};
|
|
|
|
const S = struct {
|
2021-05-04 19:23:22 +01:00
|
|
|
fn doTheTest() !void {
|
2019-06-14 01:24:10 +01:00
|
|
|
var move = LevelUpMove{ .move_id = 1, .level = 2 };
|
|
|
|
var v = @bitCast(u16, move);
|
|
|
|
var back_to_a_move = @bitCast(LevelUpMove, v);
|
2021-05-04 19:23:22 +01:00
|
|
|
try expect(back_to_a_move.move_id == 1);
|
|
|
|
try expect(back_to_a_move.level == 2);
|
2019-06-14 01:24:10 +01:00
|
|
|
}
|
|
|
|
};
|
2021-05-04 19:23:22 +01:00
|
|
|
try S.doTheTest();
|
|
|
|
comptime try S.doTheTest();
|
2019-06-14 01:24:10 +01:00
|
|
|
}
|
2019-06-21 21:54:46 +01:00
|
|
|
|
|
|
|
test "implicit cast to error union by returning" {
|
|
|
|
const S = struct {
|
2021-05-04 19:23:22 +01:00
|
|
|
fn entry() !void {
|
|
|
|
try expect((func(-1) catch unreachable) == maxInt(u64));
|
2019-06-21 21:54:46 +01:00
|
|
|
}
|
|
|
|
pub fn func(sz: i64) anyerror!u64 {
|
|
|
|
return @bitCast(u64, sz);
|
|
|
|
}
|
|
|
|
};
|
2021-05-04 19:23:22 +01:00
|
|
|
try S.entry();
|
|
|
|
comptime try S.entry();
|
2019-06-21 21:54:46 +01:00
|
|
|
}
|
2019-08-06 17:24:52 +01:00
|
|
|
|
|
|
|
// issue #3010: compiler segfault
|
|
|
|
test "bitcast literal [4]u8 param to u32" {
|
|
|
|
const ip = @bitCast(u32, [_]u8{ 255, 255, 255, 255 });
|
2021-05-04 19:23:22 +01:00
|
|
|
try expect(ip == maxInt(u32));
|
2019-08-06 17:24:52 +01:00
|
|
|
}
|
2019-08-19 22:50:37 +01:00
|
|
|
|
|
|
|
test "bitcast packed struct literal to byte" {
|
|
|
|
const Foo = packed struct {
|
|
|
|
value: u8,
|
|
|
|
};
|
|
|
|
const casted = @bitCast(u8, Foo{ .value = 0xF });
|
2021-05-04 19:23:22 +01:00
|
|
|
try expect(casted == 0xf);
|
2019-08-19 22:50:37 +01:00
|
|
|
}
|
2019-08-24 11:16:46 +01:00
|
|
|
|
|
|
|
test "comptime bitcast used in expression has the correct type" {
|
|
|
|
const Foo = packed struct {
|
|
|
|
value: u8,
|
|
|
|
};
|
2021-05-04 19:23:22 +01:00
|
|
|
try expect(@bitCast(u8, Foo{ .value = 0xF }) == 0xf);
|
2019-08-24 11:16:46 +01:00
|
|
|
}
|
2020-01-02 11:56:46 +00:00
|
|
|
|
|
|
|
test "bitcast result to _" {
|
|
|
|
_ = @bitCast(u8, @as(i8, 1));
|
|
|
|
}
|
2020-01-07 18:58:31 +00:00
|
|
|
|
|
|
|
test "nested bitcast" {
|
|
|
|
const S = struct {
|
2021-05-04 19:23:22 +01:00
|
|
|
fn moo(x: isize) !void {
|
|
|
|
try @import("std").testing.expectEqual(@intCast(isize, 42), x);
|
2020-01-07 18:58:31 +00:00
|
|
|
}
|
|
|
|
|
2021-05-04 19:23:22 +01:00
|
|
|
fn foo(x: isize) !void {
|
|
|
|
try @This().moo(
|
2020-01-07 18:58:31 +00:00
|
|
|
@bitCast(isize, if (x != 0) @bitCast(usize, x) else @bitCast(usize, x)),
|
|
|
|
);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2021-05-04 19:23:22 +01:00
|
|
|
try S.foo(42);
|
|
|
|
comptime try S.foo(42);
|
2020-01-07 18:58:31 +00:00
|
|
|
}
|
2020-01-23 05:46:44 +00:00
|
|
|
|
2020-01-27 22:30:39 +00:00
|
|
|
test "bitcast passed as tuple element" {
|
|
|
|
const S = struct {
|
2021-05-04 19:23:22 +01:00
|
|
|
fn foo(args: anytype) !void {
|
|
|
|
comptime try expect(@TypeOf(args[0]) == f32);
|
|
|
|
try expect(args[0] == 12.34);
|
2020-01-27 22:30:39 +00:00
|
|
|
}
|
|
|
|
};
|
2021-05-04 19:23:22 +01:00
|
|
|
try S.foo(.{@bitCast(f32, @as(u32, 0x414570A4))});
|
2020-01-27 22:30:39 +00:00
|
|
|
}
|
2020-01-27 23:26:39 +00:00
|
|
|
|
|
|
|
test "triple level result location with bitcast sandwich passed as tuple element" {
|
|
|
|
const S = struct {
|
2021-05-04 19:23:22 +01:00
|
|
|
fn foo(args: anytype) !void {
|
|
|
|
comptime try expect(@TypeOf(args[0]) == f64);
|
|
|
|
try expect(args[0] > 12.33 and args[0] < 12.35);
|
2020-01-27 23:26:39 +00:00
|
|
|
}
|
|
|
|
};
|
2021-05-04 19:23:22 +01:00
|
|
|
try S.foo(.{@as(f64, @bitCast(f32, @as(u32, 0x414570A4)))});
|
2020-01-27 23:26:39 +00:00
|
|
|
}
|
2020-04-23 17:44:16 +01:00
|
|
|
|
|
|
|
test "bitcast generates a temporary value" {
|
|
|
|
var y = @as(u16, 0x55AA);
|
|
|
|
const x = @bitCast(u16, @bitCast([2]u8, y));
|
2021-05-04 19:23:22 +01:00
|
|
|
try expectEqual(y, x);
|
2020-04-23 17:44:16 +01:00
|
|
|
}
|