about summary refs log tree commit diff
path: root/lang/zig/struct-packed.zig
blob: f493661eb73af06b7590d7937ee2d06290090b10 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
const std = @import("std");
const endian = std.builtin.endian;
const expect = std.testing.expect;

const Full = packed struct {
    number: u16,
};
const Divided = packed struct {
    half1: u8,
    quarter3: u4,
    quarter4: u4,
};

fn doTheTest() void {
    expect(@sizeOf(Full) == 2);
    expect(@sizeOf(Divided) == 2);
    var full = Full{ .number = 0x1234 };
    var divided = @bitCast(Divided, full);
    switch (endian) {
        .Big => {
            expect(divided.half1 == 0x12);
            expect(divided.quarter3 == 0x3);
            expect(divided.quarter4 == 0x4);
        },
        .Little => {
            expect(divided.half1 == 0x34);
            expect(divided.quarter3 == 0x2);
            expect(divided.quarter4 == 0x1);
        },
    }
}

test "@bitCast between packed structs" {
    doTheTest();
    comptime doTheTest();
}

const BitField = packed struct {
    a: u3,
    b: u3,
    c: u2,
};

var foo = BitField{
    .a = 1,
    .b = 2,
    .c = 3,
};

fn bar(x: *const u3) u3 {
    return x.*;
}

test "pointer to non-byte-aligned field" {
    const ptr = &foo.b;
    expect(ptr.* == 2);
    // The pointer to a non-byte-aligned field has special properties
    // and cannot be passed when a normal pointer is expected:
    // expect(bar(ptr) == 2);
    // Here's why:
    expect(@ptrToInt(&foo.a) == @ptrToInt(&foo.b));
    expect(@ptrToInt(&foo.a) == @ptrToInt(&foo.c));

    comptime {
        expect(@bitOffsetOf(BitField, "a") == 0);
        expect(@bitOffsetOf(BitField, "b") == 3);
        expect(@bitOffsetOf(BitField, "c") == 6);

        expect(@byteOffsetOf(BitField, "a") == 0);
        expect(@byteOffsetOf(BitField, "b") == 0);
        expect(@byteOffsetOf(BitField, "c") == 0);
    }
}