| ... | ... | @@ -27,7 +27,6 @@ fn never_index_default(name: []const u8) bool { |
| 27 | 27 | } |
| 28 | 28 | |
| 29 | 29 | const HeaderEntry = struct { |
| 30 | | allocator: *Allocator, |
| 31 | 30 | name: []const u8, |
| 32 | 31 | value: []u8, |
| 33 | 32 | never_index: bool, |
| ... | ... | @@ -36,23 +35,22 @@ const HeaderEntry = struct { |
| 36 | 35 | |
| 37 | 36 | fn init(allocator: *Allocator, name: []const u8, value: []const u8, never_index: ?bool) !Self { |
| 38 | 37 | return Self{ |
| 39 | | .allocator = allocator, |
| 40 | 38 | .name = name, // takes reference |
| 41 | 39 | .value = try allocator.dupe(u8, value), |
| 42 | 40 | .never_index = never_index orelse never_index_default(name), |
| 43 | 41 | }; |
| 44 | 42 | } |
| 45 | 43 | |
| 46 | | fn deinit(self: Self) void { |
| 47 | | self.allocator.free(self.value); |
| 44 | fn deinit(self: Self, allocator: *Allocator) void { |
| 45 | allocator.free(self.value); |
| 48 | 46 | } |
| 49 | 47 | |
| 50 | | pub fn modify(self: *Self, value: []const u8, never_index: ?bool) !void { |
| 48 | pub fn modify(self: *Self, allocator: *Allocator, value: []const u8, never_index: ?bool) !void { |
| 51 | 49 | const old_len = self.value.len; |
| 52 | 50 | if (value.len > old_len) { |
| 53 | | self.value = try self.allocator.realloc(self.value, value.len); |
| 51 | self.value = try allocator.realloc(self.value, value.len); |
| 54 | 52 | } else if (value.len < old_len) { |
| 55 | | self.value = self.allocator.shrink(self.value, value.len); |
| 53 | self.value = allocator.shrink(self.value, value.len); |
| 56 | 54 | } |
| 57 | 55 | mem.copy(u8, self.value, value); |
| 58 | 56 | self.never_index = never_index orelse never_index_default(self.name); |
| ... | ... | @@ -85,22 +83,22 @@ const HeaderEntry = struct { |
| 85 | 83 | |
| 86 | 84 | test "HeaderEntry" { |
| 87 | 85 | var e = try HeaderEntry.init(testing.allocator, "foo", "bar", null); |
| 88 | | defer e.deinit(); |
| 86 | defer e.deinit(testing.allocator); |
| 89 | 87 | testing.expectEqualSlices(u8, "foo", e.name); |
| 90 | 88 | testing.expectEqualSlices(u8, "bar", e.value); |
| 91 | 89 | testing.expectEqual(false, e.never_index); |
| 92 | 90 | |
| 93 | | try e.modify("longer value", null); |
| 91 | try e.modify(testing.allocator, "longer value", null); |
| 94 | 92 | testing.expectEqualSlices(u8, "longer value", e.value); |
| 95 | 93 | |
| 96 | 94 | // shorter value |
| 97 | | try e.modify("x", null); |
| 95 | try e.modify(testing.allocator, "x", null); |
| 98 | 96 | testing.expectEqualSlices(u8, "x", e.value); |
| 99 | 97 | } |
| 100 | 98 | |
| 101 | | const HeaderList = std.ArrayList(HeaderEntry); |
| 102 | | const HeaderIndexList = std.ArrayList(usize); |
| 103 | | const HeaderIndex = std.StringHashMap(HeaderIndexList); |
| 99 | const HeaderList = std.ArrayListUnmanaged(HeaderEntry); |
| 100 | const HeaderIndexList = std.ArrayListUnmanaged(usize); |
| 101 | const HeaderIndex = std.StringHashMapUnmanaged(HeaderIndexList); |
| 104 | 102 | |
| 105 | 103 | pub const Headers = struct { |
| 106 | 104 | // the owned header field name is stored in the index as part of the key |
| ... | ... | @@ -113,8 +111,8 @@ pub const Headers = struct { |
| 113 | 111 | pub fn init(allocator: *Allocator) Self { |
| 114 | 112 | return Self{ |
| 115 | 113 | .allocator = allocator, |
| 116 | | .data = HeaderList.init(allocator), |
| 117 | | .index = HeaderIndex.init(allocator), |
| 114 | .data = HeaderList{}, |
| 115 | .index = HeaderIndex{}, |
| 118 | 116 | }; |
| 119 | 117 | } |
| 120 | 118 | |
| ... | ... | @@ -122,16 +120,16 @@ pub const Headers = struct { |
| 122 | 120 | { |
| 123 | 121 | for (self.index.items()) |*entry| { |
| 124 | 122 | const dex = &entry.value; |
| 125 | | dex.deinit(); |
| 123 | dex.deinit(self.allocator); |
| 126 | 124 | self.allocator.free(entry.key); |
| 127 | 125 | } |
| 128 | | self.index.deinit(); |
| 126 | self.index.deinit(self.allocator); |
| 129 | 127 | } |
| 130 | 128 | { |
| 131 | | for (self.data.span()) |entry| { |
| 132 | | entry.deinit(); |
| 129 | for (self.data.items) |entry| { |
| 130 | entry.deinit(self.allocator); |
| 133 | 131 | } |
| 134 | | self.data.deinit(); |
| 132 | self.data.deinit(self.allocator); |
| 135 | 133 | } |
| 136 | 134 | self.* = undefined; |
| 137 | 135 | } |
| ... | ... | @@ -139,36 +137,36 @@ pub const Headers = struct { |
| 139 | 137 | pub fn clone(self: Self, allocator: *Allocator) !Self { |
| 140 | 138 | var other = Headers.init(allocator); |
| 141 | 139 | errdefer other.deinit(); |
| 142 | | try other.data.ensureCapacity(self.data.items.len); |
| 143 | | try other.index.initCapacity(self.index.entries.len); |
| 144 | | for (self.data.span()) |entry| { |
| 140 | try other.data.ensureCapacity(allocator, self.data.items.len); |
| 141 | try other.index.initCapacity(allocator, self.index.entries.len); |
| 142 | for (self.data.items) |entry| { |
| 145 | 143 | try other.append(entry.name, entry.value, entry.never_index); |
| 146 | 144 | } |
| 147 | 145 | return other; |
| 148 | 146 | } |
| 149 | 147 | |
| 150 | 148 | pub fn toSlice(self: Self) []const HeaderEntry { |
| 151 | | return self.data.span(); |
| 149 | return self.data.items; |
| 152 | 150 | } |
| 153 | 151 | |
| 154 | 152 | pub fn append(self: *Self, name: []const u8, value: []const u8, never_index: ?bool) !void { |
| 155 | 153 | const n = self.data.items.len + 1; |
| 156 | | try self.data.ensureCapacity(n); |
| 154 | try self.data.ensureCapacity(self.allocator, n); |
| 157 | 155 | var entry: HeaderEntry = undefined; |
| 158 | 156 | if (self.index.getEntry(name)) |kv| { |
| 159 | 157 | entry = try HeaderEntry.init(self.allocator, kv.key, value, never_index); |
| 160 | | errdefer entry.deinit(); |
| 158 | errdefer entry.deinit(self.allocator); |
| 161 | 159 | const dex = &kv.value; |
| 162 | | try dex.append(n - 1); |
| 160 | try dex.append(self.allocator, n - 1); |
| 163 | 161 | } else { |
| 164 | 162 | const name_dup = try self.allocator.dupe(u8, name); |
| 165 | 163 | errdefer self.allocator.free(name_dup); |
| 166 | 164 | entry = try HeaderEntry.init(self.allocator, name_dup, value, never_index); |
| 167 | | errdefer entry.deinit(); |
| 168 | | var dex = HeaderIndexList.init(self.allocator); |
| 169 | | try dex.append(n - 1); |
| 170 | | errdefer dex.deinit(); |
| 171 | | _ = try self.index.put(name_dup, dex); |
| 165 | errdefer entry.deinit(self.allocator); |
| 166 | var dex = HeaderIndexList{}; |
| 167 | try dex.append(self.allocator, n - 1); |
| 168 | errdefer dex.deinit(self.allocator); |
| 169 | _ = try self.index.put(self.allocator, name_dup, dex); |
| 172 | 170 | } |
| 173 | 171 | self.data.appendAssumeCapacity(entry); |
| 174 | 172 | } |
| ... | ... | @@ -194,7 +192,7 @@ pub const Headers = struct { |
| 194 | 192 | |
| 195 | 193 | /// Returns boolean indicating if something was deleted. |
| 196 | 194 | pub fn delete(self: *Self, name: []const u8) bool { |
| 197 | | if (self.index.remove(name)) |kv| { |
| 195 | if (self.index.remove(name)) |*kv| { |
| 198 | 196 | const dex = &kv.value; |
| 199 | 197 | // iterate backwards |
| 200 | 198 | var i = dex.items.len; |
| ... | ... | @@ -203,9 +201,9 @@ pub const Headers = struct { |
| 203 | 201 | const data_index = dex.items[i]; |
| 204 | 202 | const removed = self.data.orderedRemove(data_index); |
| 205 | 203 | assert(mem.eql(u8, removed.name, name)); |
| 206 | | removed.deinit(); |
| 204 | removed.deinit(self.allocator); |
| 207 | 205 | } |
| 208 | | dex.deinit(); |
| 206 | dex.deinit(self.allocator); |
| 209 | 207 | self.allocator.free(kv.key); |
| 210 | 208 | self.rebuildIndex(); |
| 211 | 209 | return true; |
| ... | ... | @@ -225,14 +223,14 @@ pub const Headers = struct { |
| 225 | 223 | const dex = &kv.value; |
| 226 | 224 | if (dex.items.len == 1) { |
| 227 | 225 | // was last item; delete the index |
| 228 | | dex.deinit(); |
| 229 | | removed.deinit(); |
| 226 | dex.deinit(self.allocator); |
| 227 | removed.deinit(self.allocator); |
| 230 | 228 | const key = kv.key; |
| 231 | 229 | _ = self.index.remove(key); // invalidates `kv` and `dex` |
| 232 | 230 | self.allocator.free(key); |
| 233 | 231 | } else { |
| 234 | | dex.shrink(dex.items.len - 1); |
| 235 | | removed.deinit(); |
| 232 | dex.shrink(self.allocator, dex.items.len - 1); |
| 233 | removed.deinit(self.allocator); |
| 236 | 234 | } |
| 237 | 235 | // if it was the last item; no need to rebuild index |
| 238 | 236 | if (i != self.data.items.len) { |
| ... | ... | @@ -250,14 +248,14 @@ pub const Headers = struct { |
| 250 | 248 | const dex = &kv.value; |
| 251 | 249 | if (dex.items.len == 1) { |
| 252 | 250 | // was last item; delete the index |
| 253 | | dex.deinit(); |
| 254 | | removed.deinit(); |
| 251 | dex.deinit(self.allocator); |
| 252 | removed.deinit(self.allocator); |
| 255 | 253 | const key = kv.key; |
| 256 | 254 | _ = self.index.remove(key); // invalidates `kv` and `dex` |
| 257 | 255 | self.allocator.free(key); |
| 258 | 256 | } else { |
| 259 | | dex.shrink(dex.items.len - 1); |
| 260 | | removed.deinit(); |
| 257 | dex.shrink(self.allocator, dex.items.len - 1); |
| 258 | removed.deinit(self.allocator); |
| 261 | 259 | } |
| 262 | 260 | // if it was the last item; no need to rebuild index |
| 263 | 261 | if (i != self.data.items.len) { |
| ... | ... | @@ -282,7 +280,7 @@ pub const Headers = struct { |
| 282 | 280 | |
| 283 | 281 | const buf = try allocator.alloc(HeaderEntry, dex.items.len); |
| 284 | 282 | var n: usize = 0; |
| 285 | | for (dex.span()) |idx| { |
| 283 | for (dex.items) |idx| { |
| 286 | 284 | buf[n] = self.data.items[idx]; |
| 287 | 285 | n += 1; |
| 288 | 286 | } |
| ... | ... | @@ -305,7 +303,7 @@ pub const Headers = struct { |
| 305 | 303 | // adapted from mem.join |
| 306 | 304 | const total_len = blk: { |
| 307 | 305 | var sum: usize = dex.items.len - 1; // space for separator(s) |
| 308 | | for (dex.span()) |idx| |
| 306 | for (dex.items) |idx| |
| 309 | 307 | sum += self.data.items[idx].value.len; |
| 310 | 308 | break :blk sum; |
| 311 | 309 | }; |
| ... | ... | @@ -493,8 +491,8 @@ test "Headers.getIndices" { |
| 493 | 491 | try h.append("set-cookie", "y=2", null); |
| 494 | 492 | |
| 495 | 493 | testing.expect(null == h.getIndices("not-present")); |
| 496 | | testing.expectEqualSlices(usize, &[_]usize{0}, h.getIndices("foo").?.span()); |
| 497 | | testing.expectEqualSlices(usize, &[_]usize{ 1, 2 }, h.getIndices("set-cookie").?.span()); |
| 494 | testing.expectEqualSlices(usize, &[_]usize{0}, h.getIndices("foo").?.items); |
| 495 | testing.expectEqualSlices(usize, &[_]usize{ 1, 2 }, h.getIndices("set-cookie").?.items); |
| 498 | 496 | } |
| 499 | 497 | |
| 500 | 498 | test "Headers.get" { |