authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2024-11-27 14:03:14-08:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2024-11-27 14:34:26-08:00
logda6e80c30a52fe061d6e534636d373594bf1cd7b
treec53f8ee78a8d719529c23a460ec6ef1a4fd71976
parentc9c7ede2f9be23fd212d968fbc2fdec6ebefdeeb

std.ArrayHashMap: explicit error sets


1 files changed, 26 insertions(+), 24 deletions(-)

lib/std/array_hash_map.zig+26-24
...@@ -604,6 +604,8 @@ pub fn ArrayHashMapUnmanaged(...@@ -604,6 +604,8 @@ pub fn ArrayHashMapUnmanaged(
604 ordered,604 ordered,
605 };605 };
606606
607 const Oom = Allocator.Error;
608
607 /// Convert from an unmanaged map to a managed map. After calling this,609 /// Convert from an unmanaged map to a managed map. After calling this,
608 /// the promoted map should no longer be used.610 /// the promoted map should no longer be used.
609 pub fn promote(self: Self, allocator: Allocator) Managed {611 pub fn promote(self: Self, allocator: Allocator) Managed {
...@@ -619,14 +621,14 @@ pub fn ArrayHashMapUnmanaged(...@@ -619,14 +621,14 @@ pub fn ArrayHashMapUnmanaged(
619 };621 };
620 }622 }
621623
622 pub fn init(allocator: Allocator, key_list: []const K, value_list: []const V) !Self {624 pub fn init(allocator: Allocator, key_list: []const K, value_list: []const V) Oom!Self {
623 var self: Self = .{};625 var self: Self = .{};
624 errdefer self.deinit(allocator);626 errdefer self.deinit(allocator);
625 try self.reinit(allocator, key_list, value_list);627 try self.reinit(allocator, key_list, value_list);
626 return self;628 return self;
627 }629 }
628630
629 pub fn reinit(self: *Self, allocator: Allocator, key_list: []const K, value_list: []const V) !void {631 pub fn reinit(self: *Self, allocator: Allocator, key_list: []const K, value_list: []const V) Oom!void {
630 try self.entries.resize(allocator, key_list.len);632 try self.entries.resize(allocator, key_list.len);
631 @memcpy(self.keys(), key_list);633 @memcpy(self.keys(), key_list);
632 if (@sizeOf(V) != 0) {634 if (@sizeOf(V) != 0) {
...@@ -750,24 +752,24 @@ pub fn ArrayHashMapUnmanaged(...@@ -750,24 +752,24 @@ pub fn ArrayHashMapUnmanaged(
750 /// Otherwise, puts a new item with undefined value, and752 /// Otherwise, puts a new item with undefined value, and
751 /// the `Entry` pointer points to it. Caller should then initialize753 /// the `Entry` pointer points to it. Caller should then initialize
752 /// the value (but not the key).754 /// the value (but not the key).
753 pub fn getOrPut(self: *Self, allocator: Allocator, key: K) !GetOrPutResult {755 pub fn getOrPut(self: *Self, allocator: Allocator, key: K) Oom!GetOrPutResult {
754 if (@sizeOf(Context) != 0)756 if (@sizeOf(Context) != 0)
755 @compileError("Cannot infer context " ++ @typeName(Context) ++ ", call getOrPutContext instead.");757 @compileError("Cannot infer context " ++ @typeName(Context) ++ ", call getOrPutContext instead.");
756 return self.getOrPutContext(allocator, key, undefined);758 return self.getOrPutContext(allocator, key, undefined);
757 }759 }
758 pub fn getOrPutContext(self: *Self, allocator: Allocator, key: K, ctx: Context) !GetOrPutResult {760 pub fn getOrPutContext(self: *Self, allocator: Allocator, key: K, ctx: Context) Oom!GetOrPutResult {
759 const gop = try self.getOrPutContextAdapted(allocator, key, ctx, ctx);761 const gop = try self.getOrPutContextAdapted(allocator, key, ctx, ctx);
760 if (!gop.found_existing) {762 if (!gop.found_existing) {
761 gop.key_ptr.* = key;763 gop.key_ptr.* = key;
762 }764 }
763 return gop;765 return gop;
764 }766 }
765 pub fn getOrPutAdapted(self: *Self, allocator: Allocator, key: anytype, key_ctx: anytype) !GetOrPutResult {767 pub fn getOrPutAdapted(self: *Self, allocator: Allocator, key: anytype, key_ctx: anytype) Oom!GetOrPutResult {
766 if (@sizeOf(Context) != 0)768 if (@sizeOf(Context) != 0)
767 @compileError("Cannot infer context " ++ @typeName(Context) ++ ", call getOrPutContextAdapted instead.");769 @compileError("Cannot infer context " ++ @typeName(Context) ++ ", call getOrPutContextAdapted instead.");
768 return self.getOrPutContextAdapted(allocator, key, key_ctx, undefined);770 return self.getOrPutContextAdapted(allocator, key, key_ctx, undefined);
769 }771 }
770 pub fn getOrPutContextAdapted(self: *Self, allocator: Allocator, key: anytype, key_ctx: anytype, ctx: Context) !GetOrPutResult {772 pub fn getOrPutContextAdapted(self: *Self, allocator: Allocator, key: anytype, key_ctx: anytype, ctx: Context) Oom!GetOrPutResult {
771 self.ensureTotalCapacityContext(allocator, self.entries.len + 1, ctx) catch |err| {773 self.ensureTotalCapacityContext(allocator, self.entries.len + 1, ctx) catch |err| {
772 // "If key exists this function cannot fail."774 // "If key exists this function cannot fail."
773 const index = self.getIndexAdapted(key, key_ctx) orelse return err;775 const index = self.getIndexAdapted(key, key_ctx) orelse return err;
...@@ -848,12 +850,12 @@ pub fn ArrayHashMapUnmanaged(...@@ -848,12 +850,12 @@ pub fn ArrayHashMapUnmanaged(
848 }850 }
849 }851 }
850852
851 pub fn getOrPutValue(self: *Self, allocator: Allocator, key: K, value: V) !GetOrPutResult {853 pub fn getOrPutValue(self: *Self, allocator: Allocator, key: K, value: V) Oom!GetOrPutResult {
852 if (@sizeOf(Context) != 0)854 if (@sizeOf(Context) != 0)
853 @compileError("Cannot infer context " ++ @typeName(Context) ++ ", call getOrPutValueContext instead.");855 @compileError("Cannot infer context " ++ @typeName(Context) ++ ", call getOrPutValueContext instead.");
854 return self.getOrPutValueContext(allocator, key, value, undefined);856 return self.getOrPutValueContext(allocator, key, value, undefined);
855 }857 }
856 pub fn getOrPutValueContext(self: *Self, allocator: Allocator, key: K, value: V, ctx: Context) !GetOrPutResult {858 pub fn getOrPutValueContext(self: *Self, allocator: Allocator, key: K, value: V, ctx: Context) Oom!GetOrPutResult {
857 const res = try self.getOrPutContextAdapted(allocator, key, ctx, ctx);859 const res = try self.getOrPutContextAdapted(allocator, key, ctx, ctx);
858 if (!res.found_existing) {860 if (!res.found_existing) {
859 res.key_ptr.* = key;861 res.key_ptr.* = key;
...@@ -864,12 +866,12 @@ pub fn ArrayHashMapUnmanaged(...@@ -864,12 +866,12 @@ pub fn ArrayHashMapUnmanaged(
864866
865 /// Increases capacity, guaranteeing that insertions up until the867 /// Increases capacity, guaranteeing that insertions up until the
866 /// `expected_count` will not cause an allocation, and therefore cannot fail.868 /// `expected_count` will not cause an allocation, and therefore cannot fail.
867 pub fn ensureTotalCapacity(self: *Self, allocator: Allocator, new_capacity: usize) !void {869 pub fn ensureTotalCapacity(self: *Self, allocator: Allocator, new_capacity: usize) Oom!void {
868 if (@sizeOf(ByIndexContext) != 0)870 if (@sizeOf(ByIndexContext) != 0)
869 @compileError("Cannot infer context " ++ @typeName(Context) ++ ", call ensureTotalCapacityContext instead.");871 @compileError("Cannot infer context " ++ @typeName(Context) ++ ", call ensureTotalCapacityContext instead.");
870 return self.ensureTotalCapacityContext(allocator, new_capacity, undefined);872 return self.ensureTotalCapacityContext(allocator, new_capacity, undefined);
871 }873 }
872 pub fn ensureTotalCapacityContext(self: *Self, allocator: Allocator, new_capacity: usize, ctx: Context) !void {874 pub fn ensureTotalCapacityContext(self: *Self, allocator: Allocator, new_capacity: usize, ctx: Context) Oom!void {
873 self.pointer_stability.lock();875 self.pointer_stability.lock();
874 defer self.pointer_stability.unlock();876 defer self.pointer_stability.unlock();
875877
...@@ -901,7 +903,7 @@ pub fn ArrayHashMapUnmanaged(...@@ -901,7 +903,7 @@ pub fn ArrayHashMapUnmanaged(
901 self: *Self,903 self: *Self,
902 allocator: Allocator,904 allocator: Allocator,
903 additional_capacity: usize,905 additional_capacity: usize,
904 ) !void {906 ) Oom!void {
905 if (@sizeOf(Context) != 0)907 if (@sizeOf(Context) != 0)
906 @compileError("Cannot infer context " ++ @typeName(Context) ++ ", call ensureTotalCapacityContext instead.");908 @compileError("Cannot infer context " ++ @typeName(Context) ++ ", call ensureTotalCapacityContext instead.");
907 return self.ensureUnusedCapacityContext(allocator, additional_capacity, undefined);909 return self.ensureUnusedCapacityContext(allocator, additional_capacity, undefined);
...@@ -911,7 +913,7 @@ pub fn ArrayHashMapUnmanaged(...@@ -911,7 +913,7 @@ pub fn ArrayHashMapUnmanaged(
911 allocator: Allocator,913 allocator: Allocator,
912 additional_capacity: usize,914 additional_capacity: usize,
913 ctx: Context,915 ctx: Context,
914 ) !void {916 ) Oom!void {
915 return self.ensureTotalCapacityContext(allocator, self.count() + additional_capacity, ctx);917 return self.ensureTotalCapacityContext(allocator, self.count() + additional_capacity, ctx);
916 }918 }
917919
...@@ -926,24 +928,24 @@ pub fn ArrayHashMapUnmanaged(...@@ -926,24 +928,24 @@ pub fn ArrayHashMapUnmanaged(
926928
927 /// Clobbers any existing data. To detect if a put would clobber929 /// Clobbers any existing data. To detect if a put would clobber
928 /// existing data, see `getOrPut`.930 /// existing data, see `getOrPut`.
929 pub fn put(self: *Self, allocator: Allocator, key: K, value: V) !void {931 pub fn put(self: *Self, allocator: Allocator, key: K, value: V) Oom!void {
930 if (@sizeOf(Context) != 0)932 if (@sizeOf(Context) != 0)
931 @compileError("Cannot infer context " ++ @typeName(Context) ++ ", call putContext instead.");933 @compileError("Cannot infer context " ++ @typeName(Context) ++ ", call putContext instead.");
932 return self.putContext(allocator, key, value, undefined);934 return self.putContext(allocator, key, value, undefined);
933 }935 }
934 pub fn putContext(self: *Self, allocator: Allocator, key: K, value: V, ctx: Context) !void {936 pub fn putContext(self: *Self, allocator: Allocator, key: K, value: V, ctx: Context) Oom!void {
935 const result = try self.getOrPutContext(allocator, key, ctx);937 const result = try self.getOrPutContext(allocator, key, ctx);
936 result.value_ptr.* = value;938 result.value_ptr.* = value;
937 }939 }
938940
939 /// Inserts a key-value pair into the hash map, asserting that no previous941 /// Inserts a key-value pair into the hash map, asserting that no previous
940 /// entry with the same key is already present942 /// entry with the same key is already present
941 pub fn putNoClobber(self: *Self, allocator: Allocator, key: K, value: V) !void {943 pub fn putNoClobber(self: *Self, allocator: Allocator, key: K, value: V) Oom!void {
942 if (@sizeOf(Context) != 0)944 if (@sizeOf(Context) != 0)
943 @compileError("Cannot infer context " ++ @typeName(Context) ++ ", call putNoClobberContext instead.");945 @compileError("Cannot infer context " ++ @typeName(Context) ++ ", call putNoClobberContext instead.");
944 return self.putNoClobberContext(allocator, key, value, undefined);946 return self.putNoClobberContext(allocator, key, value, undefined);
945 }947 }
946 pub fn putNoClobberContext(self: *Self, allocator: Allocator, key: K, value: V, ctx: Context) !void {948 pub fn putNoClobberContext(self: *Self, allocator: Allocator, key: K, value: V, ctx: Context) Oom!void {
947 const result = try self.getOrPutContext(allocator, key, ctx);949 const result = try self.getOrPutContext(allocator, key, ctx);
948 assert(!result.found_existing);950 assert(!result.found_existing);
949 result.value_ptr.* = value;951 result.value_ptr.* = value;
...@@ -977,12 +979,12 @@ pub fn ArrayHashMapUnmanaged(...@@ -977,12 +979,12 @@ pub fn ArrayHashMapUnmanaged(
977 }979 }
978980
979 /// Inserts a new `Entry` into the hash map, returning the previous one, if any.981 /// Inserts a new `Entry` into the hash map, returning the previous one, if any.
980 pub fn fetchPut(self: *Self, allocator: Allocator, key: K, value: V) !?KV {982 pub fn fetchPut(self: *Self, allocator: Allocator, key: K, value: V) Oom!?KV {
981 if (@sizeOf(Context) != 0)983 if (@sizeOf(Context) != 0)
982 @compileError("Cannot infer context " ++ @typeName(Context) ++ ", call fetchPutContext instead.");984 @compileError("Cannot infer context " ++ @typeName(Context) ++ ", call fetchPutContext instead.");
983 return self.fetchPutContext(allocator, key, value, undefined);985 return self.fetchPutContext(allocator, key, value, undefined);
984 }986 }
985 pub fn fetchPutContext(self: *Self, allocator: Allocator, key: K, value: V, ctx: Context) !?KV {987 pub fn fetchPutContext(self: *Self, allocator: Allocator, key: K, value: V, ctx: Context) Oom!?KV {
986 const gop = try self.getOrPutContext(allocator, key, ctx);988 const gop = try self.getOrPutContext(allocator, key, ctx);
987 var result: ?KV = null;989 var result: ?KV = null;
988 if (gop.found_existing) {990 if (gop.found_existing) {
...@@ -1269,12 +1271,12 @@ pub fn ArrayHashMapUnmanaged(...@@ -1269,12 +1271,12 @@ pub fn ArrayHashMapUnmanaged(
1269 /// Create a copy of the hash map which can be modified separately.1271 /// Create a copy of the hash map which can be modified separately.
1270 /// The copy uses the same context as this instance, but is allocated1272 /// The copy uses the same context as this instance, but is allocated
1271 /// with the provided allocator.1273 /// with the provided allocator.
1272 pub fn clone(self: Self, allocator: Allocator) !Self {1274 pub fn clone(self: Self, allocator: Allocator) Oom!Self {
1273 if (@sizeOf(ByIndexContext) != 0)1275 if (@sizeOf(ByIndexContext) != 0)
1274 @compileError("Cannot infer context " ++ @typeName(Context) ++ ", call cloneContext instead.");1276 @compileError("Cannot infer context " ++ @typeName(Context) ++ ", call cloneContext instead.");
1275 return self.cloneContext(allocator, undefined);1277 return self.cloneContext(allocator, undefined);
1276 }1278 }
1277 pub fn cloneContext(self: Self, allocator: Allocator, ctx: Context) !Self {1279 pub fn cloneContext(self: Self, allocator: Allocator, ctx: Context) Oom!Self {
1278 var other: Self = .{};1280 var other: Self = .{};
1279 other.entries = try self.entries.clone(allocator);1281 other.entries = try self.entries.clone(allocator);
1280 errdefer other.entries.deinit(allocator);1282 errdefer other.entries.deinit(allocator);
...@@ -1308,13 +1310,13 @@ pub fn ArrayHashMapUnmanaged(...@@ -1308,13 +1310,13 @@ pub fn ArrayHashMapUnmanaged(
1308 /// directly without going through the methods of this map.1310 /// directly without going through the methods of this map.
1309 ///1311 ///
1310 /// The time complexity of this operation is O(n).1312 /// The time complexity of this operation is O(n).
1311 pub fn reIndex(self: *Self, allocator: Allocator) !void {1313 pub fn reIndex(self: *Self, allocator: Allocator) Oom!void {
1312 if (@sizeOf(ByIndexContext) != 0)1314 if (@sizeOf(ByIndexContext) != 0)
1313 @compileError("Cannot infer context " ++ @typeName(Context) ++ ", call reIndexContext instead.");1315 @compileError("Cannot infer context " ++ @typeName(Context) ++ ", call reIndexContext instead.");
1314 return self.reIndexContext(allocator, undefined);1316 return self.reIndexContext(allocator, undefined);
1315 }1317 }
13161318
1317 pub fn reIndexContext(self: *Self, allocator: Allocator, ctx: Context) !void {1319 pub fn reIndexContext(self: *Self, allocator: Allocator, ctx: Context) Oom!void {
1318 // Recompute all hashes.1320 // Recompute all hashes.
1319 if (store_hash) {1321 if (store_hash) {
1320 for (self.keys(), self.entries.items(.hash)) |key, *hash| {1322 for (self.keys(), self.entries.items(.hash)) |key, *hash| {
...@@ -2090,7 +2092,7 @@ const IndexHeader = struct {...@@ -2090,7 +2092,7 @@ const IndexHeader = struct {
2090 return @as(u32, @intCast(self.length() - 1));2092 return @as(u32, @intCast(self.length() - 1));
2091 }2093 }
20922094
2093 fn findBitIndex(desired_capacity: usize) !u8 {2095 fn findBitIndex(desired_capacity: usize) Allocator.Error!u8 {
2094 if (desired_capacity > max_capacity) return error.OutOfMemory;2096 if (desired_capacity > max_capacity) return error.OutOfMemory;
2095 var new_bit_index = @as(u8, @intCast(std.math.log2_int_ceil(usize, desired_capacity)));2097 var new_bit_index = @as(u8, @intCast(std.math.log2_int_ceil(usize, desired_capacity)));
2096 if (desired_capacity > index_capacities[new_bit_index]) new_bit_index += 1;2098 if (desired_capacity > index_capacities[new_bit_index]) new_bit_index += 1;
...@@ -2101,7 +2103,7 @@ const IndexHeader = struct {...@@ -2101,7 +2103,7 @@ const IndexHeader = struct {
21012103
2102 /// Allocates an index header, and fills the entryIndexes array with empty.2104 /// Allocates an index header, and fills the entryIndexes array with empty.
2103 /// The distance array contents are undefined.2105 /// The distance array contents are undefined.
2104 fn alloc(allocator: Allocator, new_bit_index: u8) !*IndexHeader {2106 fn alloc(allocator: Allocator, new_bit_index: u8) Allocator.Error!*IndexHeader {
2105 const len = @as(usize, 1) << @as(math.Log2Int(usize), @intCast(new_bit_index));2107 const len = @as(usize, 1) << @as(math.Log2Int(usize), @intCast(new_bit_index));
2106 const index_size = hash_map.capacityIndexSize(new_bit_index);2108 const index_size = hash_map.capacityIndexSize(new_bit_index);
2107 const nbytes = @sizeOf(IndexHeader) + index_size * len;2109 const nbytes = @sizeOf(IndexHeader) + index_size * len;