Zig POSIX HTTP JSON fetch with deadline

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

fn getJson(alloc: std.mem.Allocator, host: []const u8, path: []const u8, timeout_ms: u64) !std.json.Parsed(std.json.Value) {
    const stream = try std.net.tcpConnectToHost(alloc, host, 80);
    defer stream.close();
    try stream.writer().print("GET {s} HTTP/1.0\r\nHost: {s}\r\nAccept: application/json\r\n\r\n", .{ path, host });
    var timer = try std.time.Timer.start();
    var fds = [_]std.posix.pollfd{.{ .fd = stream.handle, .events = std.posix.POLL.IN, .revents = 0 }};
    var raw = std.ArrayList(u8).init(alloc); defer raw.deinit();
    while (true) {
        const left = timeout_ms -| (timer.read() / std.time.ns_per_ms);
        if (left == 0) return error.Timeout;
        if (try std.posix.poll(&fds, @intCast(left)) == 0) return error.Timeout;
        var buf: [4096]u8 = undefined;
        const n = try stream.read(&buf);
        if (n == 0) break;
        try raw.appendSlice(buf[0..n]);
    }
    if (!std.mem.startsWith(u8, raw.items, "HTTP/1.0 200") and !std.mem.startsWith(u8, raw.items, "HTTP/1.1 200")) return error.HttpStatus;
    const body = raw.items[std.mem.indexOf(u8, raw.items, "\r\n\r\n").? + 4 ..];
    return std.json.parseFromSlice(std.json.Value, alloc, body, .{ .allocate = .alloc_always });
}