Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- const os = @import("std").os;
- const std = @import("std");
- const AnyType = @import("types.zig").AnyType;
- pub const ProtocolHandler = ProtocolHandlerT(*const std.net.Stream.Reader);
- fn ProtocolHandlerT(comptime GenericReader: type) type {
- return struct {
- const Self = @This();
- const HandlerFunc = fn (self: *Self, reader: GenericReader) anyerror!AnyType;
- handlers: std.StringHashMap(*const HandlerFunc),
- allocator: std.mem.Allocator,
- pub fn init(allocator: std.mem.Allocator) !Self {
- var handler = Self{
- .handlers = std.StringHashMap(*const HandlerFunc).init(allocator),
- .allocator = allocator,
- };
- try handler.handlers.put("+", handle_sstring);
- try handler.handlers.put("*", handle_array);
- try handler.handlers.put("$", handle_string);
- try handler.handlers.put(":", handle_int);
- return handler;
- }
- pub fn handle_request(self: *Self, reader: GenericReader) !AnyType {
- var request_type: [1]u8 = undefined;
- const size = try reader.readAtLeast(&request_type, 1);
- if (size == 0) return error.BadRequest;
- const handler_ref = self.handlers.get(&request_type);
- if (handler_ref == null) return error.BadRequest;
- return if (handler_ref) |ref| try ref(self, reader) else error.BadRequest;
- }
- pub fn deinit(self: *Self) void {
- self.handlers.deinit();
- }
- fn handle_sstring(self: *Self, reader: GenericReader) !AnyType {
- const bytes = try self.read_line_alloc(reader);
- if (bytes.?.len == 0) return error.BadRequest;
- return .{ .str = bytes.? };
- }
- fn handle_string(self: *Self, reader: GenericReader) !AnyType {
- _ = try self.read_line_alloc(reader); // we don't care about the length of the string
- const string = try self.read_line_alloc(reader);
- return .{ .str = string.?[0 .. string.?.len - 1] };
- }
- fn handle_int(self: *Self, reader: GenericReader) !AnyType {
- const bytes = try self.read_line_alloc(reader);
- if (bytes.?.len == 0) return error.BadRequest;
- const int = std.fmt.parseInt(i64, bytes.?[0 .. bytes.?.len - 1], 10) catch {
- return error.InvalidArrayLength;
- };
- return .{ .int = int };
- }
- fn handle_array(self: *Self, reader: GenericReader) !AnyType {
- const bytes = try self.read_line_alloc(reader);
- if (bytes.?.len == 0) return error.BadRequest;
- const array_len = std.fmt.parseInt(usize, bytes.?[0 .. bytes.?.len - 1], 10) catch {
- return error.InvalidArrayLength;
- };
- var result = std.ArrayList(AnyType).initCapacity(self.allocator, array_len) catch {
- return error.AllocatorError;
- };
- for (0..array_len) |_| {
- const item = try self.handle_request(reader);
- try result.append(item);
- }
- return .{ .array = result };
- }
- fn read_line_alloc(self: *Self, reader: GenericReader) !?[]const u8 {
- const bytes: ?[]const u8 = reader.readUntilDelimiterOrEofAlloc(
- self.allocator,
- '\n',
- std.math.maxInt(usize),
- ) catch {
- return error.BadRequest;
- };
- return bytes;
- }
- };
- }
Advertisement
Add Comment
Please, Sign In to add comment