authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-07-12 21:46:26+00:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2020-07-12 21:46:26+00:00
log7adbc1140373548f2985c8054b540cc5648f6857
treeff339ae921cbeae3a2225fc45306f4355daad80c
parent873e187f05400a8cb515f31896ce3ca11a377ac8
parent91235b937195910076a87cbb9ecbc6c5214ddd3b
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #5857 from daurnimator/use-unmanaged

Use unmanaged datastructures from std.http.headers

3 files changed, 50 insertions(+), 47 deletions(-)

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