Commit fdae5f5a07

xackus <14938807+xackus@users.noreply.github.com>
2020-02-20 20:01:52
implement bytesAsSlice, sliceAsBytes
1 parent e381a42
Changed files (1)
lib
lib/std/mem.zig
@@ -1486,6 +1486,76 @@ test "bytesToValue" {
     testing.expect(deadbeef == @as(u32, 0xDEADBEEF));
 }
 
+//TODO copy also is_volatile, etc. I tried to use @typeInfo, modify child type, use @Type, but ran into issues.
+fn BytesAsSliceReturnType(comptime T: type, comptime bytesType: type) type {
+    if (comptime !trait.isSlice(bytesType) or comptime meta.Child(bytesType) != u8) {
+        @compileError("expected []u8, passed " ++ @typeName(bytesType));
+    }
+
+    const alignment = comptime meta.alignment(bytesType);
+
+    return if (comptime trait.isConstPtr(bytesType)) []align(alignment) const T else []align(alignment) T;
+}
+
+pub fn bytesAsSlice(comptime T: type, bytes: var) BytesAsSliceReturnType(T, @TypeOf(bytes)) {
+    // let's not give an undefined pointer to @ptrCast
+    // it may be equal to zero and fail a null check
+    if (bytes.len == 0) {
+        return &[0]T{};
+    }
+
+    const bytesType = @TypeOf(bytes);
+    const alignment = comptime meta.alignment(bytesType);
+
+    const castTarget = if (comptime trait.isConstPtr(bytesType)) [*]align(alignment) const T else [*]align(alignment) T;
+
+    return @ptrCast(castTarget, bytes.ptr)[0..@divExact(bytes.len, @sizeOf(T))];
+}
+
+test "bytesAsSlice" {
+    const bytes = [_]u8{ 0xDE, 0xAD, 0xBE, 0xEF };
+    const slice = bytesAsSlice(u16, bytes[0..]);
+    testing.expect(slice.len == 2);
+    testing.expect(bigToNative(u16, slice[0]) == 0xDEAD);
+    testing.expect(bigToNative(u16, slice[1]) == 0xBEEF);
+}
+
+//TODO copy also is_volatile, etc. I tried to use @typeInfo, modify child type, use @Type, but ran into issues.
+fn SliceAsBytesReturnType(comptime sliceType: type) type {
+    if (comptime !trait.isSlice(sliceType)) {
+        @compileError("expected []T, passed " ++ @typeName(sliceType));
+    }
+
+    const alignment = comptime meta.alignment(sliceType);
+
+    return if (comptime trait.isConstPtr(sliceType)) []align(alignment) const u8 else []align(alignment) u8;
+}
+
+pub fn sliceAsBytes(slice: var) SliceAsBytesReturnType(@TypeOf(slice)) {
+    // let's not give an undefined pointer to @ptrCast
+    // it may be equal to zero and fail a null check
+    if (slice.len == 0) {
+        return &[0]u8{};
+    }
+
+    const sliceType = @TypeOf(slice);
+    const alignment = comptime meta.alignment(sliceType);
+
+    const castTarget = if (comptime trait.isConstPtr(sliceType)) [*]align(alignment) const u8 else [*]align(alignment) u8;
+
+    return @ptrCast(castTarget, slice.ptr)[0 .. slice.len * @sizeOf(comptime meta.Child(sliceType))];
+}
+
+test "sliceAsBytes" {
+    const bytes = [_]u16{ 0xDEAD, 0xBEEF };
+    const slice = sliceAsBytes(bytes[0..]);
+    testing.expect(slice.len == 4);
+    testing.expect(eql(u8, slice, switch (builtin.endian) {
+        .Big => "\xDE\xAD\xBE\xEF",
+        .Little => "\xAD\xDE\xEF\xBE",
+    }));
+}
+
 fn SubArrayPtrReturnType(comptime T: type, comptime length: usize) type {
     if (trait.isConstPtr(T))
         return *const [length]meta.Child(meta.Child(T));