about summary refs log tree commit diff
path: root/lang/zig/slices.zig
blob: 8356c2641d0d34e7d72e2a03b5654ff12017ca58 (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
74
75
76
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);
}