summaryrefslogtreecommitdiff
path: root/src/main.zig
blob: 2b983e115ded67ca7817225189d174b36dc05c90 (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
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
const std = @import("std");
const zits = @import("zits");
const clap = @import("clap");

const SubCommands = enum {
    help,
    serve,
    @"pub",
};

const main_parsers = .{
    .command = clap.parsers.enumeration(SubCommands),
};

// The parameters for `main`. Parameters for the subcommands are specified further down.
const main_params = clap.parseParamsComptime(
    \\-h, --help  Display this help and exit.
    \\<command>
    \\
);

// To pass around arguments returned by clap, `clap.Result` and `clap.ResultEx` can be used to
// get the return type of `clap.parse` and `clap.parseEx`.
const MainArgs = clap.ResultEx(clap.Help, &main_params, main_parsers);

pub fn main() !void {
    var dba = std.heap.DebugAllocator(.{}){};
    defer _ = dba.deinit();
    const gpa = dba.allocator();

    var iter = try std.process.ArgIterator.initWithAllocator(gpa);
    defer iter.deinit();

    _ = iter.next();

    var diag = clap.Diagnostic{};
    var res = clap.parseEx(clap.Help, &main_params, main_parsers, &iter, .{
        .diagnostic = &diag,
        .allocator = gpa,

        // Terminate the parsing of arguments after parsing the first positional (0 is passed
        // here because parsed positionals are, like slices and arrays, indexed starting at 0).
        //
        // This will terminate the parsing after parsing the subcommand enum and leave `iter`
        // not fully consumed. It can then be reused to parse the arguments for subcommands.
        .terminating_positional = 0,
    }) catch |err| {
        try diag.reportToFile(.stderr(), err);
        return err;
    };
    defer res.deinit();

    if (res.args.help != 0)
        return clap.helpToFile(.stderr(), clap.Help, &main_params, .{});

    const command = res.positionals[0] orelse return error.MissingCommand;
    switch (command) {
        .help => return clap.helpToFile(.stderr(), clap.Help, &main_params, .{}),
        .serve => try serverMain(gpa, &iter, res),
        .@"pub" => unreachable,
    }
}

const ServerInfo = struct {
    /// The unique identifier of the NATS server.
    server_id: []const u8,
    /// The name of the NATS server.
    server_name: []const u8,
    /// The version of NATS.
    version: []const u8,
    /// The version of golang the NATS server was built with.
    go: []const u8 = "0.0.0",
    /// The IP address used to start the NATS server,
    /// by default this will be 0.0.0.0 and can be
    /// configured with -client_advertise host:port.
    host: []const u8 = "0.0.0.0",
    /// The port number the NATS server is configured
    /// to listen on.
    port: u16 = 6868,
    /// Whether the server supports headers.
    headers: bool = false,
    /// Maximum payload size, in bytes, that the server
    /// will accept from the client.
    max_payload: u64,
    /// An integer indicating the protocol version of
    /// the server. The server version 1.2.0 sets this
    /// to 1 to indicate that it supports the "Echo"
    /// feature.
    proto: u32 = 1,
};

fn serverMain(gpa: std.mem.Allocator, iter: *std.process.ArgIterator, main_args: MainArgs) !void {
    _ = gpa;
    _ = iter;
    _ = main_args;

    const info: ServerInfo = .{
        .server_id = "foo",
        .server_name = "bar",
        .version = "6.9.0",
        .max_payload = 6969,
    };

    var out_fs = std.fs.File.stderr().writer(&.{});
    const out = &out_fs.interface;

    try std.json.Stringify.value(info, .{
        .whitespace = .indent_2,
    }, out);

    std.debug.print("in serverMain\n", .{});
}