I started writing a server that has three states and I’m saving them in an enum:
pub fn processInput(
io: std.Io,
gpa: std.mem.Allocator,
conn: std.Io.net.Stream,
data: []u8,
ctx: *Context,
endpoints: *lib.SafeEndpointList,
current_id: *std.atomic.Value(usize),
switcher: *lib.SwitcherState,
) !void {
var msg_buf: [128]u8 = undefined;
var iter = std.mem.tokenizeAny(u8, data, " \r\n\t");
switch (ctx.*) {
.global => try handleGlobal( io, conn, &msg_buf, &iter, ctx, switcher, endpoints, current_id),
.endpoint => try handleEndpoint( io, gpa, &msg_buf, conn, &iter, ctx, switcher, endpoints, current_id),
.switcher => try handleSwitcher( io, &msg_buf, conn, &iter, ctx, switcher, endpoints, current_id),
}
}
And all three handle functions have three command sets available to them:
const GlobalCmd = enum {
const Self = @This();
help,
@"?",
list,
status,
switcher,
endpoint,
exit,
quit,
q,
// Helper to turn the string into this enum
fn from(s: []const u8) ?Self {
return std.meta.stringToEnum(Self, s);
}
};
const EndpointCmd = enum {
const Self = @This();
help,
@"?",
list,
status,
add,
remove,
set,
switcher,
@"return",
ret,
exit,
quit,
q,
// Helper to turn the string into this enum
fn from(s: []const u8) ?Self {
return std.meta.stringToEnum(Self, s);
}
};
const SwitcherCmd = enum {
const Self = @This();
help,
@"?",
status,
play,
pause,
kill,
timer,
endpoint,
@"return",
ret,
exit,
quit,
q,
// Helper to turn the string into this enum
fn from(s: []const u8) ?Self {
return std.meta.stringToEnum(Self, s);
}
};
Is there a way to combine them to remove duplication of the same enums or a better way to approach this? Currently each of my functions is processing input like this:
fn handleGlobal(
io: std.Io,
conn: std.Io.net.Stream,
msg_buf: []u8,
iter: *std.mem.TokenIterator(u8, .any),
ctx: *Context,
switcher: *lib.SwitcherState,
endpoints: *lib.SafeEndpointList,
current_id: *std.atomic.Value(usize),
) !void {
const help_msg =
\\Available Global Commands:
\\ help (?) - Show this message
\\ list - List all available endpoints
\\ status - Show switcher status and current server info
\\ switcher - Interactively manage switcher
\\ endpoint - Interactively manage endpoint
\\ exit - Close the admin connection
\\
;
const raw_cmd = iter.next() orelse {
printPrompt(io, conn, ctx.*);
return;
};
// Use your GlobalCmd enum helper
const cmd = GlobalCmd.from(raw_cmd) orelse {
reply(io, conn, "Unknown command!\n");
printPrompt(io, conn, ctx.*);
return;
};
switch (cmd) {
.exit, .quit, .q => return error.Exit,
.help, .@"?" => reply(io, conn, help_msg),
.list => try listEndpoints(io, conn, msg_buf, endpoints),
.status => try showStatus( io, conn, msg_buf, switcher, endpoints, current_id),
.switcher => ctx.* = .switcher,
.endpoint => ctx.* = .endpoint,
}
// After every successful command:
printPrompt(io, conn, ctx.*);
}