diff --git a/lib/std/mem.zig b/lib/std/mem.zig index 8900e53f70..8d05be4117 100644 --- a/lib/std/mem.zig +++ b/lib/std/mem.zig @@ -1911,7 +1911,7 @@ pub fn writePackedInt(comptime T: type, bytes: []u8, bit_offset: usize, value: T /// Any extra bytes in buffer after writing the integer are set to zero. To /// avoid the branch to check for extra buffer bytes, use writeIntLittle /// instead. -pub fn writeIntSliceLittle(comptime T: type, buffer: []u8, value: T) void { +fn writeIntSliceLittleNative(comptime T: type, buffer: []u8, value: T) void { assert(buffer.len >= @divExact(@typeInfo(T).Int.bits, 8)); if (@typeInfo(T).Int.bits == 0) { @@ -1921,21 +1921,27 @@ pub fn writeIntSliceLittle(comptime T: type, buffer: []u8, value: T) void { buffer[0] = @as(u8, @bitCast(value)); return; } - // TODO I want to call writeIntLittle here but comptime eval facilities aren't good enough - const uint = std.meta.Int(.unsigned, @typeInfo(T).Int.bits); - var bits = @as(uint, @bitCast(value)); - for (buffer) |*b| { - b.* = @as(u8, @truncate(bits)); - bits >>= 8; - } + + const write_end = @divExact(@typeInfo(T).Int.bits, 8); + @as(*align(1) T, @ptrCast(buffer)).* = value; + @memset(buffer[write_end..], 0); } +fn writeIntSliceLittleForeign(comptime T: type, buffer: []u8, value: T) void { + return writeIntSliceLittleNative(T, buffer, @byteSwap(value)); +} + +pub const writeIntSliceLittle = switch (native_endian) { + .Little => writeIntSliceLittleNative, + .Big => writeIntSliceLittleForeign, +}; + /// Writes a twos-complement big-endian integer to memory. /// Asserts that buffer.len >= @typeInfo(T).Int.bits / 8. /// The bit count of T must be divisible by 8. /// Any extra bytes in buffer before writing the integer are set to zero. To /// avoid the branch to check for extra buffer bytes, use writeIntBig instead. -pub fn writeIntSliceBig(comptime T: type, buffer: []u8, value: T) void { +fn writeIntSliceBigNative(comptime T: type, buffer: []u8, value: T) void { assert(buffer.len >= @divExact(@typeInfo(T).Int.bits, 8)); if (@typeInfo(T).Int.bits == 0) { @@ -1946,25 +1952,28 @@ pub fn writeIntSliceBig(comptime T: type, buffer: []u8, value: T) void { return; } - // TODO I want to call writeIntBig here but comptime eval facilities aren't good enough - const uint = std.meta.Int(.unsigned, @typeInfo(T).Int.bits); - var bits = @as(uint, @bitCast(value)); - var index: usize = buffer.len; - while (index != 0) { - index -= 1; - buffer[index] = @as(u8, @truncate(bits)); - bits >>= 8; - } + const write_start = buffer.len - @divExact(@typeInfo(T).Int.bits, 8); + @memset(buffer[0..write_start], 0); + @as(*align(1) T, @ptrCast(buffer[write_start..])).* = value; } +fn writeIntSliceBigForeign(comptime T: type, buffer: []u8, value: T) void { + return writeIntSliceBigNative(T, buffer, @byteSwap(value)); +} + +pub const writeIntSliceBig = switch (native_endian) { + .Little => writeIntSliceBigForeign, + .Big => writeIntSliceBigNative, +}; + pub const writeIntSliceNative = switch (native_endian) { - .Little => writeIntSliceLittle, - .Big => writeIntSliceBig, + .Little => writeIntSliceLittleNative, + .Big => writeIntSliceBigNative, }; pub const writeIntSliceForeign = switch (native_endian) { - .Little => writeIntSliceBig, - .Big => writeIntSliceLittle, + .Little => writeIntSliceBigForeign, + .Big => writeIntSliceLittleForeign, }; /// Writes a twos-complement integer to memory, with the specified endianness.