test:zig
This commit is contained in:
78
guide/language/sentinel-termination.zig
Normal file
78
guide/language/sentinel-termination.zig
Normal file
@@ -0,0 +1,78 @@
|
||||
const expect = @import("std").testing.expect;
|
||||
|
||||
// Arrays, slices and many pointers may be terminated by a value of their child type.
|
||||
// This is known as sentinel termination. These follow the syntax `[N:t]T`, `[:t]T`, and `[*:t]T`,
|
||||
// where `t` is a value of the child type `T`.
|
||||
|
||||
// An example of a sentinel terminated array. The built-in `@ptrCast` is used to perform an unsafe type conversion.
|
||||
// This shows us that the last element of the array is followed by a 0 byte.
|
||||
test "sentinel termination" {
|
||||
const terminated = [3:0]u8{ 3, 2, 1 };
|
||||
try expect(terminated.len == 3);
|
||||
try expect(@as(*const [4]u8, @ptrCast(&terminated))[3] == 0);
|
||||
}
|
||||
|
||||
// The types of string literals is `*const [N:0]u8`, where N is the length of the string.
|
||||
// This allows string literals to coerce to sentinel terminated slices, and sentinel terminated many pointers.
|
||||
// Note: string literals are UTF-8 encoded.
|
||||
test "string literal" {
|
||||
try expect(@TypeOf("hello") == *const [5:0]u8);
|
||||
}
|
||||
|
||||
// `[*:0]u8` and `[*:0]const u8` perfectly model C's strings.
|
||||
const eql = @import("std").mem.eql;
|
||||
test "C string" {
|
||||
const c_string: [*:0]const u8 = "hello";
|
||||
var array: [5]u8 = undefined;
|
||||
|
||||
var i: usize = 0;
|
||||
while (c_string[i] != 0) : (i += 1) {
|
||||
array[i] = c_string[i];
|
||||
}
|
||||
|
||||
// XXX: Maybe we should use `c_string[0..i]` instead of `c_string[0..5]`?
|
||||
// try expect(eql(u8, &array, c_string[0..i]));
|
||||
}
|
||||
|
||||
// Sentinel terminated types coerce to their non-sentinel-terminated counterparts.
|
||||
test "coercion" {
|
||||
const a: [*:0]u8 = undefined;
|
||||
const b: [*]u8 = a;
|
||||
|
||||
const c: [5:0]u8 = undefined;
|
||||
const d: [5]u8 = c;
|
||||
|
||||
const e: [:0]f32 = undefined;
|
||||
const f: []f32 = e;
|
||||
|
||||
_ = .{ b, d, f }; //ignore unused
|
||||
}
|
||||
|
||||
// Sentinel terminated slicing is provided
|
||||
// which can be used to create a sentinel terminated slice with the syntax `x[n..m:t]`,
|
||||
// where `t` is the terminator value.
|
||||
// Doing this is an assertion from the programmer that the memory is terminated where it should be
|
||||
// - getting this wrong is detectable illegal behaviour.
|
||||
test "sentinel terminated slicing" {
|
||||
var x = [_:0]u8{255} ** 3;
|
||||
const y = x[0..3 :0];
|
||||
_ = y;
|
||||
}
|
||||
|
||||
// My tests here to understand the concept better
|
||||
const print = @import("std").debug.print;
|
||||
test "sentianel checking" {
|
||||
const x = [_:0]u8{ 'h', 'i', @as(u8, 0), 'w', 'o', 'r', 'l', 'd', @as(u8, 0) };
|
||||
// To validate the memory is terminated where it should be, we can use the `x[n..m:t]` syntax,
|
||||
const y = x[0..2 :@as(u8, 0)];
|
||||
|
||||
// print("\n", .{});
|
||||
// print("x: {any}\n", .{x});
|
||||
// print("y: {any}\n", .{y});
|
||||
|
||||
try expect(x[2] == 0);
|
||||
try expect(y.len == 2);
|
||||
try expect(y[0] == 'h');
|
||||
try expect(y[1] == 'i');
|
||||
try expect(y[2] == 0);
|
||||
}
|
||||
Reference in New Issue
Block a user