| ... | @@ -104,7 +104,7 @@ pub fn Child(comptime T: type) type { | ... | @@ -104,7 +104,7 @@ pub fn Child(comptime T: type) type { |
| 104 | .Array => |info| info.child, | 104 | .Array => |info| info.child, |
| 105 | .Pointer => |info| info.child, | 105 | .Pointer => |info| info.child, |
| 106 | .Optional => |info| info.child, | 106 | .Optional => |info| info.child, |
| 107 | else => @compileError("Expected pointer, optional, or array type, " ++ "found '" ++ @typeName(T) ++ "'"), | 107 | else => @compileError("Expected pointer, optional, or array type, found '" ++ @typeName(T) ++ "'"), |
| 108 | }; | 108 | }; |
| 109 | } | 109 | } |
| 110 | | 110 | |
| ... | @@ -115,16 +115,39 @@ test "std.meta.Child" { | ... | @@ -115,16 +115,39 @@ test "std.meta.Child" { |
| 115 | testing.expect(Child(?u8) == u8); | 115 | testing.expect(Child(?u8) == u8); |
| 116 | } | 116 | } |
| 117 | | 117 | |
| | 118 | /// Given a "memory span" type, returns the "element type". |
| | 119 | pub fn Elem(comptime T: type) type { |
| | 120 | switch (@typeInfo(T)) { |
| | 121 | .Array => |info| return info.child, |
| | 122 | .Pointer => |info| switch (info.size) { |
| | 123 | .One => switch (@typeInfo(info.child)) { |
| | 124 | .Array => |array_info| return array_info.child, |
| | 125 | else => {}, |
| | 126 | }, |
| | 127 | .Many, .C, .Slice => return info.child, |
| | 128 | }, |
| | 129 | else => {}, |
| | 130 | } |
| | 131 | @compileError("Expected pointer, slice, or array, found '" ++ @typeName(T) ++ "'"); |
| | 132 | } |
| | 133 | |
| | 134 | test "std.meta.Elem" { |
| | 135 | testing.expect(Elem([1]u8) == u8); |
| | 136 | testing.expect(Elem([*]u8) == u8); |
| | 137 | testing.expect(Elem([]u8) == u8); |
| | 138 | testing.expect(Elem(*[10]u8) == u8); |
| | 139 | } |
| | 140 | |
| 118 | /// Given a type which can have a sentinel e.g. `[:0]u8`, returns the sentinel value, | 141 | /// Given a type which can have a sentinel e.g. `[:0]u8`, returns the sentinel value, |
| 119 | /// or `null` if there is not one. | 142 | /// or `null` if there is not one. |
| 120 | /// Types which cannot possibly have a sentinel will be a compile error. | 143 | /// Types which cannot possibly have a sentinel will be a compile error. |
| 121 | pub fn sentinel(comptime T: type) ?Child(T) { | 144 | pub fn sentinel(comptime T: type) ?Elem(T) { |
| 122 | switch (@typeInfo(T)) { | 145 | switch (@typeInfo(T)) { |
| 123 | .Array => |info| return info.sentinel, | 146 | .Array => |info| return info.sentinel, |
| 124 | .Pointer => |info| { | 147 | .Pointer => |info| { |
| 125 | switch (info.size) { | 148 | switch (info.size) { |
| 126 | .Many, .Slice => return info.sentinel, | 149 | .Many, .Slice => return info.sentinel, |
| 127 | .One => switch (info.child) { | 150 | .One => switch (@typeInfo(info.child)) { |
| 128 | .Array => |array_info| return array_info.sentinel, | 151 | .Array => |array_info| return array_info.sentinel, |
| 129 | else => {}, | 152 | else => {}, |
| 130 | }, | 153 | }, |
| ... | @@ -137,6 +160,11 @@ pub fn sentinel(comptime T: type) ?Child(T) { | ... | @@ -137,6 +160,11 @@ pub fn sentinel(comptime T: type) ?Child(T) { |
| 137 | } | 160 | } |
| 138 | | 161 | |
| 139 | test "std.meta.sentinel" { | 162 | test "std.meta.sentinel" { |
| | 163 | testSentinel(); |
| | 164 | comptime testSentinel(); |
| | 165 | } |
| | 166 | |
| | 167 | fn testSentinel() void { |
| 140 | testing.expectEqual(@as(u8, 0), sentinel([:0]u8).?); | 168 | testing.expectEqual(@as(u8, 0), sentinel([:0]u8).?); |
| 141 | testing.expectEqual(@as(u8, 0), sentinel([*:0]u8).?); | 169 | testing.expectEqual(@as(u8, 0), sentinel([*:0]u8).?); |
| 142 | testing.expectEqual(@as(u8, 0), sentinel([5:0]u8).?); | 170 | testing.expectEqual(@as(u8, 0), sentinel([5:0]u8).?); |