1const std = @import("std");2const pkt = @import("packet.zig");3const opts = @import("opts.zig");4const codes = @import("codes.zig");56pub const ResourceHandler = fn (resp: *pkt.Response, req: *pkt.Request) codes.Code;78// Size for reply buffer9const REPLY_BUFSIZ = 256;1011pub const Resource = struct {12 path: []const u8,13 handler: ResourceHandler,1415 pub fn matchPath(self: Resource, path: []const u8) bool {16 return std.mem.eql(u8, self.path, path);17 }18};1920pub const Dispatcher = struct {21 resources: []const Resource,22 rbuf: [REPLY_BUFSIZ]u8 = undefined,2324 pub fn reply(self: *Dispatcher, req: *const pkt.Request, mt: pkt.Msg, code: codes.Code) !pkt.Response {25 return pkt.Response.reply(&self.rbuf, req, mt, code);26 }2728 pub fn dispatch(self: *Dispatcher, req: *pkt.Request) !pkt.Response {29 const hdr = req.header;30 if (hdr.type == pkt.Msg.con) {31 // We are not able to process confirmable message presently32 // thus *always* answer those with a reset with NOT_IMPL.33 return self.reply(req, pkt.Msg.rst, codes.NOT_IMPL);34 }3536 const path_opt = try req.findOption(opts.URIPath);37 const path = path_opt.value;3839 for (self.resources) |res| {40 if (!res.matchPath(path))41 continue;4243 var resp = try self.reply(req, pkt.Msg.non, .{ .class = 0, .detail = 0 });44 resp.setCode(res.handler(&resp, req));4546 return resp;47 }4849 return self.reply(req, pkt.Msg.non, codes.NOT_FOUND);50 }51};