const std = @import("std"); const SSHashMap = std.StringHashMap([]const u8); const Config = @import("config.zig"); const StartupMessage = @import("startup_message.zig"); const AuthenticationOk = @import("authentication_ok.zig"); const AuthenticationCleartextPassword = @import("authentication_cleartext_password.zig"); const ErrorResponse = @import("error_response.zig"); const Conn = @This(); const ConnStatus = enum { connStatusUninitialized, connStatusConnecting, connStatusClosed, connStatusIdle, connStatusBusy, }; stream: std.net.Stream, config: Config, status: ConnStatus, pub fn connect(config: Config) !Conn { const allocator = config.allocator; var stream = switch (config.address) { .net => |addr| try std.net.tcpConnectToAddress(addr), .unix => |path| try std.net.connectUnixSocket(path), }; var writer = stream.writer(); errdefer stream.close(); var params = SSHashMap.init(allocator); errdefer params.deinit(); try params.put("user", config.user); if (config.database) |database| try params.put(database); var sm = StartupMessage{ .parameters = params, }; defer sm.deinit(allocator); try sm.write(allocator, writer); } const StartupMessageResponseType = enum(u8) { ErrorResponse = 'E', AuthenticationResponse = AuthenticationOk.Tag, // All the authentication responses share a message type and must be decoded by the next field }; const StartupMessageResponse = union(StartupMessageResponseType) { error: ErrorResponse, };