Zig 0.17.0-dev (Split by item)

Shortcut keys
?
Show these tips
S
Focus search field
Esc
Clear focus & close tips
U
Jump to source code
↑
Move up in search results
↓
Move down in search results
↵
Go to active search result
This is an example of documentation generated by ZigDoc, an alternative to Zig's built-in Auto Doc feature. See also examples in other modes/formats. The project being documented here (as the example) is the Zig standard library. Public Struct

Preopens

Public Struct

Fields

map: Map

Namespaces

Types

Values

Functions

pub fn get(p: *const Preopens, name: []const u8) ?Resource
pub fn init(arena: Allocator) InitError!Preopens

File

process/Preopens.zig
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
78
79
const Preopens = @This();

const builtin = @import("builtin");
const native_os = builtin.os.tag;

const std = @import("../std.zig");
const Io = std.Io;
const Allocator = std.mem.Allocator;

map: Map,

pub const empty: Preopens = switch (native_os) {
    .wasi => .{ .map = .empty },
    else => .{ .map = {} },
};

pub const Map = switch (native_os) {
    // Indexed by file descriptor number.
    .wasi => std.array_hash_map.String(void),
    else => void,
};

pub const Resource = union(enum) {
    file: Io.File,
    dir: Io.Dir,
};

pub fn get(p: *const Preopens, name: []const u8) ?Resource {
    switch (native_os) {
        .wasi => {
            const index = p.map.getIndex(name) orelse return null;
            if (index <= 2) return .{ .file = .{
                .handle = @intCast(index),
                .flags = .{ .nonblocking = false },
            } };
            return .{ .dir = .{ .handle = @intCast(index) } };
        },
        else => {
            if (std.mem.eql(u8, name, "stdin")) return .{ .file = .stdin() };
            if (std.mem.eql(u8, name, "stdout")) return .{ .file = .stdout() };
            if (std.mem.eql(u8, name, "stderr")) return .{ .file = .stderr() };
            return null;
        },
    }
}

pub const InitError = Allocator.Error || error{Unexpected};

pub fn init(arena: Allocator) InitError!Preopens {
    if (native_os != .wasi) return .{ .map = {} };
    const wasi = std.os.wasi;
    var map: Map = .empty;

    try map.ensureUnusedCapacity(arena, 3);

    map.putAssumeCapacityNoClobber("stdin", {}); // 0
    map.putAssumeCapacityNoClobber("stdout", {}); // 1
    map.putAssumeCapacityNoClobber("stderr", {}); // 2
    while (true) {
        const fd: wasi.fd_t = @intCast(map.entries.len);
        var prestat: wasi.prestat_t = undefined;
        switch (wasi.fd_prestat_get(fd, &prestat)) {
            .SUCCESS => {},
            .OPNOTSUPP, .BADF => return .{ .map = map },
            else => return error.Unexpected,
        }
        try map.ensureUnusedCapacity(arena, 1);
        // This length does not include a null byte. Let's keep it this way to
        // gently encourage WASI implementations to behave properly.
        const name_len = prestat.u.dir.pr_name_len;
        const name = try arena.alloc(u8, name_len);
        switch (wasi.fd_prestat_dir_name(fd, name.ptr, name.len)) {
            .SUCCESS => {},
            else => return error.Unexpected,
        }
        map.putAssumeCapacityNoClobber(name, {});
    }
}