summaryrefslogtreecommitdiff
path: root/exercises/115_packed2.zig
diff options
context:
space:
mode:
Diffstat (limited to 'exercises/115_packed2.zig')
-rw-r--r--exercises/115_packed2.zig78
1 files changed, 78 insertions, 0 deletions
diff --git a/exercises/115_packed2.zig b/exercises/115_packed2.zig
new file mode 100644
index 0000000..2b6b558
--- /dev/null
+++ b/exercises/115_packed2.zig
@@ -0,0 +1,78 @@
+//
+// We've already learned about switch statements in exercises 030, 031 and 108.
+// They also work with packed containers:
+
+const S = packed struct(u2) {
+ a: bool,
+ b: i1,
+};
+
+// Try to make it compile without adding an `else` prong!
+
+comptime {
+ const s: S = .{ .a = true, .b = -1 };
+ switch (s) {
+ .{ .a = true, .b = -1 } => {}, // ok!
+ .{ .a = true, .b = ??? },
+ .{ .a = ???, .b = 0 },
+ .{ .a = ???, .b = ??? },
+ => @compileError("We don't want to end up here!"),
+ }
+}
+
+// As we can see, switching on packed structs is pretty straightforward.
+// When switching on packed unions however, we'll realize that a packed
+// union never keeps track of its active tag, not even in debug mode! This
+// means that packed unions compare solely by their bit pattern (again, just
+// like integers).
+
+const U = packed union(u2) {
+ a: u2,
+ b: i2,
+};
+
+// Find and remove the duplicate case!
+
+comptime {
+ const u: U = .{ .a = 3 };
+ switch (u) {
+ .{ .a = 3 } => {}, // ok!
+ .{ .a = 2 },
+ .{ .b = 1 },
+ .{ .b = -1 },
+ .{ .a = 0 },
+ => @compileError("We don't want to end up here!"),
+ }
+}
+
+// Since packed unions don't have the concept of an active tag, it's always legal
+// to access any of their fields. This can be useful to view the same data from
+// different perspectives seamlessly.
+//
+// Try to make the float below negative:
+
+/// IEEE 754 half precision float
+const Float = packed union(u16) {
+ value: f16,
+ bits: packed struct(u16) {
+ mantissa: u10,
+ exponent: u5,
+ sign: u1,
+ },
+};
+
+pub fn main() void {
+ // Reminder: if the sign bit of a float is set, the number is negative!
+
+ var number: Float = .{ .value = 2.34 };
+ number.bits.??? = ???;
+ if (number.value != -2.34) {
+ std.debug.print("Make it negative!\n", .{});
+ }
+}
+
+// This concludes our introduction to packed containers. The next time you need
+// control over individual bits, keep them in mind as a potent alternative!
+//
+
+const std = @import("std");