summaryrefslogtreecommitdiff
path: root/src/server
diff options
context:
space:
mode:
Diffstat (limited to 'src/server')
-rw-r--r--src/server/message_parser.zig59
1 files changed, 43 insertions, 16 deletions
diff --git a/src/server/message_parser.zig b/src/server/message_parser.zig
index 381dc2c..0d60df5 100644
--- a/src/server/message_parser.zig
+++ b/src/server/message_parser.zig
@@ -294,7 +294,7 @@ pub const Message = union(enum) {
@branchHint(.unlikely);
return error.InvalidStream;
}
- const subject = try readSubject(alloc, in);
+ const subject = try readSubject(alloc, in, .sub);
errdefer alloc.free(subject);
const second = blk: {
// Drop whitespace
@@ -392,7 +392,7 @@ fn parsePub(alloc: std.mem.Allocator, in: *std.Io.Reader) !Message {
try in.discardAll(1); // throw away space
// Parse subject
- const subject: []const u8 = try readSubject(alloc, in);
+ const subject: []const u8 = try readSubject(alloc, in, .@"pub");
errdefer alloc.free(subject);
const States = enum {
@@ -526,7 +526,7 @@ fn parseHPub(alloc: std.mem.Allocator, in: *std.Io.Reader) !Message {
try in.discardAll(1); // throw away space
// Parse subject
- const subject: []const u8 = try readSubject(alloc, in);
+ const subject: []const u8 = try readSubject(alloc, in, .@"pub");
errdefer alloc.free(subject);
const States = enum {
@@ -699,30 +699,57 @@ test parseHPub {
}
}
-fn readSubject(alloc: std.mem.Allocator, in: *std.Io.Reader) ![]const u8 {
+fn readSubject(alloc: std.mem.Allocator, in: *std.Io.Reader, comptime pub_or_sub: enum { @"pub", sub }) ![]const u8 {
var subject_list: std.ArrayList(u8) = .empty;
errdefer subject_list.deinit(alloc);
// Handle the first character
{
const byte = try in.takeByte();
- if (std.ascii.isWhitespace(byte) or byte == '.')
+ if (std.ascii.isWhitespace(byte) or byte == '.' or (pub_or_sub == .@"pub" and (byte == '*' or byte == '>')))
return error.InvalidStream;
try subject_list.append(alloc, byte);
}
- while (in.takeByte()) |byte| {
- if (std.ascii.isWhitespace(byte)) break;
- if (std.ascii.isAscii(byte)) {
- if (byte == '.') {
- const next_byte = try in.peekByte();
- if (next_byte == '.' or std.ascii.isWhitespace(next_byte))
- return error.InvalidSubject;
- }
- try subject_list.append(alloc, byte);
- }
- } else |err| return err;
+ switch (pub_or_sub) {
+ .sub => {
+ while (in.takeByte()) |byte| {
+ if (std.ascii.isWhitespace(byte)) break;
+ if (std.ascii.isAscii(byte)) {
+ if (byte == '.') {
+ const next_byte = try in.peekByte();
+ if (next_byte == '.' or std.ascii.isWhitespace(next_byte))
+ return error.InvalidStream;
+ } else if (byte == '>') {
+ const next_byte = try in.takeByte();
+ if (!std.ascii.isWhitespace(next_byte))
+ return error.InvalidStream;
+ } else if (byte == '*') {
+ const next_byte = try in.peekByte();
+ if (next_byte != '.' and !std.ascii.isWhitespace(next_byte))
+ return error.InvalidStream;
+ }
+ try subject_list.append(alloc, byte);
+ }
+ } else |err| return err;
+ },
+ .@"pub" => {
+ while (in.takeByte()) |byte| {
+ if (std.ascii.isWhitespace(byte)) break;
+ if (std.ascii.isAscii(byte)) {
+ if (byte == '*' or byte == '>') return error.InvalidStream;
+ if (byte == '.') {
+ const next_byte = try in.peekByte();
+ if (next_byte == '.' or std.ascii.isWhitespace(next_byte))
+ return error.InvalidStream;
+ }
+ try subject_list.append(alloc, byte);
+ }
+ } else |err| return err;
+ },
+ }
+
return subject_list.toOwnedSlice(alloc);
}