aboutsummaryrefslogtreecommitdiff
path: root/lib/std/meta
diff options
context:
space:
mode:
authorMartin Wickham <spexguy070@gmail.com>2021-03-06 18:25:04 -0600
committerAndrew Kelley <andrew@ziglang.org>2021-03-18 14:05:01 -0700
commit96ae451bbe78cd35a62e00e3fb48a32f24ebd315 (patch)
treea11930cd240610a90eb486510055075fe18decc4 /lib/std/meta
parent5e5b35f1077d5cf77a89aee5dde939de35f2e247 (diff)
downloadzig-96ae451bbe78cd35a62e00e3fb48a32f24ebd315.tar.gz
zig-96ae451bbe78cd35a62e00e3fb48a32f24ebd315.zip
Add some enum utilities
Diffstat (limited to 'lib/std/meta')
-rw-r--r--lib/std/meta/trait.zig78
1 files changed, 78 insertions, 0 deletions
diff --git a/lib/std/meta/trait.zig b/lib/std/meta/trait.zig
index e67f9b9bc4..481bfe212b 100644
--- a/lib/std/meta/trait.zig
+++ b/lib/std/meta/trait.zig
@@ -408,6 +408,84 @@ test "std.meta.trait.isTuple" {
testing.expect(isTuple(@TypeOf(t3)));
}
+/// Returns true if the passed type will coerce to []const u8.
+/// Any of the following are considered strings:
+/// ```
+/// []const u8, [:S]const u8, *const [N]u8, *const [N:S]u8,
+/// []u8, [:S]u8, *[:S]u8, *[N:S]u8.
+/// ```
+/// These types are not considered strings:
+/// ```
+/// u8, [N]u8, [*]const u8, [*:0]const u8,
+/// [*]const [N]u8, []const u16, []const i8,
+/// *const u8, ?[]const u8, ?*const [N]u8.
+/// ```
+pub fn isZigString(comptime T: type) bool {
+ comptime {
+ // Only pointer types can be strings, no optionals
+ const info = @typeInfo(T);
+ if (info != .Pointer) return false;
+
+ const ptr = &info.Pointer;
+ // Check for CV qualifiers that would prevent coerction to []const u8
+ if (ptr.is_volatile or ptr.is_allowzero) return false;
+
+ // If it's already a slice, simple check.
+ if (ptr.size == .Slice) {
+ return ptr.child == u8;
+ }
+
+ // Otherwise check if it's an array type that coerces to slice.
+ if (ptr.size == .One) {
+ const child = @typeInfo(ptr.child);
+ if (child == .Array) {
+ const arr = &child.Array;
+ return arr.child == u8;
+ }
+ }
+
+ return false;
+ }
+}
+
+test "std.meta.trait.isZigString" {
+ testing.expect(isZigString([]const u8));
+ testing.expect(isZigString([]u8));
+ testing.expect(isZigString([:0]const u8));
+ testing.expect(isZigString([:0]u8));
+ testing.expect(isZigString([:5]const u8));
+ testing.expect(isZigString([:5]u8));
+ testing.expect(isZigString(*const [0]u8));
+ testing.expect(isZigString(*[0]u8));
+ testing.expect(isZigString(*const [0:0]u8));
+ testing.expect(isZigString(*[0:0]u8));
+ testing.expect(isZigString(*const [0:5]u8));
+ testing.expect(isZigString(*[0:5]u8));
+ testing.expect(isZigString(*const [10]u8));
+ testing.expect(isZigString(*[10]u8));
+ testing.expect(isZigString(*const [10:0]u8));
+ testing.expect(isZigString(*[10:0]u8));
+ testing.expect(isZigString(*const [10:5]u8));
+ testing.expect(isZigString(*[10:5]u8));
+
+ testing.expect(!isZigString(u8));
+ testing.expect(!isZigString([4]u8));
+ testing.expect(!isZigString([4:0]u8));
+ testing.expect(!isZigString([*]const u8));
+ testing.expect(!isZigString([*]const [4]u8));
+ testing.expect(!isZigString([*c]const u8));
+ testing.expect(!isZigString([*c]const [4]u8));
+ testing.expect(!isZigString([*:0]const u8));
+ testing.expect(!isZigString([*:0]const u8));
+ testing.expect(!isZigString(*[]const u8));
+ testing.expect(!isZigString(?[]const u8));
+ testing.expect(!isZigString(?*const [4]u8));
+ testing.expect(!isZigString([]allowzero u8));
+ testing.expect(!isZigString([]volatile u8));
+ testing.expect(!isZigString(*allowzero [4]u8));
+ testing.expect(!isZigString(*volatile [4]u8));
+}
+
pub fn hasDecls(comptime T: type, comptime names: anytype) bool {
inline for (names) |name| {
if (!@hasDecl(T, name))