Zig env config with defaults and checks

Zig
const std = @import("std");

const Config = struct { port: u16, host: []const u8, debug: bool };

fn envOr(a: std.mem.Allocator, key: []const u8, fallback: []const u8) ![]const u8 {
    return std.process.getEnvVarOwned(a, key) catch |err| switch (err) {
        error.EnvironmentVariableNotFound => fallback,
        else => return err,
    };
}

fn loadConfig(a: std.mem.Allocator) !Config {
    const port_text = try envOr(a, "PORT", "8080");
    const port = std.fmt.parseInt(u16, port_text, 10) catch return error.InvalidPort;
    const host = try envOr(a, "HOST", "127.0.0.1");
    if (host.len == 0) return error.InvalidHost;
    const debug = std.mem.eql(u8, try envOr(a, "DEBUG", "0"), "1");
    return .{ .port = port, .host = host, .debug = debug };
}