authorgravatar for jhc@dismail.deJimmi Holst Christensen <jhc@dismail.de> 2018-10-19 23:27:16+02:00
committergravatar for jhc@dismail.deJimmi Holst Christensen <jhc@dismail.de> 2018-10-19 23:27:16+02:00
logdb3b768eabaf0ca7f83cccabfaa61eb0aa400c41
tree7cff9bfe7a108346e749a52920d9e69fe8320c9e
parent2a3fdd52ce7bd0cc577947e49bc8a3e69a34b6d0

Ran fmt on last PR


3 files changed, 232 insertions(+), 364 deletions(-)

std/mem.zig+61-73
......@@ -866,128 +866,123 @@ test "std.mem.endianSwap" {
866866 assert(endianSwap(u32, 0xDEADBEEF) == 0xEFBEADDE);
867867}
868868
869
870
871fn AsBytesReturnType(comptime P: type) type
872{
873 if(comptime !trait.isSingleItemPtr(P)) @compileError("expected single item "
874 ++ "pointer, passed " ++ @typeName(P));
869fn AsBytesReturnType(comptime P: type) type {
870 if (comptime !trait.isSingleItemPtr(P))
871 @compileError("expected single item " ++ "pointer, passed " ++ @typeName(P));
875872
876873 const size = usize(@sizeOf(meta.Child(P)));
877874 const alignment = comptime meta.alignment(P);
878 if(comptime trait.isConstPtr(P)) return *align(alignment) const [size]u8;
875
876 if (comptime trait.isConstPtr(P))
877 return *align(alignment) const [size]u8;
879878 return *align(alignment) [size]u8;
880879}
881880
882881///Given a pointer to a single item, returns a slice of the underlying bytes, preserving constness.
883pub fn asBytes(ptr: var) AsBytesReturnType(@typeOf(ptr))
884{
882pub fn asBytes(ptr: var) AsBytesReturnType(@typeOf(ptr)) {
885883 const P = @typeOf(ptr);
886884 return @ptrCast(AsBytesReturnType(P), ptr);
887885}
888886
889test "std.mem.asBytes"
890{
887test "std.mem.asBytes" {
891888 const deadbeef = u32(0xDEADBEEF);
892 const deadbeef_bytes = switch(builtin.endian)
893 {
889 const deadbeef_bytes = switch (builtin.endian) {
894890 builtin.Endian.Big => "\xDE\xAD\xBE\xEF",
895891 builtin.Endian.Little => "\xEF\xBE\xAD\xDE",
896892 };
897
893
898894 debug.assert(std.mem.eql(u8, asBytes(&deadbeef), deadbeef_bytes));
899
895
900896 var codeface = u32(0xC0DEFACE);
901 for(asBytes(&codeface).*) |*b| b.* = 0;
897 for (asBytes(&codeface).*) |*b|
898 b.* = 0;
902899 debug.assert(codeface == 0);
903
904 const S = packed struct.
905 {
900
901 const S = packed struct.{
906902 a: u8,
907903 b: u8,
908904 c: u8,
909905 d: u8,
910906 };
911
912 const inst = S.{ .a = 0xBE, .b = 0xEF, .c = 0xDE, .d = 0xA1, };
907
908 const inst = S.{
909 .a = 0xBE,
910 .b = 0xEF,
911 .c = 0xDE,
912 .d = 0xA1,
913 };
913914 debug.assert(std.mem.eql(u8, asBytes(&inst), "\xBE\xEF\xDE\xA1"));
914915}
915916
916917///Given any value, returns a copy of its bytes in an array.
917pub fn toBytes(value: var) [@sizeOf(@typeOf(value))]u8
918{
918pub fn toBytes(value: var) [@sizeOf(@typeOf(value))]u8 {
919919 return asBytes(&value).*;
920920}
921921
922test "std.mem.toBytes"
923{
922test "std.mem.toBytes" {
924923 var my_bytes = toBytes(u32(0x12345678));
925 switch(builtin.endian)
926 {
924 switch (builtin.endian) {
927925 builtin.Endian.Big => debug.assert(std.mem.eql(u8, my_bytes, "\x12\x34\x56\x78")),
928926 builtin.Endian.Little => debug.assert(std.mem.eql(u8, my_bytes, "\x78\x56\x34\x12")),
929927 }
930
928
931929 my_bytes[0] = '\x99';
932 switch(builtin.endian)
933 {
930 switch (builtin.endian) {
934931 builtin.Endian.Big => debug.assert(std.mem.eql(u8, my_bytes, "\x99\x34\x56\x78")),
935932 builtin.Endian.Little => debug.assert(std.mem.eql(u8, my_bytes, "\x99\x56\x34\x12")),
936933 }
937934}
938935
939
940fn BytesAsValueReturnType(comptime T: type, comptime B: type) type
941{
936fn BytesAsValueReturnType(comptime T: type, comptime B: type) type {
942937 const size = usize(@sizeOf(T));
943938
944 if(comptime !trait.is(builtin.TypeId.Pointer)(B) or meta.Child(B) != [size]u8)
945 {
939 if (comptime !trait.is(builtin.TypeId.Pointer)(B) or meta.Child(B) != [size]u8) {
946940 @compileError("expected *[N]u8 " ++ ", passed " ++ @typeName(B));
947941 }
948
942
949943 const alignment = comptime meta.alignment(B);
950
951 return if(comptime trait.isConstPtr(B)) *align(alignment) const T else *align(alignment) T;
944
945 return if (comptime trait.isConstPtr(B)) *align(alignment) const T else *align(alignment) T;
952946}
953947
954948///Given a pointer to an array of bytes, returns a pointer to a value of the specified type
955949/// backed by those bytes, preserving constness.
956pub fn bytesAsValue(comptime T: type, bytes: var) BytesAsValueReturnType(T, @typeOf(bytes))
957{
950pub fn bytesAsValue(comptime T: type, bytes: var) BytesAsValueReturnType(T, @typeOf(bytes)) {
958951 return @ptrCast(BytesAsValueReturnType(T, @typeOf(bytes)), bytes);
959952}
960953
961test "std.mem.bytesAsValue"
962{
954test "std.mem.bytesAsValue" {
963955 const deadbeef = u32(0xDEADBEEF);
964 const deadbeef_bytes = switch(builtin.endian)
965 {
956 const deadbeef_bytes = switch (builtin.endian) {
966957 builtin.Endian.Big => "\xDE\xAD\xBE\xEF",
967958 builtin.Endian.Little => "\xEF\xBE\xAD\xDE",
968959 };
969
960
970961 debug.assert(deadbeef == bytesAsValue(u32, &deadbeef_bytes).*);
971
972 var codeface_bytes = switch(builtin.endian)
973 {
962
963 var codeface_bytes = switch (builtin.endian) {
974964 builtin.Endian.Big => "\xC0\xDE\xFA\xCE",
975965 builtin.Endian.Little => "\xCE\xFA\xDE\xC0",
976966 };
977967 var codeface = bytesAsValue(u32, &codeface_bytes);
978968 debug.assert(codeface.* == 0xC0DEFACE);
979969 codeface.* = 0;
980 for(codeface_bytes) |b| debug.assert(b == 0);
981
982 const S = packed struct.
983 {
970 for (codeface_bytes) |b|
971 debug.assert(b == 0);
972
973 const S = packed struct.{
984974 a: u8,
985975 b: u8,
986976 c: u8,
987977 d: u8,
988978 };
989
990 const inst = S.{ .a = 0xBE, .b = 0xEF, .c = 0xDE, .d = 0xA1, };
979
980 const inst = S.{
981 .a = 0xBE,
982 .b = 0xEF,
983 .c = 0xDE,
984 .d = 0xA1,
985 };
991986 const inst_bytes = "\xBE\xEF\xDE\xA1";
992987 const inst2 = bytesAsValue(S, &inst_bytes);
993988 debug.assert(meta.eql(inst, inst2.*));
......@@ -995,50 +990,43 @@ test "std.mem.bytesAsValue"
995990
996991///Given a pointer to an array of bytes, returns a value of the specified type backed by a
997992/// copy of those bytes.
998pub fn bytesToValue(comptime T: type, bytes: var) T
999{
993pub fn bytesToValue(comptime T: type, bytes: var) T {
1000994 return bytesAsValue(T, &bytes).*;
1001995}
1002 test "std.mem.bytesToValue"
1003{
1004 const deadbeef_bytes = switch(builtin.endian)
1005 {
996test "std.mem.bytesToValue" {
997 const deadbeef_bytes = switch (builtin.endian) {
1006998 builtin.Endian.Big => "\xDE\xAD\xBE\xEF",
1007999 builtin.Endian.Little => "\xEF\xBE\xAD\xDE",
10081000 };
1009
1001
10101002 const deadbeef = bytesToValue(u32, deadbeef_bytes);
10111003 debug.assert(deadbeef == u32(0xDEADBEEF));
10121004}
10131005
1014
1015fn SubArrayPtrReturnType(comptime T: type, comptime length: usize) type
1016{
1017 if(trait.isConstPtr(T)) return *const [length]meta.Child(meta.Child(T));
1006fn SubArrayPtrReturnType(comptime T: type, comptime length: usize) type {
1007 if (trait.isConstPtr(T))
1008 return *const [length]meta.Child(meta.Child(T));
10181009 return *[length]meta.Child(meta.Child(T));
10191010}
10201011
10211012///Given a pointer to an array, returns a pointer to a portion of that array, preserving constness.
1022pub fn subArrayPtr(ptr: var, comptime start: usize, comptime length: usize)
1023 SubArrayPtrReturnType(@typeOf(ptr), length)
1024{
1013pub fn subArrayPtr(ptr: var, comptime start: usize, comptime length: usize) SubArrayPtrReturnType(@typeOf(ptr), length) {
10251014 debug.assert(start + length <= ptr.*.len);
1026
1015
10271016 const ReturnType = SubArrayPtrReturnType(@typeOf(ptr), length);
10281017 const T = meta.Child(meta.Child(@typeOf(ptr)));
10291018 return @ptrCast(ReturnType, &ptr[start]);
10301019}
10311020
1032test "std.mem.subArrayPtr"
1033{
1021test "std.mem.subArrayPtr" {
10341022 const a1 = "abcdef";
10351023 const sub1 = subArrayPtr(&a1, 2, 3);
10361024 debug.assert(std.mem.eql(u8, sub1.*, "cde"));
1037
1025
10381026 var a2 = "abcdef";
10391027 var sub2 = subArrayPtr(&a2, 2, 3);
10401028
10411029 debug.assert(std.mem.eql(u8, sub2, "cde"));
10421030 sub2[1] = 'X';
10431031 debug.assert(std.mem.eql(u8, a2, "abcXef"));
1044}
\ No newline at end of file
1032}
std/meta/index.zig+71-111
......@@ -21,7 +21,7 @@ pub fn tagName(v: var) []const u8 {
2121 unreachable;
2222 },
2323 TypeId.Union => |info| {
24 const UnionTag = if(info.tag_type) |UT| UT else @compileError("union is untagged");
24 const UnionTag = if (info.tag_type) |UT| UT else @compileError("union is untagged");
2525 const Tag = @typeInfo(UnionTag).Enum.tag_type;
2626 inline for (info.fields) |field| {
2727 if (field.enum_field.?.value == @enumToInt(UnionTag(v)))
......@@ -37,8 +37,7 @@ pub fn tagName(v: var) []const u8 {
3737
3838 unreachable;
3939 },
40 else => @compileError("expected enum, error set or union type, found '"
41 ++ @typeName(T) ++ "'"),
40 else => @compileError("expected enum, error set or union type, found '" ++ @typeName(T) ++ "'"),
4241 }
4342}
4443
......@@ -92,7 +91,7 @@ test "std.meta.bitCount" {
9291
9392pub fn alignment(comptime T: type) u29 {
9493 //@alignOf works on non-pointer types
95 const P = if(comptime trait.is(TypeId.Pointer)(T)) T else *T;
94 const P = if (comptime trait.is(TypeId.Pointer)(T)) T else *T;
9695 return @typeInfo(P).Pointer.alignment;
9796}
9897
......@@ -109,9 +108,8 @@ pub fn Child(comptime T: type) type {
109108 TypeId.Array => |info| info.child,
110109 TypeId.Pointer => |info| info.child,
111110 TypeId.Optional => |info| info.child,
112 TypeId.Promise => |info| if(info.child) |child| child else null,
113 else => @compileError("Expected promise, pointer, optional, or array type, "
114 ++ "found '" ++ @typeName(T) ++ "'"),
111 TypeId.Promise => |info| if (info.child) |child| child else null,
112 else => @compileError("Expected promise, pointer, optional, or array type, " ++ "found '" ++ @typeName(T) ++ "'"),
115113 };
116114}
117115
......@@ -128,8 +126,7 @@ pub fn containerLayout(comptime T: type) TypeInfo.ContainerLayout {
128126 TypeId.Struct => |info| info.layout,
129127 TypeId.Enum => |info| info.layout,
130128 TypeId.Union => |info| info.layout,
131 else => @compileError("Expected struct, enum or union type, found '"
132 ++ @typeName(T) ++ "'"),
129 else => @compileError("Expected struct, enum or union type, found '" ++ @typeName(T) ++ "'"),
133130 };
134131}
135132
......@@ -172,8 +169,7 @@ pub fn definitions(comptime T: type) []TypeInfo.Definition {
172169 TypeId.Struct => |info| info.defs,
173170 TypeId.Enum => |info| info.defs,
174171 TypeId.Union => |info| info.defs,
175 else => @compileError("Expected struct, enum or union type, found '"
176 ++ @typeName(T) ++ "'"),
172 else => @compileError("Expected struct, enum or union type, found '" ++ @typeName(T) ++ "'"),
177173 };
178174}
179175
......@@ -245,16 +241,14 @@ pub fn fields(comptime T: type) switch (@typeInfo(T)) {
245241 TypeId.Union => []TypeInfo.UnionField,
246242 TypeId.ErrorSet => []TypeInfo.Error,
247243 TypeId.Enum => []TypeInfo.EnumField,
248 else => @compileError("Expected struct, union, error set or enum type, found '"
249 ++ @typeName(T) ++ "'"),
244 else => @compileError("Expected struct, union, error set or enum type, found '" ++ @typeName(T) ++ "'"),
250245} {
251246 return switch (@typeInfo(T)) {
252247 TypeId.Struct => |info| info.fields,
253248 TypeId.Union => |info| info.fields,
254249 TypeId.Enum => |info| info.fields,
255250 TypeId.ErrorSet => |info| info.errors,
256 else => @compileError("Expected struct, union, error set or enum type, found '"
257 ++ @typeName(T) ++ "'"),
251 else => @compileError("Expected struct, union, error set or enum type, found '" ++ @typeName(T) ++ "'"),
258252 };
259253}
260254
......@@ -292,8 +286,7 @@ pub fn fieldInfo(comptime T: type, comptime field_name: []const u8) switch (@typ
292286 TypeId.Union => TypeInfo.UnionField,
293287 TypeId.ErrorSet => TypeInfo.Error,
294288 TypeId.Enum => TypeInfo.EnumField,
295 else => @compileError("Expected struct, union, error set or enum type, found '"
296 ++ @typeName(T) ++ "'"),
289 else => @compileError("Expected struct, union, error set or enum type, found '" ++ @typeName(T) ++ "'"),
297290} {
298291 inline for (comptime fields(T)) |field| {
299292 if (comptime mem.eql(u8, field.name, field_name))
......@@ -331,7 +324,7 @@ test "std.meta.fieldInfo" {
331324pub fn TagType(comptime T: type) type {
332325 return switch (@typeInfo(T)) {
333326 TypeId.Enum => |info| info.tag_type,
334 TypeId.Union => |info| if(info.tag_type) |Tag| Tag else null,
327 TypeId.Union => |info| if (info.tag_type) |Tag| Tag else null,
335328 else => @compileError("expected enum or union type, found '" ++ @typeName(T) ++ "'"),
336329 };
337330}
......@@ -350,104 +343,80 @@ test "std.meta.TagType" {
350343 debug.assert(TagType(U) == E);
351344}
352345
353
354
355346///Returns the active tag of a tagged union
356pub fn activeTag(u: var) @TagType(@typeOf(u))
357{
347pub fn activeTag(u: var) @TagType(@typeOf(u)) {
358348 const T = @typeOf(u);
359349 return @TagType(T)(u);
360350}
361351
362test "std.meta.activeTag"
363{
364 const UE = enum.
365 {
352test "std.meta.activeTag" {
353 const UE = enum.{
366354 Int,
367355 Float,
368356 };
369
370 const U = union(UE).
371 {
357
358 const U = union(UE).{
372359 Int: u32,
373360 Float: f32,
374361 };
375
376 var u = U.{ .Int = 32, };
362
363 var u = U.{ .Int = 32 };
377364 debug.assert(activeTag(u) == UE.Int);
378
379 u = U.{ .Float = 112.9876, };
380 debug.assert(activeTag(u) == UE.Float);
381365
366 u = U.{ .Float = 112.9876 };
367 debug.assert(activeTag(u) == UE.Float);
382368}
383369
384370///Compares two of any type for equality. Containers are compared on a field-by-field basis,
385371/// where possible. Pointers are not followed.
386pub fn eql(a: var, b: @typeOf(a)) bool
387{
372pub fn eql(a: var, b: @typeOf(a)) bool {
388373 const T = @typeOf(a);
389
390 switch(@typeId(T))
391 {
392 builtin.TypeId.Struct =>
393 {
374
375 switch (@typeId(T)) {
376 builtin.TypeId.Struct => {
394377 const info = @typeInfo(T).Struct;
395
396 inline for(info.fields) |field_info|
397 {
398 if(!eql(@field(a, field_info.name),
399 @field(b, field_info.name))) return false;
378
379 inline for (info.fields) |field_info| {
380 if (!eql(@field(a, field_info.name), @field(b, field_info.name))) return false;
400381 }
401382 return true;
402383 },
403 builtin.TypeId.ErrorUnion =>
404 {
405 if(a) |a_p|
406 {
407 if(b) |b_p| return eql(a_p, b_p) else |_| return false;
408 }
409 else |a_e|
410 {
411 if(b) |_| return false else |b_e| return a_e == b_e;
384 builtin.TypeId.ErrorUnion => {
385 if (a) |a_p| {
386 if (b) |b_p| return eql(a_p, b_p) else |_| return false;
387 } else |a_e| {
388 if (b) |_| return false else |b_e| return a_e == b_e;
412389 }
413390 },
414 builtin.TypeId.Union =>
415 {
391 builtin.TypeId.Union => {
416392 const info = @typeInfo(T).Union;
417
418 if(info.tag_type) |_|
419 {
393
394 if (info.tag_type) |_| {
420395 const tag_a = activeTag(a);
421396 const tag_b = activeTag(b);
422 if(tag_a != tag_b) return false;
423
424 inline for(info.fields) |field_info|
425 {
397 if (tag_a != tag_b) return false;
398
399 inline for (info.fields) |field_info| {
426400 const enum_field = field_info.enum_field.?;
427 if(enum_field.value == @enumToInt(tag_a))
428 {
429 return eql(@field(a, enum_field.name),
430 @field(b, enum_field.name));
401 if (enum_field.value == @enumToInt(tag_a)) {
402 return eql(@field(a, enum_field.name), @field(b, enum_field.name));
431403 }
432404 }
433405 return false;
434406 }
435
407
436408 @compileError("cannot compare untagged union type " ++ @typeName(T));
437409 },
438 builtin.TypeId.Array =>
439 {
440 if(a.len != b.len) return false;
441 for(a) |e, i| if(!eql(e, b[i])) return false;
410 builtin.TypeId.Array => {
411 if (a.len != b.len) return false;
412 for (a) |e, i|
413 if (!eql(e, b[i])) return false;
442414 return true;
443415 },
444 builtin.TypeId.Pointer =>
445 {
416 builtin.TypeId.Pointer => {
446417 const info = @typeInfo(T).Pointer;
447 switch(info.size)
448 {
449 builtin.TypeInfo.Pointer.Size.One,
450 builtin.TypeInfo.Pointer.Size.Many => return a == b,
418 switch (info.size) {
419 builtin.TypeInfo.Pointer.Size.One, builtin.TypeInfo.Pointer.Size.Many => return a == b,
451420 builtin.TypeInfo.Pointer.Size.Slice => return a.ptr == b.ptr and a.len == b.len,
452421 }
453422 },
......@@ -455,71 +424,62 @@ pub fn eql(a: var, b: @typeOf(a)) bool
455424 }
456425}
457426
458
459test "std.meta.eql"
460{
461 const S = struct.
462 {
427test "std.meta.eql" {
428 const S = struct.{
463429 a: u32,
464430 b: f64,
465431 c: [5]u8,
466432 };
467
468 const U = union(enum).
469 {
433
434 const U = union(enum).{
470435 s: S,
471436 f: f32,
472437 };
473
474 const s_1 = S.
475 {
438
439 const s_1 = S.{
476440 .a = 134,
477441 .b = 123.3,
478442 .c = "12345",
479443 };
480
481 const s_2 = S.
482 {
444
445 const s_2 = S.{
483446 .a = 1,
484447 .b = 123.3,
485448 .c = "54321",
486449 };
487
488 const s_3 = S.
489 {
450
451 const s_3 = S.{
490452 .a = 134,
491453 .b = 123.3,
492454 .c = "12345",
493455 };
494
495 const u_1 = U.{ .f = 24, };
496 const u_2 = U.{ .s = s_1, };
497 const u_3 = U.{ .f = 24, };
498
456
457 const u_1 = U.{ .f = 24 };
458 const u_2 = U.{ .s = s_1 };
459 const u_3 = U.{ .f = 24 };
460
499461 debug.assert(eql(s_1, s_3));
500462 debug.assert(eql(&s_1, &s_1));
501463 debug.assert(!eql(&s_1, &s_3));
502464 debug.assert(eql(u_1, u_3));
503465 debug.assert(!eql(u_1, u_2));
504
466
505467 var a1 = "abcdef";
506468 var a2 = "abcdef";
507469 var a3 = "ghijkl";
508
470
509471 debug.assert(eql(a1, a2));
510472 debug.assert(!eql(a1, a3));
511473 debug.assert(!eql(a1[0..], a2[0..]));
512
513 const EU = struct.
514 {
515 fn tst(err: bool) !u8
516 {
517 if(err) return error.Error;
474
475 const EU = struct.{
476 fn tst(err: bool) !u8 {
477 if (err) return error.Error;
518478 return u8(5);
519479 }
520480 };
521
481
522482 debug.assert(eql(EU.tst(true), EU.tst(true)));
523483 debug.assert(eql(EU.tst(false), EU.tst(false)));
524484 debug.assert(!eql(EU.tst(false), EU.tst(true)));
525}
\ No newline at end of file
485}
std/meta/trait.zig+100-180
......@@ -8,101 +8,80 @@ const meta = @import("index.zig");
88
99//This is necessary if we want to return generic functions directly because of how the
1010// the type erasure works. see: #1375
11fn traitFnWorkaround(comptime T: type) bool
12{
11fn traitFnWorkaround(comptime T: type) bool {
1312 return false;
1413}
1514
1615pub const TraitFn = @typeOf(traitFnWorkaround);
17
1816///
1917
2018//////Trait generators
2119
2220//Need TraitList because compiler can't do varargs at comptime yet
2321pub const TraitList = []const TraitFn;
24pub fn multiTrait(comptime traits: TraitList) TraitFn
25{
26 const Closure = struct.
27 {
28 pub fn trait(comptime T: type) bool
29 {
30 inline for(traits) |t| if(!t(T)) return false;
22pub fn multiTrait(comptime traits: TraitList) TraitFn {
23 const Closure = struct.{
24 pub fn trait(comptime T: type) bool {
25 inline for (traits) |t|
26 if (!t(T)) return false;
3127 return true;
3228 }
3329 };
3430 return Closure.trait;
3531}
3632
37test "std.meta.trait.multiTrait"
38{
39 const Vector2 = struct.
40 {
33test "std.meta.trait.multiTrait" {
34 const Vector2 = struct.{
4135 const MyType = @This();
42
36
4337 x: u8,
4438 y: u8,
45
46 pub fn add(self: MyType, other: MyType) MyType
47 {
48 return MyType.
49 {
39
40 pub fn add(self: MyType, other: MyType) MyType {
41 return MyType.{
5042 .x = self.x + other.x,
5143 .y = self.y + other.y,
5244 };
5345 }
5446 };
55
56 const isVector = multiTrait
57 (
58 TraitList.
59 {
60 hasFn("add"),
61 hasField("x"),
62 hasField("y"),
63 }
64 );
47
48 const isVector = multiTrait(TraitList.{
49 hasFn("add"),
50 hasField("x"),
51 hasField("y"),
52 });
6553 debug.assert(isVector(Vector2));
6654 debug.assert(!isVector(u8));
6755}
6856
6957///
70
71pub fn hasDef(comptime name: []const u8) TraitFn
72{
73 const Closure = struct.
74 {
75 pub fn trait(comptime T: type) bool
76 {
58pub fn hasDef(comptime name: []const u8) TraitFn {
59 const Closure = struct.{
60 pub fn trait(comptime T: type) bool {
7761 const info = @typeInfo(T);
78 const defs = switch(info)
79 {
62 const defs = switch (info) {
8063 builtin.TypeId.Struct => |s| s.defs,
8164 builtin.TypeId.Union => |u| u.defs,
8265 builtin.TypeId.Enum => |e| e.defs,
8366 else => return false,
8467 };
8568
86 inline for(defs) |def|
87 {
88 if(mem.eql(u8, def.name, name)) return def.is_pub;
69 inline for (defs) |def| {
70 if (mem.eql(u8, def.name, name)) return def.is_pub;
8971 }
90
72
9173 return false;
9274 }
9375 };
9476 return Closure.trait;
9577}
9678
97test "std.meta.trait.hasDef"
98{
99 const TestStruct = struct.
100 {
79test "std.meta.trait.hasDef" {
80 const TestStruct = struct.{
10181 pub const value = u8(16);
10282 };
103
104 const TestStructFail = struct.
105 {
83
84 const TestStructFail = struct.{
10685 const value = u8(16);
10786 };
10887
......@@ -115,13 +94,10 @@ test "std.meta.trait.hasDef"
11594}
11695
11796///
118pub fn hasFn(comptime name: []const u8) TraitFn
119{
120 const Closure = struct.
121 {
122 pub fn trait(comptime T: type) bool
123 {
124 if(!comptime hasDef(name)(T)) return false;
97pub fn hasFn(comptime name: []const u8) TraitFn {
98 const Closure = struct.{
99 pub fn trait(comptime T: type) bool {
100 if (!comptime hasDef(name)(T)) return false;
125101 const DefType = @typeOf(@field(T, name));
126102 const def_type_id = @typeId(DefType);
127103 return def_type_id == builtin.TypeId.Fn;
......@@ -130,10 +106,8 @@ pub fn hasFn(comptime name: []const u8) TraitFn
130106 return Closure.trait;
131107}
132108
133test "std.meta.trait.hasFn"
134{
135 const TestStruct = struct.
136 {
109test "std.meta.trait.hasFn" {
110 const TestStruct = struct.{
137111 pub fn useless() void {}
138112 };
139113
......@@ -143,36 +117,29 @@ test "std.meta.trait.hasFn"
143117}
144118
145119///
146pub fn hasField(comptime name: []const u8) TraitFn
147{
148 const Closure = struct.
149 {
150 pub fn trait(comptime T: type) bool
151 {
120pub fn hasField(comptime name: []const u8) TraitFn {
121 const Closure = struct.{
122 pub fn trait(comptime T: type) bool {
152123 const info = @typeInfo(T);
153 const fields = switch(info)
154 {
124 const fields = switch (info) {
155125 builtin.TypeId.Struct => |s| s.fields,
156126 builtin.TypeId.Union => |u| u.fields,
157127 builtin.TypeId.Enum => |e| e.fields,
158128 else => return false,
159129 };
160130
161 inline for(fields) |field|
162 {
163 if(mem.eql(u8, field.name, name)) return true;
131 inline for (fields) |field| {
132 if (mem.eql(u8, field.name, name)) return true;
164133 }
165
134
166135 return false;
167136 }
168137 };
169138 return Closure.trait;
170139}
171140
172test "std.meta.trait.hasField"
173{
174 const TestStruct = struct.
175 {
141test "std.meta.trait.hasField" {
142 const TestStruct = struct.{
176143 value: u32,
177144 };
178145
......@@ -184,21 +151,16 @@ test "std.meta.trait.hasField"
184151}
185152
186153///
187
188pub fn is(comptime id: builtin.TypeId) TraitFn
189{
190 const Closure = struct.
191 {
192 pub fn trait(comptime T: type) bool
193 {
154pub fn is(comptime id: builtin.TypeId) TraitFn {
155 const Closure = struct.{
156 pub fn trait(comptime T: type) bool {
194157 return id == @typeId(T);
195158 }
196159 };
197160 return Closure.trait;
198161}
199162
200test "std.meta.trait.is"
201{
163test "std.meta.trait.is" {
202164 debug.assert(is(builtin.TypeId.Int)(u8));
203165 debug.assert(!is(builtin.TypeId.Int)(f32));
204166 debug.assert(is(builtin.TypeId.Pointer)(*u8));
......@@ -207,39 +169,31 @@ test "std.meta.trait.is"
207169}
208170
209171///
210
211pub fn isPtrTo(comptime id: builtin.TypeId) TraitFn
212{
213 const Closure = struct.
214 {
215 pub fn trait(comptime T: type) bool
216 {
217 if(!comptime isSingleItemPtr(T)) return false;
172pub fn isPtrTo(comptime id: builtin.TypeId) TraitFn {
173 const Closure = struct.{
174 pub fn trait(comptime T: type) bool {
175 if (!comptime isSingleItemPtr(T)) return false;
218176 return id == @typeId(meta.Child(T));
219177 }
220178 };
221179 return Closure.trait;
222180}
223181
224test "std.meta.trait.isPtrTo"
225{
182test "std.meta.trait.isPtrTo" {
226183 debug.assert(!isPtrTo(builtin.TypeId.Struct)(struct.{}));
227184 debug.assert(isPtrTo(builtin.TypeId.Struct)(*struct.{}));
228185 debug.assert(!isPtrTo(builtin.TypeId.Struct)(**struct.{}));
229186}
230187
231
232188///////////Strait trait Fns
233189
234190//@TODO:
235191// Somewhat limited since we can't apply this logic to normal variables, fields, or
236192// Fns yet. Should be isExternType?
237pub fn isExtern(comptime T: type) bool
238{
193pub fn isExtern(comptime T: type) bool {
239194 const Extern = builtin.TypeInfo.ContainerLayout.Extern;
240195 const info = @typeInfo(T);
241 return switch(info)
242 {
196 return switch (info) {
243197 builtin.TypeId.Struct => |s| s.layout == Extern,
244198 builtin.TypeId.Union => |u| u.layout == Extern,
245199 builtin.TypeId.Enum => |e| e.layout == Extern,
......@@ -247,8 +201,7 @@ pub fn isExtern(comptime T: type) bool
247201 };
248202}
249203
250test "std.meta.trait.isExtern"
251{
204test "std.meta.trait.isExtern" {
252205 const TestExStruct = extern struct.{};
253206 const TestStruct = struct.{};
254207
......@@ -258,13 +211,10 @@ test "std.meta.trait.isExtern"
258211}
259212
260213///
261
262pub fn isPacked(comptime T: type) bool
263{
214pub fn isPacked(comptime T: type) bool {
264215 const Packed = builtin.TypeInfo.ContainerLayout.Packed;
265216 const info = @typeInfo(T);
266 return switch(info)
267 {
217 return switch (info) {
268218 builtin.TypeId.Struct => |s| s.layout == Packed,
269219 builtin.TypeId.Union => |u| u.layout == Packed,
270220 builtin.TypeId.Enum => |e| e.layout == Packed,
......@@ -272,8 +222,7 @@ pub fn isPacked(comptime T: type) bool
272222 };
273223}
274224
275test "std.meta.trait.isPacked"
276{
225test "std.meta.trait.isPacked" {
277226 const TestPStruct = packed struct.{};
278227 const TestStruct = struct.{};
279228
......@@ -283,19 +232,15 @@ test "std.meta.trait.isPacked"
283232}
284233
285234///
286
287pub fn isSingleItemPtr(comptime T: type) bool
288{
289 if(comptime is(builtin.TypeId.Pointer)(T))
290 {
235pub fn isSingleItemPtr(comptime T: type) bool {
236 if (comptime is(builtin.TypeId.Pointer)(T)) {
291237 const info = @typeInfo(T);
292238 return info.Pointer.size == builtin.TypeInfo.Pointer.Size.One;
293239 }
294240 return false;
295241}
296242
297test "std.meta.trait.isSingleItemPtr"
298{
243test "std.meta.trait.isSingleItemPtr" {
299244 const array = []u8.{0} ** 10;
300245 debug.assert(isSingleItemPtr(@typeOf(&array[0])));
301246 debug.assert(!isSingleItemPtr(@typeOf(array)));
......@@ -303,19 +248,15 @@ test "std.meta.trait.isSingleItemPtr"
303248}
304249
305250///
306
307pub fn isManyItemPtr(comptime T: type) bool
308{
309 if(comptime is(builtin.TypeId.Pointer)(T))
310 {
251pub fn isManyItemPtr(comptime T: type) bool {
252 if (comptime is(builtin.TypeId.Pointer)(T)) {
311253 const info = @typeInfo(T);
312254 return info.Pointer.size == builtin.TypeInfo.Pointer.Size.Many;
313255 }
314256 return false;
315257}
316258
317test "std.meta.trait.isManyItemPtr"
318{
259test "std.meta.trait.isManyItemPtr" {
319260 const array = []u8.{0} ** 10;
320261 const mip = @ptrCast([*]const u8, &array[0]);
321262 debug.assert(isManyItemPtr(@typeOf(mip)));
......@@ -324,19 +265,15 @@ test "std.meta.trait.isManyItemPtr"
324265}
325266
326267///
327
328pub fn isSlice(comptime T: type) bool
329{
330 if(comptime is(builtin.TypeId.Pointer)(T))
331 {
268pub fn isSlice(comptime T: type) bool {
269 if (comptime is(builtin.TypeId.Pointer)(T)) {
332270 const info = @typeInfo(T);
333271 return info.Pointer.size == builtin.TypeInfo.Pointer.Size.Slice;
334272 }
335273 return false;
336274}
337275
338test "std.meta.trait.isSlice"
339{
276test "std.meta.trait.isSlice" {
340277 const array = []u8.{0} ** 10;
341278 debug.assert(isSlice(@typeOf(array[0..])));
342279 debug.assert(!isSlice(@typeOf(array)));
......@@ -344,27 +281,22 @@ test "std.meta.trait.isSlice"
344281}
345282
346283///
347
348pub fn isIndexable(comptime T: type) bool
349{
350 if(comptime is(builtin.TypeId.Pointer)(T))
351 {
352 const info = @typeInfo(T);
353 if(info.Pointer.size == builtin.TypeInfo.Pointer.Size.One)
354 {
355 if(comptime is(builtin.TypeId.Array)(meta.Child(T))) return true;
356 return false;
357 }
358 return true;
359 }
360 return comptime is(builtin.TypeId.Array)(T);
284pub fn isIndexable(comptime T: type) bool {
285 if (comptime is(builtin.TypeId.Pointer)(T)) {
286 const info = @typeInfo(T);
287 if (info.Pointer.size == builtin.TypeInfo.Pointer.Size.One) {
288 if (comptime is(builtin.TypeId.Array)(meta.Child(T))) return true;
289 return false;
290 }
291 return true;
292 }
293 return comptime is(builtin.TypeId.Array)(T);
361294}
362295
363test "std.meta.trait.isIndexable"
364{
296test "std.meta.trait.isIndexable" {
365297 const array = []u8.{0} ** 10;
366298 const slice = array[0..];
367
299
368300 debug.assert(isIndexable(@typeOf(array)));
369301 debug.assert(isIndexable(@typeOf(&array)));
370302 debug.assert(isIndexable(@typeOf(slice)));
......@@ -372,26 +304,18 @@ test "std.meta.trait.isIndexable"
372304}
373305
374306///
375
376pub fn isNumber(comptime T: type) bool
377{
378 return switch(@typeId(T))
379 {
380 builtin.TypeId.Int,
381 builtin.TypeId.Float,
382 builtin.TypeId.ComptimeInt,
383 builtin.TypeId.ComptimeFloat => true,
307pub fn isNumber(comptime T: type) bool {
308 return switch (@typeId(T)) {
309 builtin.TypeId.Int, builtin.TypeId.Float, builtin.TypeId.ComptimeInt, builtin.TypeId.ComptimeFloat => true,
384310 else => false,
385311 };
386312}
387313
388test "std.meta.trait.isNumber"
389{
390 const NotANumber = struct.
391 {
314test "std.meta.trait.isNumber" {
315 const NotANumber = struct.{
392316 number: u8,
393317 };
394
318
395319 debug.assert(isNumber(u32));
396320 debug.assert(isNumber(f32));
397321 debug.assert(isNumber(u64));
......@@ -402,16 +326,13 @@ test "std.meta.trait.isNumber"
402326}
403327
404328///
405
406pub fn isConstPtr(comptime T: type) bool
407{
408 if(!comptime is(builtin.TypeId.Pointer)(T)) return false;
329pub fn isConstPtr(comptime T: type) bool {
330 if (!comptime is(builtin.TypeId.Pointer)(T)) return false;
409331 const info = @typeInfo(T);
410332 return info.Pointer.is_const;
411333}
412334
413test "std.meta.trait.isConstPtr"
414{
335test "std.meta.trait.isConstPtr" {
415336 var t = u8(0);
416337 const c = u8(0);
417338 debug.assert(isConstPtr(*const @typeOf(t)));
......@@ -421,12 +342,9 @@ test "std.meta.trait.isConstPtr"
421342}
422343
423344///
424
425pub fn isContainer(comptime T: type) bool
426{
345pub fn isContainer(comptime T: type) bool {
427346 const info = @typeInfo(T);
428 return switch(info)
429 {
347 return switch (info) {
430348 builtin.TypeId.Struct => true,
431349 builtin.TypeId.Union => true,
432350 builtin.TypeId.Enum => true,
......@@ -434,16 +352,18 @@ pub fn isContainer(comptime T: type) bool
434352 };
435353}
436354
437test "std.meta.trait.isContainer"
438{
355test "std.meta.trait.isContainer" {
439356 const TestStruct = struct.{};
440 const TestUnion = union.{ a: void, };
441 const TestEnum = enum.{ A, B, };
442
357 const TestUnion = union.{
358 a: void,
359 };
360 const TestEnum = enum.{
361 A,
362 B,
363 };
364
443365 debug.assert(isContainer(TestStruct));
444366 debug.assert(isContainer(TestUnion));
445367 debug.assert(isContainer(TestEnum));
446368 debug.assert(!isContainer(u8));
447369}
448
449///
\ No newline at end of file