improve std lib code for the new semantics
This commit is contained in:
parent
8d0ac6dc4d
commit
8ea0a00f40
|
@ -1829,21 +1829,19 @@ fn SliceAsBytesReturnType(comptime sliceType: type) type {
|
|||
}
|
||||
|
||||
pub fn sliceAsBytes(slice: var) SliceAsBytesReturnType(@TypeOf(slice)) {
|
||||
const actualSlice = if (comptime trait.isPtrTo(.Array)(@TypeOf(slice))) slice[0..] else slice;
|
||||
const actualSliceTypeInfo = @typeInfo(@TypeOf(actualSlice)).Pointer;
|
||||
const Slice = @TypeOf(slice);
|
||||
|
||||
// let's not give an undefined pointer to @ptrCast
|
||||
// it may be equal to zero and fail a null check
|
||||
if (actualSlice.len == 0 and actualSliceTypeInfo.sentinel == null) {
|
||||
if (slice.len == 0 and comptime meta.sentinel(Slice) == null) {
|
||||
return &[0]u8{};
|
||||
}
|
||||
|
||||
const sliceType = @TypeOf(actualSlice);
|
||||
const alignment = comptime meta.alignment(sliceType);
|
||||
const alignment = comptime meta.alignment(Slice);
|
||||
|
||||
const castTarget = if (comptime trait.isConstPtr(sliceType)) [*]align(alignment) const u8 else [*]align(alignment) u8;
|
||||
const cast_target = if (comptime trait.isConstPtr(Slice)) [*]align(alignment) const u8 else [*]align(alignment) u8;
|
||||
|
||||
return @ptrCast(castTarget, actualSlice.ptr)[0 .. actualSlice.len * @sizeOf(comptime meta.Child(sliceType))];
|
||||
return @ptrCast(cast_target, slice)[0 .. slice.len * @sizeOf(meta.Child(Slice))];
|
||||
}
|
||||
|
||||
test "sliceAsBytes" {
|
||||
|
|
|
@ -115,30 +115,37 @@ test "std.meta.Child" {
|
|||
testing.expect(Child(?u8) == u8);
|
||||
}
|
||||
|
||||
/// Given a type with a sentinel e.g. `[:0]u8`, returns the sentinel
|
||||
pub fn Sentinel(comptime T: type) Child(T) {
|
||||
// comptime asserts that ptr has a sentinel
|
||||
/// Given a type which can have a sentinel e.g. `[:0]u8`, returns the sentinel value,
|
||||
/// or `null` if there is not one.
|
||||
/// Types which cannot possibly have a sentinel will be a compile error.
|
||||
pub fn sentinel(comptime T: type) ?Child(T) {
|
||||
switch (@typeInfo(T)) {
|
||||
.Array => |arrayInfo| {
|
||||
return comptime arrayInfo.sentinel.?;
|
||||
},
|
||||
.Pointer => |ptrInfo| {
|
||||
switch (ptrInfo.size) {
|
||||
.Many, .Slice => {
|
||||
return comptime ptrInfo.sentinel.?;
|
||||
.Array => |info| return info.sentinel,
|
||||
.Pointer => |info| {
|
||||
switch (info.size) {
|
||||
.Many, .Slice => return info.sentinel,
|
||||
.One => switch (info.child) {
|
||||
.Array => |array_info| return array_info.sentinel,
|
||||
else => {},
|
||||
},
|
||||
else => {},
|
||||
}
|
||||
},
|
||||
else => {},
|
||||
}
|
||||
@compileError("not a sentinel type, found '" ++ @typeName(T) ++ "'");
|
||||
@compileError("type '" ++ @typeName(T) ++ "' cannot possibly have a sentinel");
|
||||
}
|
||||
|
||||
test "std.meta.Sentinel" {
|
||||
testing.expectEqual(@as(u8, 0), Sentinel([:0]u8));
|
||||
testing.expectEqual(@as(u8, 0), Sentinel([*:0]u8));
|
||||
testing.expectEqual(@as(u8, 0), Sentinel([5:0]u8));
|
||||
test "std.meta.sentinel" {
|
||||
testing.expectEqual(@as(u8, 0), sentinel([:0]u8).?);
|
||||
testing.expectEqual(@as(u8, 0), sentinel([*:0]u8).?);
|
||||
testing.expectEqual(@as(u8, 0), sentinel([5:0]u8).?);
|
||||
testing.expectEqual(@as(u8, 0), sentinel(*const [5:0]u8).?);
|
||||
|
||||
testing.expect(sentinel([]u8) == null);
|
||||
testing.expect(sentinel([*]u8) == null);
|
||||
testing.expect(sentinel([5]u8) == null);
|
||||
testing.expect(sentinel(*const [5]u8) == null);
|
||||
}
|
||||
|
||||
pub fn containerLayout(comptime T: type) TypeInfo.ContainerLayout {
|
||||
|
|
|
@ -1744,20 +1744,18 @@ fn writeEscapedString(buf: []u8, s: []const u8) void {
|
|||
// Returns either a string literal or a slice of `buf`.
|
||||
fn escapeChar(c: u8, char_buf: *[4]u8) []const u8 {
|
||||
return switch (c) {
|
||||
'\"' => "\\\""[0..],
|
||||
'\'' => "\\'"[0..],
|
||||
'\\' => "\\\\"[0..],
|
||||
'\n' => "\\n"[0..],
|
||||
'\r' => "\\r"[0..],
|
||||
'\t' => "\\t"[0..],
|
||||
else => {
|
||||
// Handle the remaining escapes Zig doesn't support by turning them
|
||||
// into their respective hex representation
|
||||
if (std.ascii.isCntrl(c))
|
||||
return std.fmt.bufPrint(char_buf[0..], "\\x{x:0<2}", .{c}) catch unreachable
|
||||
else
|
||||
return std.fmt.bufPrint(char_buf[0..], "{c}", .{c}) catch unreachable;
|
||||
},
|
||||
'\"' => "\\\"",
|
||||
'\'' => "\\'",
|
||||
'\\' => "\\\\",
|
||||
'\n' => "\\n",
|
||||
'\r' => "\\r",
|
||||
'\t' => "\\t",
|
||||
// Handle the remaining escapes Zig doesn't support by turning them
|
||||
// into their respective hex representation
|
||||
else => if (std.ascii.isCntrl(c))
|
||||
std.fmt.bufPrint(char_buf, "\\x{x:0<2}", .{c}) catch unreachable
|
||||
else
|
||||
std.fmt.bufPrint(char_buf, "{c}", .{c}) catch unreachable,
|
||||
};
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user