zig

fork of https://codeberg.org/ziglang/zig
Log | Files | Refs | README | LICENSE

test_structs.zig (3075B) - Raw


      1 // Declare a struct.
      2 // Zig gives no guarantees about the order of fields and the size of
      3 // the struct but the fields are guaranteed to be ABI-aligned.
      4 const Point = struct {
      5     x: f32,
      6     y: f32,
      7 };
      8 
      9 // Declare an instance of a struct.
     10 const p: Point = .{
     11     .x = 0.12,
     12     .y = 0.34,
     13 };
     14 
     15 // Functions in the struct's namespace can be called with dot syntax.
     16 const Vec3 = struct {
     17     x: f32,
     18     y: f32,
     19     z: f32,
     20 
     21     pub fn init(x: f32, y: f32, z: f32) Vec3 {
     22         return Vec3{
     23             .x = x,
     24             .y = y,
     25             .z = z,
     26         };
     27     }
     28 
     29     pub fn dot(self: Vec3, other: Vec3) f32 {
     30         return self.x * other.x + self.y * other.y + self.z * other.z;
     31     }
     32 };
     33 
     34 test "dot product" {
     35     const v1 = Vec3.init(1.0, 0.0, 0.0);
     36     const v2 = Vec3.init(0.0, 1.0, 0.0);
     37     try expect(v1.dot(v2) == 0.0);
     38 
     39     // Other than being available to call with dot syntax, struct methods are
     40     // not special. You can reference them as any other declaration inside
     41     // the struct:
     42     try expect(Vec3.dot(v1, v2) == 0.0);
     43 }
     44 
     45 // Structs can have declarations.
     46 // Structs can have 0 fields.
     47 const Empty = struct {
     48     pub const PI = 3.14;
     49 };
     50 test "struct namespaced variable" {
     51     try expect(Empty.PI == 3.14);
     52     try expect(@sizeOf(Empty) == 0);
     53 
     54     // Empty structs can be instantiated the same as usual.
     55     const does_nothing: Empty = .{};
     56 
     57     _ = does_nothing;
     58 }
     59 
     60 // Struct field order is determined by the compiler, however, a base pointer
     61 // can be computed from a field pointer:
     62 fn setYBasedOnX(x: *f32, y: f32) void {
     63     const point: *Point = @fieldParentPtr("x", x);
     64     point.y = y;
     65 }
     66 test "field parent pointer" {
     67     var point = Point{
     68         .x = 0.1234,
     69         .y = 0.5678,
     70     };
     71     setYBasedOnX(&point.x, 0.9);
     72     try expect(point.y == 0.9);
     73 }
     74 
     75 // Structs can be returned from functions.
     76 fn LinkedList(comptime T: type) type {
     77     return struct {
     78         pub const Node = struct {
     79             prev: ?*Node,
     80             next: ?*Node,
     81             data: T,
     82         };
     83 
     84         first: ?*Node,
     85         last: ?*Node,
     86         len: usize,
     87     };
     88 }
     89 
     90 test "linked list" {
     91     // Functions called at compile-time are memoized.
     92     try expect(LinkedList(i32) == LinkedList(i32));
     93 
     94     const list = LinkedList(i32){
     95         .first = null,
     96         .last = null,
     97         .len = 0,
     98     };
     99     try expect(list.len == 0);
    100 
    101     // Since types are first class values you can instantiate the type
    102     // by assigning it to a variable:
    103     const ListOfInts = LinkedList(i32);
    104     try expect(ListOfInts == LinkedList(i32));
    105 
    106     var node = ListOfInts.Node{
    107         .prev = null,
    108         .next = null,
    109         .data = 1234,
    110     };
    111     const list2 = LinkedList(i32){
    112         .first = &node,
    113         .last = &node,
    114         .len = 1,
    115     };
    116 
    117     // When using a pointer to a struct, fields can be accessed directly,
    118     // without explicitly dereferencing the pointer.
    119     // So you can do
    120     try expect(list2.first.?.data == 1234);
    121     // instead of try expect(list2.first.?.*.data == 1234);
    122 }
    123 
    124 const expect = @import("std").testing.expect;
    125 
    126 // test