2017-01-05 00:57:48 -08:00
|
|
|
const assert = @import("std").debug.assert;
|
|
|
|
|
2016-12-21 21:12:27 -08:00
|
|
|
const StructWithNoFields = struct {
|
|
|
|
fn add(a: i32, b: i32) -> i32 { a + b }
|
|
|
|
};
|
|
|
|
const empty_global_instance = StructWithNoFields {};
|
|
|
|
|
2017-05-23 18:38:31 -07:00
|
|
|
test "call struct static method" {
|
2016-12-21 21:12:27 -08:00
|
|
|
const result = StructWithNoFields.add(3, 4);
|
|
|
|
assert(result == 7);
|
|
|
|
}
|
|
|
|
|
2017-05-23 18:38:31 -07:00
|
|
|
test "return empty struct instance" {
|
2017-03-16 13:02:35 -07:00
|
|
|
_ = returnEmptyStructInstance();
|
|
|
|
}
|
2016-12-21 21:12:27 -08:00
|
|
|
fn returnEmptyStructInstance() -> StructWithNoFields {
|
|
|
|
return empty_global_instance;
|
|
|
|
}
|
|
|
|
|
|
|
|
const should_be_11 = StructWithNoFields.add(5, 6);
|
|
|
|
|
2017-05-23 18:38:31 -07:00
|
|
|
test "invake static method in global scope" {
|
2016-12-21 21:12:27 -08:00
|
|
|
assert(should_be_11 == 11);
|
|
|
|
}
|
|
|
|
|
2017-05-23 18:38:31 -07:00
|
|
|
test "void struct fields" {
|
2016-12-21 21:55:21 -08:00
|
|
|
const foo = VoidStructFieldsFoo {
|
|
|
|
.a = void{},
|
|
|
|
.b = 1,
|
|
|
|
.c = void{},
|
|
|
|
};
|
|
|
|
assert(foo.b == 1);
|
|
|
|
assert(@sizeOf(VoidStructFieldsFoo) == 4);
|
|
|
|
}
|
|
|
|
const VoidStructFieldsFoo = struct {
|
|
|
|
a : void,
|
|
|
|
b : i32,
|
|
|
|
c : void,
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2017-05-23 18:38:31 -07:00
|
|
|
test "structs" {
|
2016-12-21 21:55:21 -08:00
|
|
|
var foo: StructFoo = undefined;
|
2017-04-21 07:39:13 -07:00
|
|
|
@memset(@ptrCast(&u8, &foo), 0, @sizeOf(StructFoo));
|
2016-12-21 21:55:21 -08:00
|
|
|
foo.a += 1;
|
|
|
|
foo.b = foo.a == 1;
|
|
|
|
testFoo(foo);
|
|
|
|
testMutation(&foo);
|
|
|
|
assert(foo.c == 100);
|
|
|
|
}
|
|
|
|
const StructFoo = struct {
|
|
|
|
a : i32,
|
|
|
|
b : bool,
|
|
|
|
c : f32,
|
|
|
|
};
|
2017-03-26 00:39:18 -07:00
|
|
|
fn testFoo(foo: &const StructFoo) {
|
2016-12-21 21:55:21 -08:00
|
|
|
assert(foo.b);
|
|
|
|
}
|
2017-03-26 00:39:18 -07:00
|
|
|
fn testMutation(foo: &StructFoo) {
|
2016-12-21 21:55:21 -08:00
|
|
|
foo.c = 100;
|
|
|
|
}
|
|
|
|
|
2016-12-21 21:12:27 -08:00
|
|
|
|
2016-12-21 22:20:08 -08:00
|
|
|
const Node = struct {
|
|
|
|
val: Val,
|
|
|
|
next: &Node,
|
|
|
|
};
|
|
|
|
|
|
|
|
const Val = struct {
|
|
|
|
x: i32,
|
|
|
|
};
|
|
|
|
|
2017-05-23 18:38:31 -07:00
|
|
|
test "struct point to self" {
|
2016-12-21 22:20:08 -08:00
|
|
|
var root : Node = undefined;
|
|
|
|
root.val.x = 1;
|
|
|
|
|
|
|
|
var node : Node = undefined;
|
|
|
|
node.next = &root;
|
|
|
|
node.val.x = 2;
|
|
|
|
|
|
|
|
root.next = &node;
|
|
|
|
|
|
|
|
assert(node.next.next.next.val.x == 1);
|
|
|
|
}
|
|
|
|
|
2017-05-23 18:38:31 -07:00
|
|
|
test "struct byval assign" {
|
2016-12-21 22:20:08 -08:00
|
|
|
var foo1 : StructFoo = undefined;
|
|
|
|
var foo2 : StructFoo = undefined;
|
|
|
|
|
|
|
|
foo1.a = 1234;
|
|
|
|
foo2.a = 0;
|
|
|
|
assert(foo2.a == 0);
|
|
|
|
foo2 = foo1;
|
|
|
|
assert(foo2.a == 1234);
|
|
|
|
}
|
|
|
|
|
|
|
|
fn structInitializer() {
|
|
|
|
const val = Val { .x = 42 };
|
|
|
|
assert(val.x == 42);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-05-23 18:38:31 -07:00
|
|
|
test "fn call of struct field" {
|
2016-12-21 22:20:08 -08:00
|
|
|
assert(callStructField(Foo {.ptr = aFunc,}) == 13);
|
|
|
|
}
|
|
|
|
|
|
|
|
const Foo = struct {
|
|
|
|
ptr: fn() -> i32,
|
|
|
|
};
|
|
|
|
|
|
|
|
fn aFunc() -> i32 { 13 }
|
|
|
|
|
2017-03-26 00:39:18 -07:00
|
|
|
fn callStructField(foo: &const Foo) -> i32 {
|
2016-12-21 22:20:08 -08:00
|
|
|
return foo.ptr();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-05-23 18:38:31 -07:00
|
|
|
test "store member function in variable" {
|
2016-12-21 22:42:30 -08:00
|
|
|
const instance = MemberFnTestFoo { .x = 1234, };
|
|
|
|
const memberFn = MemberFnTestFoo.member;
|
|
|
|
const result = memberFn(instance);
|
|
|
|
assert(result == 1234);
|
|
|
|
}
|
|
|
|
const MemberFnTestFoo = struct {
|
|
|
|
x: i32,
|
2017-03-26 00:39:18 -07:00
|
|
|
fn member(foo: &const MemberFnTestFoo) -> i32 { foo.x }
|
2016-12-21 22:42:30 -08:00
|
|
|
};
|
|
|
|
|
|
|
|
|
2017-05-23 18:38:31 -07:00
|
|
|
test "call member function directly" {
|
2016-12-21 22:42:30 -08:00
|
|
|
const instance = MemberFnTestFoo { .x = 1234, };
|
|
|
|
const result = MemberFnTestFoo.member(instance);
|
|
|
|
assert(result == 1234);
|
|
|
|
}
|
|
|
|
|
2017-05-23 18:38:31 -07:00
|
|
|
test "member functions" {
|
2016-12-21 22:42:30 -08:00
|
|
|
const r = MemberFnRand {.seed = 1234};
|
|
|
|
assert(r.getSeed() == 1234);
|
|
|
|
}
|
|
|
|
const MemberFnRand = struct {
|
|
|
|
seed: u32,
|
2017-01-05 15:50:36 -08:00
|
|
|
pub fn getSeed(r: &const MemberFnRand) -> u32 {
|
2016-12-21 22:42:30 -08:00
|
|
|
r.seed
|
|
|
|
}
|
|
|
|
};
|
2016-12-21 22:20:08 -08:00
|
|
|
|
2017-05-23 18:38:31 -07:00
|
|
|
test "return struct byval from function" {
|
2016-12-26 00:44:59 -08:00
|
|
|
const bar = makeBar(1234, 5678);
|
|
|
|
assert(bar.y == 5678);
|
|
|
|
}
|
|
|
|
const Bar = struct {
|
|
|
|
x: i32,
|
|
|
|
y: i32,
|
|
|
|
};
|
|
|
|
fn makeBar(x: i32, y: i32) -> Bar {
|
|
|
|
Bar {
|
|
|
|
.x = x,
|
|
|
|
.y = y,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-05-23 18:38:31 -07:00
|
|
|
test "empty struct method call" {
|
2016-12-26 00:44:59 -08:00
|
|
|
const es = EmptyStruct{};
|
|
|
|
assert(es.method() == 1234);
|
|
|
|
}
|
|
|
|
const EmptyStruct = struct {
|
2017-01-05 15:50:36 -08:00
|
|
|
fn method(es: &const EmptyStruct) -> i32 {
|
2016-12-26 00:44:59 -08:00
|
|
|
1234
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2017-05-23 18:38:31 -07:00
|
|
|
test "return empty struct from fn" {
|
2017-02-24 12:00:47 -08:00
|
|
|
_ = testReturnEmptyStructFromFn();
|
2016-12-26 00:44:59 -08:00
|
|
|
}
|
|
|
|
const EmptyStruct2 = struct {};
|
|
|
|
fn testReturnEmptyStructFromFn() -> EmptyStruct2 {
|
|
|
|
EmptyStruct2 {}
|
|
|
|
}
|
|
|
|
|
2017-05-23 18:38:31 -07:00
|
|
|
test "pass slice of empty struct to fn" {
|
2016-12-27 22:15:09 -08:00
|
|
|
assert(testPassSliceOfEmptyStructToFn([]EmptyStruct2{ EmptyStruct2{} }) == 1);
|
|
|
|
}
|
2017-02-12 14:22:35 -08:00
|
|
|
fn testPassSliceOfEmptyStructToFn(slice: []const EmptyStruct2) -> usize {
|
2016-12-27 22:15:09 -08:00
|
|
|
slice.len
|
|
|
|
}
|
2017-02-03 08:39:24 -08:00
|
|
|
|
|
|
|
const APackedStruct = packed struct {
|
|
|
|
x: u8,
|
|
|
|
y: u8,
|
|
|
|
};
|
|
|
|
|
2017-05-23 18:38:31 -07:00
|
|
|
test "packed struct" {
|
2017-02-03 08:39:24 -08:00
|
|
|
var foo = APackedStruct {
|
|
|
|
.x = 1,
|
|
|
|
.y = 2,
|
|
|
|
};
|
|
|
|
foo.y += 1;
|
|
|
|
const four = foo.x + foo.y;
|
|
|
|
assert(four == 4);
|
|
|
|
}
|
2017-02-16 12:45:41 -08:00
|
|
|
|
|
|
|
|
|
|
|
const BitField1 = packed struct {
|
|
|
|
a: u3,
|
|
|
|
b: u3,
|
|
|
|
c: u2,
|
|
|
|
};
|
|
|
|
|
2017-02-16 15:42:52 -08:00
|
|
|
const bit_field_1 = BitField1 {
|
|
|
|
.a = 1,
|
|
|
|
.b = 2,
|
|
|
|
.c = 3,
|
|
|
|
};
|
|
|
|
|
2017-05-23 18:38:31 -07:00
|
|
|
test "bit field access" {
|
2017-02-16 15:42:52 -08:00
|
|
|
var data = bit_field_1;
|
2017-02-16 14:08:55 -08:00
|
|
|
assert(getA(&data) == 1);
|
2017-02-16 12:45:41 -08:00
|
|
|
assert(getB(&data) == 2);
|
|
|
|
assert(getC(&data) == 3);
|
|
|
|
comptime assert(@sizeOf(BitField1) == 1);
|
2017-02-16 15:42:52 -08:00
|
|
|
|
|
|
|
data.b += 1;
|
|
|
|
assert(data.b == 3);
|
|
|
|
|
|
|
|
data.a += 1;
|
|
|
|
assert(data.a == 2);
|
|
|
|
assert(data.b == 3);
|
2017-02-16 12:45:41 -08:00
|
|
|
}
|
|
|
|
|
2017-02-16 14:08:55 -08:00
|
|
|
fn getA(data: &const BitField1) -> u3 {
|
|
|
|
return data.a;
|
|
|
|
}
|
|
|
|
|
2017-02-16 12:45:41 -08:00
|
|
|
fn getB(data: &const BitField1) -> u3 {
|
|
|
|
return data.b;
|
|
|
|
}
|
|
|
|
|
|
|
|
fn getC(data: &const BitField1) -> u2 {
|
|
|
|
return data.c;
|
|
|
|
}
|
2017-02-21 11:22:23 -08:00
|
|
|
|
2017-04-17 21:05:09 -07:00
|
|
|
const u24 = @IntType(false, 24);
|
2017-02-21 11:22:23 -08:00
|
|
|
const Foo24Bits = packed struct {
|
|
|
|
field: u24,
|
|
|
|
};
|
|
|
|
const Foo96Bits = packed struct {
|
|
|
|
a: u24,
|
|
|
|
b: u24,
|
|
|
|
c: u24,
|
|
|
|
d: u24,
|
|
|
|
};
|
|
|
|
|
2017-05-23 18:38:31 -07:00
|
|
|
test "packed struct 24bits" {
|
2017-02-21 21:49:10 -08:00
|
|
|
comptime {
|
|
|
|
assert(@sizeOf(Foo24Bits) == 3);
|
|
|
|
assert(@sizeOf(Foo96Bits) == 12);
|
|
|
|
}
|
2017-02-21 11:22:23 -08:00
|
|
|
|
|
|
|
var value = Foo96Bits {
|
|
|
|
.a = 0,
|
|
|
|
.b = 0,
|
|
|
|
.c = 0,
|
|
|
|
.d = 0,
|
|
|
|
};
|
|
|
|
value.a += 1;
|
|
|
|
assert(value.a == 1);
|
|
|
|
assert(value.b == 0);
|
|
|
|
assert(value.c == 0);
|
|
|
|
assert(value.d == 0);
|
|
|
|
|
|
|
|
value.b += 1;
|
|
|
|
assert(value.a == 1);
|
|
|
|
assert(value.b == 1);
|
|
|
|
assert(value.c == 0);
|
|
|
|
assert(value.d == 0);
|
|
|
|
|
|
|
|
value.c += 1;
|
|
|
|
assert(value.a == 1);
|
|
|
|
assert(value.b == 1);
|
|
|
|
assert(value.c == 1);
|
|
|
|
assert(value.d == 0);
|
|
|
|
|
|
|
|
value.d += 1;
|
|
|
|
assert(value.a == 1);
|
|
|
|
assert(value.b == 1);
|
|
|
|
assert(value.c == 1);
|
|
|
|
assert(value.d == 1);
|
|
|
|
}
|
2017-02-21 21:49:10 -08:00
|
|
|
|
|
|
|
const FooArray24Bits = packed struct {
|
|
|
|
a: u16,
|
|
|
|
b: [2]Foo24Bits,
|
|
|
|
c: u16,
|
|
|
|
};
|
|
|
|
|
2017-05-23 18:38:31 -07:00
|
|
|
test "packed array 24bits" {
|
2017-02-21 21:49:10 -08:00
|
|
|
comptime {
|
|
|
|
assert(@sizeOf([9]Foo24Bits) == 9 * 3);
|
|
|
|
assert(@sizeOf(FooArray24Bits) == 2 + 2 * 3 + 2);
|
|
|
|
}
|
|
|
|
|
|
|
|
var bytes = []u8{0} ** (@sizeOf(FooArray24Bits) + 1);
|
|
|
|
bytes[bytes.len - 1] = 0xaa;
|
2017-05-19 07:39:59 -07:00
|
|
|
const ptr = &([]FooArray24Bits)(bytes[0..bytes.len - 1])[0];
|
2017-02-21 21:49:10 -08:00
|
|
|
assert(ptr.a == 0);
|
|
|
|
assert(ptr.b[0].field == 0);
|
|
|
|
assert(ptr.b[1].field == 0);
|
|
|
|
assert(ptr.c == 0);
|
|
|
|
|
|
|
|
ptr.a = @maxValue(u16);
|
|
|
|
assert(ptr.a == @maxValue(u16));
|
|
|
|
assert(ptr.b[0].field == 0);
|
|
|
|
assert(ptr.b[1].field == 0);
|
|
|
|
assert(ptr.c == 0);
|
|
|
|
|
|
|
|
ptr.b[0].field = @maxValue(u24);
|
|
|
|
assert(ptr.a == @maxValue(u16));
|
|
|
|
assert(ptr.b[0].field == @maxValue(u24));
|
|
|
|
assert(ptr.b[1].field == 0);
|
|
|
|
assert(ptr.c == 0);
|
|
|
|
|
|
|
|
ptr.b[1].field = @maxValue(u24);
|
|
|
|
assert(ptr.a == @maxValue(u16));
|
|
|
|
assert(ptr.b[0].field == @maxValue(u24));
|
|
|
|
assert(ptr.b[1].field == @maxValue(u24));
|
|
|
|
assert(ptr.c == 0);
|
|
|
|
|
|
|
|
ptr.c = @maxValue(u16);
|
|
|
|
assert(ptr.a == @maxValue(u16));
|
|
|
|
assert(ptr.b[0].field == @maxValue(u24));
|
|
|
|
assert(ptr.b[1].field == @maxValue(u24));
|
|
|
|
assert(ptr.c == @maxValue(u16));
|
|
|
|
|
|
|
|
assert(bytes[bytes.len - 1] == 0xaa);
|
|
|
|
}
|
2017-02-21 21:54:11 -08:00
|
|
|
|
|
|
|
const FooStructAligned = packed struct {
|
|
|
|
a: u8,
|
|
|
|
b: u8,
|
|
|
|
};
|
|
|
|
|
|
|
|
const FooArrayOfAligned = packed struct {
|
|
|
|
a: [2]FooStructAligned,
|
|
|
|
};
|
|
|
|
|
2017-05-23 18:38:31 -07:00
|
|
|
test "aligned array of packed struct" {
|
2017-02-21 21:54:11 -08:00
|
|
|
comptime {
|
|
|
|
assert(@sizeOf(FooStructAligned) == 2);
|
|
|
|
assert(@sizeOf(FooArrayOfAligned) == 2 * 2);
|
|
|
|
}
|
|
|
|
|
|
|
|
var bytes = []u8{0xbb} ** @sizeOf(FooArrayOfAligned);
|
2017-05-19 07:39:59 -07:00
|
|
|
const ptr = &([]FooArrayOfAligned)(bytes[0..bytes.len])[0];
|
2017-02-21 21:54:11 -08:00
|
|
|
|
|
|
|
assert(ptr.a[0].a == 0xbb);
|
|
|
|
assert(ptr.a[0].b == 0xbb);
|
|
|
|
assert(ptr.a[1].a == 0xbb);
|
|
|
|
assert(ptr.a[1].b == 0xbb);
|
|
|
|
}
|
2017-04-06 12:04:18 -07:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
test "runtime struct initialization of bitfield" {
|
|
|
|
const s1 = Nibbles { .x = x1, .y = x1 };
|
|
|
|
const s2 = Nibbles { .x = u4(x2), .y = u4(x2) };
|
|
|
|
|
|
|
|
assert(s1.x == x1);
|
|
|
|
assert(s1.y == x1);
|
|
|
|
assert(s2.x == u4(x2));
|
|
|
|
assert(s2.y == u4(x2));
|
|
|
|
}
|
|
|
|
|
|
|
|
var x1 = u4(1);
|
|
|
|
var x2 = u8(2);
|
|
|
|
|
|
|
|
const Nibbles = packed struct {
|
|
|
|
x: u4,
|
|
|
|
y: u4,
|
|
|
|
};
|