const std = @import("std"); const Config = struct { url: []const u8 = "https://codeforces.com", }; const Client = struct { alloc: std.mem.Allocator, arena: std.heap.ArenaAllocator, config: Config, client: std.http.Client, fn init(alloc: std.mem.Allocator, config: Config) Client { return .{ .alloc = alloc, .arena = std.heap.ArenaAllocator.init(alloc), .config = config, .client = .{ .allocator = alloc }, }; } fn deinit(self: *Client) void { self.client.deinit(); self.arena.deinit(); } fn reflectParse(value: anytype) []const u8 { return switch (@typeInfo(@TypeOf(value))) { .Pointer => value, .Optional => if (value) |v| reflectParse(v) else null, .Bool => if (value) "true" else "false", else => @compileError("unknown type"), }; } fn sendApi(self: *Client, comptime T: type, comptime method: []const u8, args: anytype) !T { var arena = std.heap.ArenaAllocator.init(self.alloc); defer arena.deinit(); var params = std.ArrayList(u8).init(arena.allocator()); if (@typeInfo(@TypeOf(args)) != .Struct) { @compileError("expected struct"); } inline for (std.meta.fields(@TypeOf(args))) |field| { try params.appendSlice(field.name); try params.append('='); try params.appendSlice(reflectParse(@field(args, field.name))); try params.append('&'); } _ = params.popOrNull(); // const url = try std.fmt.allocPrint(arena.allocator(), "{s}/api/" ++ method ++ "?{s}", .{ self.config.url, params.items, }); std.debug.print("{s}\n", .{url}); const uri = try std.Uri.parse(url); var buf: [1024]u8 = undefined; var req = try self.client.open(.GET, uri, .{ .server_header_buffer = &buf, }); defer req.deinit(); try req.send(); try req.wait(); if (req.response.status != .ok) return error.BadStatus; var body = std.ArrayList(u8).init(arena.allocator()); try req.reader().readAllArrayList(&body, std.math.maxInt(usize)); try req.finish(); const result = try std.json.parseFromSliceLeaky(Response([]User), self.arena.allocator(), body.items, .{ .ignore_unknown_fields = true, .allocate = .alloc_always, }); if (result.status == .FAILED) return error.FailedCF; return result.result orelse error.InvalidFieldCF; } fn userInfo(self: *Client, handles: []const u8) ![]User { return self.sendApi([]User, "user.info", .{ .handles = handles, .checkHistoricHandles = false }); } }; const User = struct { handle: []const u8, firstName: ?[]const u8 = null, lastName: ?[]const u8 = null, rating: i32, }; fn Response(comptime T: type) type { return struct { status: enum { OK, FAILED }, comment: []const u8 = "", result: ?T, }; } pub fn main() !void { var gpa: std.heap.GeneralPurposeAllocator(.{}) = .{}; defer _ = gpa.deinit(); const alloc = gpa.allocator(); var cli = Client.init(alloc, .{}); defer cli.deinit(); const users = try cli.userInfo("oniuzhe"); for (users) |user| { std.debug.print("{?s} {}\n", .{ user.lastName, user.rating }); } } // 1, 2, 3, 4, 5... fn genList(alloc: std.mem.Allocator, n: usize) ![]i32 { var arr = try std.ArrayList(i32).initCapacity(alloc, n); for (1..n + 1) |i| { arr.appendAssumeCapacity(@intCast(i)); } return arr.toOwnedSlice(); } test "gen list" { const arr = try genList(std.testing.allocator, 5); defer std.testing.allocator.free(arr); try std.testing.expectEqualSlices(i32, &[_]i32{ 1, 2, 3, 4, 5 }, arr); } test "array list" { var arr = std.ArrayList(i32).init(std.testing.allocator); defer arr.deinit(); try arr.append(43); try arr.appendSlice(&[_]i32{ 1, 2, 3 }); _ = arr.popOrNull(); try std.testing.expectEqualSlices(i32, &[_]i32{ 43, 1, 2 }, arr.items); } test "vectorization" { const arr = &[_]i32{ 1, 2, 3, 4, 5, 6, 123, 123, 1, 2, 3, 4, 1, 213, 123, 123, 432, 123, 432, 123, 432 }; var rres: @Vector(8, i32) = @splat(std.math.maxInt(i32)); var i: usize = 0; while (i + 8 < arr.len) : (i += 8) { const rarr: @Vector(8, i32) = arr[i..][0..8].*; rres = @min(rres, rarr); } var ans = @reduce(.Min, rres); while (i < arr.len) : (i += 1) { ans = @min(ans, arr[i]); } try std.testing.expectEqual(std.mem.min(i32, arr), ans); }