Guest User

Untitled

a guest
Dec 3rd, 2023
70
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 3.58 KB | None | 0 0
  1. const os = @import("std").os;
  2. const std = @import("std");
  3.  
  4. const AnyType = @import("types.zig").AnyType;
  5.  
  6. pub const ProtocolHandler = ProtocolHandlerT(*const std.net.Stream.Reader);
  7. fn ProtocolHandlerT(comptime GenericReader: type) type {
  8.     return struct {
  9.         const Self = @This();
  10.  
  11.         const HandlerFunc = fn (self: *Self, reader: GenericReader) anyerror!AnyType;
  12.         handlers: std.StringHashMap(*const HandlerFunc),
  13.         allocator: std.mem.Allocator,
  14.  
  15.         pub fn init(allocator: std.mem.Allocator) !Self {
  16.             var handler = Self{
  17.                 .handlers = std.StringHashMap(*const HandlerFunc).init(allocator),
  18.                 .allocator = allocator,
  19.             };
  20.  
  21.             try handler.handlers.put("+", handle_sstring);
  22.             try handler.handlers.put("*", handle_array);
  23.             try handler.handlers.put("$", handle_string);
  24.             try handler.handlers.put(":", handle_int);
  25.  
  26.             return handler;
  27.         }
  28.  
  29.         pub fn handle_request(self: *Self, reader: GenericReader) !AnyType {
  30.             var request_type: [1]u8 = undefined;
  31.             const size = try reader.readAtLeast(&request_type, 1);
  32.  
  33.             if (size == 0) return error.BadRequest;
  34.  
  35.             const handler_ref = self.handlers.get(&request_type);
  36.             if (handler_ref == null) return error.BadRequest;
  37.             return if (handler_ref) |ref| try ref(self, reader) else error.BadRequest;
  38.         }
  39.  
  40.         pub fn deinit(self: *Self) void {
  41.             self.handlers.deinit();
  42.         }
  43.  
  44.         fn handle_sstring(self: *Self, reader: GenericReader) !AnyType {
  45.             const bytes = try self.read_line_alloc(reader);
  46.  
  47.             if (bytes.?.len == 0) return error.BadRequest;
  48.  
  49.             return .{ .str = bytes.? };
  50.         }
  51.  
  52.         fn handle_string(self: *Self, reader: GenericReader) !AnyType {
  53.             _ = try self.read_line_alloc(reader); // we don't care about the length of the string
  54.  
  55.             const string = try self.read_line_alloc(reader);
  56.  
  57.             return .{ .str = string.?[0 .. string.?.len - 1] };
  58.         }
  59.  
  60.         fn handle_int(self: *Self, reader: GenericReader) !AnyType {
  61.             const bytes = try self.read_line_alloc(reader);
  62.             if (bytes.?.len == 0) return error.BadRequest;
  63.  
  64.             const int = std.fmt.parseInt(i64, bytes.?[0 .. bytes.?.len - 1], 10) catch {
  65.                 return error.InvalidArrayLength;
  66.             };
  67.  
  68.             return .{ .int = int };
  69.         }
  70.  
  71.         fn handle_array(self: *Self, reader: GenericReader) !AnyType {
  72.             const bytes = try self.read_line_alloc(reader);
  73.  
  74.             if (bytes.?.len == 0) return error.BadRequest;
  75.  
  76.             const array_len = std.fmt.parseInt(usize, bytes.?[0 .. bytes.?.len - 1], 10) catch {
  77.                 return error.InvalidArrayLength;
  78.             };
  79.  
  80.             var result = std.ArrayList(AnyType).initCapacity(self.allocator, array_len) catch {
  81.                 return error.AllocatorError;
  82.             };
  83.  
  84.             for (0..array_len) |_| {
  85.                 const item = try self.handle_request(reader);
  86.                 try result.append(item);
  87.             }
  88.             return .{ .array = result };
  89.         }
  90.  
  91.         fn read_line_alloc(self: *Self, reader: GenericReader) !?[]const u8 {
  92.             const bytes: ?[]const u8 = reader.readUntilDelimiterOrEofAlloc(
  93.                 self.allocator,
  94.                 '\n',
  95.                 std.math.maxInt(usize),
  96.             ) catch {
  97.                 return error.BadRequest;
  98.             };
  99.             return bytes;
  100.         }
  101.     };
  102. }
Advertisement
Add Comment
Please, Sign In to add comment