about summary refs log tree commit diff
path: root/lang/zig/slices.zig
diff options
context:
space:
mode:
Diffstat (limited to 'lang/zig/slices.zig')
-rw-r--r--lang/zig/slices.zig77
1 files changed, 77 insertions, 0 deletions
diff --git a/lang/zig/slices.zig b/lang/zig/slices.zig
new file mode 100644
index 0000000..8356c26
--- /dev/null
+++ b/lang/zig/slices.zig
@@ -0,0 +1,77 @@
+const bufPrint = std.fmt.bufPrint;
+const eql = std.mem.eql;
+const expect = std.testing.expect;
+const std = @import("std");
+
+test "basic slices" {
+    var array = [_]i32{ 1, 2, 3, 4 };
+    // A slice is a pointer and a length. The difference between an array and
+    // a slice is that the array's length is part of the type and known at
+    // compile-time, whereas the slice's length is known at runtime.
+    // Both can be accessed with the `len` field.
+    var known_at_runtime_zero: usize = 0;
+    const slice = array[known_at_runtime_zero..array.len];
+    expect(&slice[0] == &array[0]);
+    expect(slice.len == array.len);
+
+    // Using the address-of operator on a slice gives a pointer to a single
+    // item, while using the `ptr` field gives an unknown length pointer.
+    expect(@TypeOf(slice.ptr) == [*]i32);
+    expect(@TypeOf(&slice[0]) == *i32);
+    expect(@ptrToInt(slice.ptr) == @ptrToInt(&slice[0]));
+
+    // Slices have array bounds checking. If you try to access something out
+    // of bounds, you'll get a safety check failure:
+    // slice[10] += 1;
+
+    // Note that `slice.ptr` does not invoke safety checking, while `&slice[0]`
+    // asserts that the slice has len >= 1.
+}
+
+test "using slices for strings" {
+    // Zig has no concept of strings. String literals are const pointers to
+    // arrays of u8, and by convention parameters that are "strings" are
+    // expected to be UTF-8 encoded slices of u8.
+    // Here we coerce [5]u8 to []const u8
+    const hello: []const u8 = "hello";
+    const world: []const u8 = "世界";
+
+    var all_together: [100]u8 = undefined;
+    // String concatenation example.
+    const hello_world = try bufPrint(
+        all_together[0..], "{} {}", .{ hello, world });
+
+    // Generally, you can use UTF-8 and not worry about whether something is a
+    // string. If you don't need to deal with individual characters, no need
+    // to decode.
+    expect(eql(u8, hello_world, "hello 世界"));
+}
+
+test "slice pointer" {
+    var array: [10]u8 = undefined;
+    const ptr = &array;
+
+    // You can use slicing syntax to convert a pointer into a slice:
+    const slice = ptr[0..5];
+    slice[2] = 3;
+    expect(slice[2] == 3);
+    // The slice is mutable because we sliced a mutable pointer.
+    // Furthermore, it is actually a pointer to an array, since the start
+    // and end indexes were both comptime-known.
+    expect(@TypeOf(slice) == *[5]u8);
+
+    // You can also slice a slice:
+    const slice2 = slice[2..3];
+    expect(slice2.len == 1);
+    expect(slice2[0] == 3);
+}
+
+test "null terminated slice" {
+    const string = "hello";
+    const slice: [:0]const u8 = string;
+    expect(@TypeOf(string) == *const [5:0]u8);
+    expect(@TypeOf(slice) == [:0]const u8);
+
+    expect(slice.len == 5);
+    expect(slice[5] == 0);
+}