| author | |
| committer | |
| log | 7d8a556ba92474d78b465b30c8d5df64e9775d93 |
| tree | 497f7266c1a24ed35df05cd3ac7f327228d59aef |
| parent | 1aca3dd6e07a9285d9455a527f3ee676f15afb1b |
| signature |
Minor fix for `Allocator.remap` and `mem.bytesAsSlice` for zero-sized types3 files changed, 51 insertions(+), 1 deletions(-)
lib/std/json/static_test.zig+16| ... | @@ -925,3 +925,19 @@ test "parse at comptime" { | ... | @@ -925,3 +925,19 @@ test "parse at comptime" { |
| 925 | }; | 925 | }; |
| 926 | comptime testing.expectEqual(@as(u64, 9999), config.uptime) catch unreachable; | 926 | comptime testing.expectEqual(@as(u64, 9999), config.uptime) catch unreachable; |
| 927 | } | 927 | } |
| 928 | |||
| 929 | test "parse with zero-bit field" { | ||
| 930 | const str = | ||
| 931 | \\{ | ||
| 932 | \\ "a": ["a", "a"], | ||
| 933 | \\ "b": "a" | ||
| 934 | \\} | ||
| 935 | ; | ||
| 936 | const ZeroSizedEnum = enum { a }; | ||
| 937 | try testing.expectEqual(0, @sizeOf(ZeroSizedEnum)); | ||
| 938 | |||
| 939 | const Inner = struct { a: []const ZeroSizedEnum, b: ZeroSizedEnum }; | ||
| 940 | const expected: Inner = .{ .a = &.{ .a, .a }, .b = .a }; | ||
| 941 | |||
| 942 | try testAllParseFunctions(Inner, expected, str); | ||
| 943 | } |
lib/std/mem.zig+27-1| ... | @@ -228,6 +228,18 @@ test "Allocator.resize" { | ... | @@ -228,6 +228,18 @@ test "Allocator.resize" { |
| 228 | } | 228 | } |
| 229 | } | 229 | } |
| 230 | 230 | ||
| 231 | test "Allocator alloc and remap with zero-bit type" { | ||
| 232 | var values = try testing.allocator.alloc(void, 10); | ||
| 233 | defer testing.allocator.free(values); | ||
| 234 | |||
| 235 | try testing.expectEqual(10, values.len); | ||
| 236 | const remaped = testing.allocator.remap(values, 200); | ||
| 237 | try testing.expect(remaped != null); | ||
| 238 | |||
| 239 | values = remaped.?; | ||
| 240 | try testing.expectEqual(200, values.len); | ||
| 241 | } | ||
| 242 | |||
| 231 | /// Copy all of source into dest at position 0. | 243 | /// Copy all of source into dest at position 0. |
| 232 | /// dest.len must be >= source.len. | 244 | /// dest.len must be >= source.len. |
| 233 | /// If the slices overlap, dest.ptr must be <= src.ptr. | 245 | /// If the slices overlap, dest.ptr must be <= src.ptr. |
| ... | @@ -4207,10 +4219,11 @@ fn BytesAsSliceReturnType(comptime T: type, comptime bytesType: type) type { | ... | @@ -4207,10 +4219,11 @@ fn BytesAsSliceReturnType(comptime T: type, comptime bytesType: type) type { |
| 4207 | 4219 | ||
| 4208 | /// Given a slice of bytes, returns a slice of the specified type | 4220 | /// Given a slice of bytes, returns a slice of the specified type |
| 4209 | /// backed by those bytes, preserving pointer attributes. | 4221 | /// backed by those bytes, preserving pointer attributes. |
| 4222 | /// If `T` is zero-bytes sized, the returned slice has a len of zero. | ||
| 4210 | pub fn bytesAsSlice(comptime T: type, bytes: anytype) BytesAsSliceReturnType(T, @TypeOf(bytes)) { | 4223 | pub fn bytesAsSlice(comptime T: type, bytes: anytype) BytesAsSliceReturnType(T, @TypeOf(bytes)) { |
| 4211 | // let's not give an undefined pointer to @ptrCast | 4224 | // let's not give an undefined pointer to @ptrCast |
| 4212 | // it may be equal to zero and fail a null check | 4225 | // it may be equal to zero and fail a null check |
| 4213 | if (bytes.len == 0) { | 4226 | if (bytes.len == 0 or @sizeOf(T) == 0) { |
| 4214 | return &[0]T{}; | 4227 | return &[0]T{}; |
| 4215 | } | 4228 | } |
| 4216 | 4229 | ||
| ... | @@ -4288,6 +4301,19 @@ test "bytesAsSlice preserves pointer attributes" { | ... | @@ -4288,6 +4301,19 @@ test "bytesAsSlice preserves pointer attributes" { |
| 4288 | try testing.expectEqual(in.alignment, out.alignment); | 4301 | try testing.expectEqual(in.alignment, out.alignment); |
| 4289 | } | 4302 | } |
| 4290 | 4303 | ||
| 4304 | test "bytesAsSlice with zero-bit element type" { | ||
| 4305 | { | ||
| 4306 | const bytes = [_]u8{}; | ||
| 4307 | const slice = bytesAsSlice(void, &bytes); | ||
| 4308 | try testing.expectEqual(0, slice.len); | ||
| 4309 | } | ||
| 4310 | { | ||
| 4311 | const bytes = [_]u8{ 0x01, 0x02, 0x03, 0x04 }; | ||
| 4312 | const slice = bytesAsSlice(u0, &bytes); | ||
| 4313 | try testing.expectEqual(0, slice.len); | ||
| 4314 | } | ||
| 4315 | } | ||
| 4316 | |||
| 4291 | fn SliceAsBytesReturnType(comptime Slice: type) type { | 4317 | fn SliceAsBytesReturnType(comptime Slice: type) type { |
| 4292 | return CopyPtrAttrs(Slice, .slice, u8); | 4318 | return CopyPtrAttrs(Slice, .slice, u8); |
| 4293 | } | 4319 | } |
lib/std/mem/Allocator.zig+8| ... | @@ -312,12 +312,15 @@ pub fn resize(self: Allocator, allocation: anytype, new_len: usize) bool { | ... | @@ -312,12 +312,15 @@ pub fn resize(self: Allocator, allocation: anytype, new_len: usize) bool { |
| 312 | /// unless `new_len` is also 0, in which case `allocation` is returned. | 312 | /// unless `new_len` is also 0, in which case `allocation` is returned. |
| 313 | /// | 313 | /// |
| 314 | /// `new_len` may be zero, in which case the allocation is freed. | 314 | /// `new_len` may be zero, in which case the allocation is freed. |
| 315 | /// | ||
| 316 | /// If the allocation's elements' type is zero bytes sized, `allocation.len` is set to `new_len`. | ||
| 315 | pub fn remap(self: Allocator, allocation: anytype, new_len: usize) t: { | 317 | pub fn remap(self: Allocator, allocation: anytype, new_len: usize) t: { |
| 316 | const Slice = @typeInfo(@TypeOf(allocation)).pointer; | 318 | const Slice = @typeInfo(@TypeOf(allocation)).pointer; |
| 317 | break :t ?[]align(Slice.alignment) Slice.child; | 319 | break :t ?[]align(Slice.alignment) Slice.child; |
| 318 | } { | 320 | } { |
| 319 | const Slice = @typeInfo(@TypeOf(allocation)).pointer; | 321 | const Slice = @typeInfo(@TypeOf(allocation)).pointer; |
| 320 | const T = Slice.child; | 322 | const T = Slice.child; |
| 323 | |||
| 321 | const alignment = Slice.alignment; | 324 | const alignment = Slice.alignment; |
| 322 | if (new_len == 0) { | 325 | if (new_len == 0) { |
| 323 | self.free(allocation); | 326 | self.free(allocation); |
| ... | @@ -326,6 +329,11 @@ pub fn remap(self: Allocator, allocation: anytype, new_len: usize) t: { | ... | @@ -326,6 +329,11 @@ pub fn remap(self: Allocator, allocation: anytype, new_len: usize) t: { |
| 326 | if (allocation.len == 0) { | 329 | if (allocation.len == 0) { |
| 327 | return null; | 330 | return null; |
| 328 | } | 331 | } |
| 332 | if (@sizeOf(T) == 0) { | ||
| 333 | var new_memory = allocation; | ||
| 334 | new_memory.len = new_len; | ||
| 335 | return new_memory; | ||
| 336 | } | ||
| 329 | const old_memory = mem.sliceAsBytes(allocation); | 337 | const old_memory = mem.sliceAsBytes(allocation); |
| 330 | // I would like to use saturating multiplication here, but LLVM cannot lower it | 338 | // I would like to use saturating multiplication here, but LLVM cannot lower it |
| 331 | // on WebAssembly: https://github.com/ziglang/zig/issues/9660 | 339 | // on WebAssembly: https://github.com/ziglang/zig/issues/9660 |