summaryrefslogtreecommitdiff
path: root/src/main.zig
blob: a413fbab527b3b4ec4bb01f9eb3dc64e7d941bef (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
const std = @import("std");
const builtin = @import("builtin");
const zits = @import("zits");
const yazap = @import("yazap");

const Message = zits.MessageParser.Message;
const Server = zits.Server;

const serverSubcommand = @import("./subcommand/server.zig").main;

pub fn main() !void {
    var dba: std.heap.DebugAllocator(.{}) = .init;
    defer _ = dba.deinit();
    const gpa = if (builtin.mode == .Debug or builtin.mode == .ReleaseSafe) dba.allocator() else std.heap.smp_allocator;

    var app = yazap.App.init(gpa, "zits", "High performance NATS compatible client and server.");
    defer app.deinit();

    var zits_app = app.rootCommand();

    var server_cmd = app.createCommand("serve", "Run a high performance NATS compatible server.");
    try server_cmd.addArgs(&[_]yazap.Arg{
        yazap.Arg.singleValueOption(
            "addr",
            'a',
            std.fmt.comptimePrint(
                "Address to bind to (default: {s})",
                .{std.meta.fieldInfo(zits.Server.Message.ServerInfo, .host).defaultValue().?},
            ),
        ),
        yazap.Arg.singleValueOption(
            "port",
            'p',
            std.fmt.comptimePrint(
                "Port to listen on (default: {d})",
                .{std.meta.fieldInfo(zits.Server.Message.ServerInfo, .port).defaultValue().?},
            ),
        ),
        yazap.Arg.singleValueOption(
            "name",
            'n',
            "Server name (default: auto)",
        ),
    });
    try zits_app.addSubcommand(server_cmd);

    const pub_cmd = app.createCommand("pub", "Publish a message.");
    try zits_app.addSubcommand(pub_cmd);

    var io_impl: std.Io.Threaded = .init_single_threaded;
    defer io_impl.deinit();
    const io = io_impl.io();

    const matches = try app.parseProcess(io);

    if (matches.subcommandMatches("serve")) |serve_matches| {
        var info: zits.Server.Message.ServerInfo = .{
            .server_id = zits.Server.default_id,
            .server_name = zits.Server.default_name,
            .version = "zits-master",
            .max_payload = 1048576,
            .headers = true,
        };
        if (serve_matches.getSingleValue("port")) |port| {
            info.port = std.fmt.parseUnsigned(@TypeOf(info.port), port, 10) catch |err| std.process.fatal("Could not parse port ({s}): {}\n", .{ port, err });
        }

        if (serve_matches.getSingleValue("name")) |name| {
            info.server_name = name;
        }

        try serverSubcommand(gpa, info);
        return;
    } else if (matches.subcommandMatches("pub")) |_| {
        std.debug.print("Unimplemented\n", .{});
        return;
    }

    try app.displayHelp(io);
}

pub const std_options: std.Options = .{
    // By default, in safe build modes, the standard library will attach a segfault handler to the program to
    // print a helpful stack trace if a segmentation fault occurs. Here, we can disable this, or even enable
    // it in unsafe build modes.
    .enable_segfault_handler = true,
    // This is the logging function used by `std.log`.
    .logFn = myLogFn,
};

fn myLogFn(
    comptime level: std.log.Level,
    comptime scope: @EnumLiteral(),
    comptime format: []const u8,
    args: anytype,
) void {
    if (scope == .zits) {
        std.log.defaultLog(level, std.log.default_log_scope, format, args);
    } else {
        std.log.defaultLog(level, scope, format, args);
    }
}