breaking API changes to all readInt/writeInt functions & more
* add `@bswap` builtin function. See #767 * comptime evaluation facilities are improved to be able to handle a `@ptrCast` with a backing array. * `@truncate` allows "truncating" a u0 value to any integer type, and the result is always comptime known to be `0`. * when specifying pointer alignment in a type expression, the alignment value of pointers which do not have addresses at runtime is ignored, and always has the default/ABI alignment * threw in a fix to freebsd/x86_64.zig to update syntax from language changes * some improvements are pending #863 closes #638 closes #1733 std lib API changes * io.InStream().readIntNe renamed to readIntNative * io.InStream().readIntLe renamed to readIntLittle * io.InStream().readIntBe renamed to readIntBig * introduced io.InStream().readIntForeign * io.InStream().readInt has parameter order changed * io.InStream().readVarInt has parameter order changed * io.InStream().writeIntNe renamed to writeIntNative * introduced io.InStream().writeIntForeign * io.InStream().writeIntLe renamed to writeIntLittle * io.InStream().writeIntBe renamed to writeIntBig * io.InStream().writeInt has parameter order changed * mem.readInt has different parameters and semantics * introduced mem.readIntNative * introduced mem.readIntForeign * mem.readIntBE renamed to mem.readIntBig and different API * mem.readIntLE renamed to mem.readIntLittle and different API * introduced mem.readIntSliceNative * introduced mem.readIntSliceForeign * introduced mem.readIntSliceLittle * introduced mem.readIntSliceBig * introduced mem.readIntSlice * mem.writeInt has different parameters and semantics * introduced mem.writeIntNative * introduced mem.writeIntForeign * mem.writeIntBE renamed to mem.readIntBig and different semantics * mem.writeIntLE renamed to mem.readIntLittle and different semantics * introduced mem.writeIntSliceForeign * introduced mem.writeIntSliceNative * introduced mem.writeIntSliceBig * introduced mem.writeIntSliceLittle * introduced mem.writeIntSlice * removed mem.endianSwapIfLe * removed mem.endianSwapIfBe * removed mem.endianSwapIf * added mem.littleToNative * added mem.bigToNative * added mem.toNative * added mem.nativeTo * added mem.nativeToLittle * added mem.nativeToBig
This commit is contained in:
parent
634d11ab28
commit
b883bc873d
@ -5312,6 +5312,15 @@ comptime {
|
|||||||
</p>
|
</p>
|
||||||
{#header_close#}
|
{#header_close#}
|
||||||
|
|
||||||
|
{#header_open|@bswap#}
|
||||||
|
<pre>{#syntax#}@swap(comptime T: type, value: T) T{#endsyntax#}</pre>
|
||||||
|
<p>{#syntax#}T{#endsyntax#} must be an integer type with bit count evenly divisible by 8.</p>
|
||||||
|
<p>
|
||||||
|
Swaps the byte order of the integer. This converts a big endian integer to a little endian integer,
|
||||||
|
and converts a little endian integer to a big endian integer.
|
||||||
|
</p>
|
||||||
|
{#header_close#}
|
||||||
|
|
||||||
{#header_open|@bytesToSlice#}
|
{#header_open|@bytesToSlice#}
|
||||||
<pre>{#syntax#}@bytesToSlice(comptime Element: type, bytes: []u8) []Element{#endsyntax#}</pre>
|
<pre>{#syntax#}@bytesToSlice(comptime Element: type, bytes: []u8) []Element{#endsyntax#}</pre>
|
||||||
<p>
|
<p>
|
||||||
|
@ -15,7 +15,7 @@ pub fn main() !void {
|
|||||||
std.debug.warn("unable to seed random number generator: {}", err);
|
std.debug.warn("unable to seed random number generator: {}", err);
|
||||||
return err;
|
return err;
|
||||||
};
|
};
|
||||||
const seed = std.mem.readInt(seed_bytes, u64, builtin.Endian.Big);
|
const seed = std.mem.readIntNative(u64, &seed_bytes);
|
||||||
var prng = std.rand.DefaultPrng.init(seed);
|
var prng = std.rand.DefaultPrng.init(seed);
|
||||||
|
|
||||||
const answer = prng.random.range(u8, 0, 100) + 1;
|
const answer = prng.random.range(u8, 0, 100) + 1;
|
||||||
|
@ -55,7 +55,7 @@ pub const ZigCompiler = struct {
|
|||||||
|
|
||||||
var seed_bytes: [@sizeOf(u64)]u8 = undefined;
|
var seed_bytes: [@sizeOf(u64)]u8 = undefined;
|
||||||
try std.os.getRandomBytes(seed_bytes[0..]);
|
try std.os.getRandomBytes(seed_bytes[0..]);
|
||||||
const seed = std.mem.readInt(seed_bytes, u64, builtin.Endian.Big);
|
const seed = mem.readIntNative(u64, &seed_bytes);
|
||||||
|
|
||||||
return ZigCompiler{
|
return ZigCompiler{
|
||||||
.loop = loop,
|
.loop = loop,
|
||||||
|
@ -1415,6 +1415,7 @@ enum BuiltinFnId {
|
|||||||
BuiltinFnIdErrorReturnTrace,
|
BuiltinFnIdErrorReturnTrace,
|
||||||
BuiltinFnIdAtomicRmw,
|
BuiltinFnIdAtomicRmw,
|
||||||
BuiltinFnIdAtomicLoad,
|
BuiltinFnIdAtomicLoad,
|
||||||
|
BuiltinFnIdBswap,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct BuiltinFnEntry {
|
struct BuiltinFnEntry {
|
||||||
@ -1487,6 +1488,7 @@ enum ZigLLVMFnId {
|
|||||||
ZigLLVMFnIdFloor,
|
ZigLLVMFnIdFloor,
|
||||||
ZigLLVMFnIdCeil,
|
ZigLLVMFnIdCeil,
|
||||||
ZigLLVMFnIdSqrt,
|
ZigLLVMFnIdSqrt,
|
||||||
|
ZigLLVMFnIdBswap,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum AddSubMul {
|
enum AddSubMul {
|
||||||
@ -1516,6 +1518,9 @@ struct ZigLLVMFnKey {
|
|||||||
uint32_t bit_count;
|
uint32_t bit_count;
|
||||||
bool is_signed;
|
bool is_signed;
|
||||||
} overflow_arithmetic;
|
} overflow_arithmetic;
|
||||||
|
struct {
|
||||||
|
uint32_t bit_count;
|
||||||
|
} bswap;
|
||||||
} data;
|
} data;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -2158,6 +2163,7 @@ enum IrInstructionId {
|
|||||||
IrInstructionIdMergeErrRetTraces,
|
IrInstructionIdMergeErrRetTraces,
|
||||||
IrInstructionIdMarkErrRetTracePtr,
|
IrInstructionIdMarkErrRetTracePtr,
|
||||||
IrInstructionIdSqrt,
|
IrInstructionIdSqrt,
|
||||||
|
IrInstructionIdBswap,
|
||||||
IrInstructionIdErrSetCast,
|
IrInstructionIdErrSetCast,
|
||||||
IrInstructionIdToBytes,
|
IrInstructionIdToBytes,
|
||||||
IrInstructionIdFromBytes,
|
IrInstructionIdFromBytes,
|
||||||
@ -3251,6 +3257,13 @@ struct IrInstructionCheckRuntimeScope {
|
|||||||
IrInstruction *is_comptime;
|
IrInstruction *is_comptime;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct IrInstructionBswap {
|
||||||
|
IrInstruction base;
|
||||||
|
|
||||||
|
IrInstruction *type;
|
||||||
|
IrInstruction *op;
|
||||||
|
};
|
||||||
|
|
||||||
static const size_t slice_ptr_index = 0;
|
static const size_t slice_ptr_index = 0;
|
||||||
static const size_t slice_len_index = 1;
|
static const size_t slice_len_index = 1;
|
||||||
|
|
||||||
|
@ -401,7 +401,8 @@ ZigType *get_promise_type(CodeGen *g, ZigType *result_type) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_const,
|
ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_const,
|
||||||
bool is_volatile, PtrLen ptr_len, uint32_t byte_alignment, uint32_t bit_offset_in_host, uint32_t host_int_bytes)
|
bool is_volatile, PtrLen ptr_len, uint32_t byte_alignment,
|
||||||
|
uint32_t bit_offset_in_host, uint32_t host_int_bytes)
|
||||||
{
|
{
|
||||||
assert(!type_is_invalid(child_type));
|
assert(!type_is_invalid(child_type));
|
||||||
assert(ptr_len == PtrLenSingle || child_type->id != ZigTypeIdOpaque);
|
assert(ptr_len == PtrLenSingle || child_type->id != ZigTypeIdOpaque);
|
||||||
@ -6110,6 +6111,8 @@ uint32_t zig_llvm_fn_key_hash(ZigLLVMFnKey x) {
|
|||||||
return (uint32_t)(x.data.floating.bit_count) * (uint32_t)1953839089;
|
return (uint32_t)(x.data.floating.bit_count) * (uint32_t)1953839089;
|
||||||
case ZigLLVMFnIdSqrt:
|
case ZigLLVMFnIdSqrt:
|
||||||
return (uint32_t)(x.data.floating.bit_count) * (uint32_t)2225366385;
|
return (uint32_t)(x.data.floating.bit_count) * (uint32_t)2225366385;
|
||||||
|
case ZigLLVMFnIdBswap:
|
||||||
|
return (uint32_t)(x.data.bswap.bit_count) * (uint32_t)3661994335;
|
||||||
case ZigLLVMFnIdOverflowArithmetic:
|
case ZigLLVMFnIdOverflowArithmetic:
|
||||||
return ((uint32_t)(x.data.overflow_arithmetic.bit_count) * 87135777) +
|
return ((uint32_t)(x.data.overflow_arithmetic.bit_count) * 87135777) +
|
||||||
((uint32_t)(x.data.overflow_arithmetic.add_sub_mul) * 31640542) +
|
((uint32_t)(x.data.overflow_arithmetic.add_sub_mul) * 31640542) +
|
||||||
@ -6128,6 +6131,8 @@ bool zig_llvm_fn_key_eql(ZigLLVMFnKey a, ZigLLVMFnKey b) {
|
|||||||
return a.data.clz.bit_count == b.data.clz.bit_count;
|
return a.data.clz.bit_count == b.data.clz.bit_count;
|
||||||
case ZigLLVMFnIdPopCount:
|
case ZigLLVMFnIdPopCount:
|
||||||
return a.data.pop_count.bit_count == b.data.pop_count.bit_count;
|
return a.data.pop_count.bit_count == b.data.pop_count.bit_count;
|
||||||
|
case ZigLLVMFnIdBswap:
|
||||||
|
return a.data.bswap.bit_count == b.data.bswap.bit_count;
|
||||||
case ZigLLVMFnIdFloor:
|
case ZigLLVMFnIdFloor:
|
||||||
case ZigLLVMFnIdCeil:
|
case ZigLLVMFnIdCeil:
|
||||||
case ZigLLVMFnIdSqrt:
|
case ZigLLVMFnIdSqrt:
|
||||||
|
@ -3814,6 +3814,11 @@ static LLVMValueRef get_int_builtin_fn(CodeGen *g, ZigType *int_type, BuiltinFnI
|
|||||||
n_args = 1;
|
n_args = 1;
|
||||||
key.id = ZigLLVMFnIdPopCount;
|
key.id = ZigLLVMFnIdPopCount;
|
||||||
key.data.pop_count.bit_count = (uint32_t)int_type->data.integral.bit_count;
|
key.data.pop_count.bit_count = (uint32_t)int_type->data.integral.bit_count;
|
||||||
|
} else if (fn_id == BuiltinFnIdBswap) {
|
||||||
|
fn_name = "bswap";
|
||||||
|
n_args = 1;
|
||||||
|
key.id = ZigLLVMFnIdBswap;
|
||||||
|
key.data.bswap.bit_count = (uint32_t)int_type->data.integral.bit_count;
|
||||||
} else {
|
} else {
|
||||||
zig_unreachable();
|
zig_unreachable();
|
||||||
}
|
}
|
||||||
@ -5098,6 +5103,29 @@ static LLVMValueRef ir_render_sqrt(CodeGen *g, IrExecutable *executable, IrInstr
|
|||||||
return LLVMBuildCall(g->builder, fn_val, &op, 1, "");
|
return LLVMBuildCall(g->builder, fn_val, &op, 1, "");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static LLVMValueRef ir_render_bswap(CodeGen *g, IrExecutable *executable, IrInstructionBswap *instruction) {
|
||||||
|
LLVMValueRef op = ir_llvm_value(g, instruction->op);
|
||||||
|
ZigType *int_type = instruction->base.value.type;
|
||||||
|
assert(int_type->id == ZigTypeIdInt);
|
||||||
|
if (int_type->data.integral.bit_count % 16 == 0) {
|
||||||
|
LLVMValueRef fn_val = get_int_builtin_fn(g, instruction->base.value.type, BuiltinFnIdBswap);
|
||||||
|
return LLVMBuildCall(g->builder, fn_val, &op, 1, "");
|
||||||
|
}
|
||||||
|
// Not an even number of bytes, so we zext 1 byte, then bswap, shift right 1 byte, truncate
|
||||||
|
ZigType *extended_type = get_int_type(g, int_type->data.integral.is_signed,
|
||||||
|
int_type->data.integral.bit_count + 8);
|
||||||
|
// aabbcc
|
||||||
|
LLVMValueRef extended = LLVMBuildZExt(g->builder, op, extended_type->type_ref, "");
|
||||||
|
// 00aabbcc
|
||||||
|
LLVMValueRef fn_val = get_int_builtin_fn(g, extended_type, BuiltinFnIdBswap);
|
||||||
|
LLVMValueRef swapped = LLVMBuildCall(g->builder, fn_val, &extended, 1, "");
|
||||||
|
// ccbbaa00
|
||||||
|
LLVMValueRef shifted = ZigLLVMBuildLShrExact(g->builder, swapped,
|
||||||
|
LLVMConstInt(extended_type->type_ref, 8, false), "");
|
||||||
|
// 00ccbbaa
|
||||||
|
return LLVMBuildTrunc(g->builder, shifted, int_type->type_ref, "");
|
||||||
|
}
|
||||||
|
|
||||||
static void set_debug_location(CodeGen *g, IrInstruction *instruction) {
|
static void set_debug_location(CodeGen *g, IrInstruction *instruction) {
|
||||||
AstNode *source_node = instruction->source_node;
|
AstNode *source_node = instruction->source_node;
|
||||||
Scope *scope = instruction->scope;
|
Scope *scope = instruction->scope;
|
||||||
@ -5335,6 +5363,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
|
|||||||
return ir_render_mark_err_ret_trace_ptr(g, executable, (IrInstructionMarkErrRetTracePtr *)instruction);
|
return ir_render_mark_err_ret_trace_ptr(g, executable, (IrInstructionMarkErrRetTracePtr *)instruction);
|
||||||
case IrInstructionIdSqrt:
|
case IrInstructionIdSqrt:
|
||||||
return ir_render_sqrt(g, executable, (IrInstructionSqrt *)instruction);
|
return ir_render_sqrt(g, executable, (IrInstructionSqrt *)instruction);
|
||||||
|
case IrInstructionIdBswap:
|
||||||
|
return ir_render_bswap(g, executable, (IrInstructionBswap *)instruction);
|
||||||
}
|
}
|
||||||
zig_unreachable();
|
zig_unreachable();
|
||||||
}
|
}
|
||||||
@ -6757,6 +6787,7 @@ static void define_builtin_fns(CodeGen *g) {
|
|||||||
create_builtin_fn(g, BuiltinFnIdToBytes, "sliceToBytes", 1);
|
create_builtin_fn(g, BuiltinFnIdToBytes, "sliceToBytes", 1);
|
||||||
create_builtin_fn(g, BuiltinFnIdFromBytes, "bytesToSlice", 2);
|
create_builtin_fn(g, BuiltinFnIdFromBytes, "bytesToSlice", 2);
|
||||||
create_builtin_fn(g, BuiltinFnIdThis, "This", 0);
|
create_builtin_fn(g, BuiltinFnIdThis, "This", 0);
|
||||||
|
create_builtin_fn(g, BuiltinFnIdBswap, "bswap", 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char *bool_to_str(bool b) {
|
static const char *bool_to_str(bool b) {
|
||||||
|
156
src/ir.cpp
156
src/ir.cpp
@ -856,6 +856,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionSqrt *) {
|
|||||||
return IrInstructionIdSqrt;
|
return IrInstructionIdSqrt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static constexpr IrInstructionId ir_instruction_id(IrInstructionBswap *) {
|
||||||
|
return IrInstructionIdBswap;
|
||||||
|
}
|
||||||
|
|
||||||
static constexpr IrInstructionId ir_instruction_id(IrInstructionCheckRuntimeScope *) {
|
static constexpr IrInstructionId ir_instruction_id(IrInstructionCheckRuntimeScope *) {
|
||||||
return IrInstructionIdCheckRuntimeScope;
|
return IrInstructionIdCheckRuntimeScope;
|
||||||
}
|
}
|
||||||
@ -2705,6 +2709,17 @@ static IrInstruction *ir_build_sqrt(IrBuilder *irb, Scope *scope, AstNode *sourc
|
|||||||
return &instruction->base;
|
return &instruction->base;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static IrInstruction *ir_build_bswap(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *type, IrInstruction *op) {
|
||||||
|
IrInstructionBswap *instruction = ir_build_instruction<IrInstructionBswap>(irb, scope, source_node);
|
||||||
|
instruction->type = type;
|
||||||
|
instruction->op = op;
|
||||||
|
|
||||||
|
if (type != nullptr) ir_ref_instruction(type, irb->current_basic_block);
|
||||||
|
ir_ref_instruction(op, irb->current_basic_block);
|
||||||
|
|
||||||
|
return &instruction->base;
|
||||||
|
}
|
||||||
|
|
||||||
static IrInstruction *ir_build_check_runtime_scope(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *scope_is_comptime, IrInstruction *is_comptime) {
|
static IrInstruction *ir_build_check_runtime_scope(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *scope_is_comptime, IrInstruction *is_comptime) {
|
||||||
IrInstructionCheckRuntimeScope *instruction = ir_build_instruction<IrInstructionCheckRuntimeScope>(irb, scope, source_node);
|
IrInstructionCheckRuntimeScope *instruction = ir_build_instruction<IrInstructionCheckRuntimeScope>(irb, scope, source_node);
|
||||||
instruction->scope_is_comptime = scope_is_comptime;
|
instruction->scope_is_comptime = scope_is_comptime;
|
||||||
@ -4689,6 +4704,21 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
|
|||||||
IrInstruction *result = ir_build_enum_to_int(irb, scope, node, arg0_value);
|
IrInstruction *result = ir_build_enum_to_int(irb, scope, node, arg0_value);
|
||||||
return ir_lval_wrap(irb, scope, result, lval);
|
return ir_lval_wrap(irb, scope, result, lval);
|
||||||
}
|
}
|
||||||
|
case BuiltinFnIdBswap:
|
||||||
|
{
|
||||||
|
AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
|
||||||
|
IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, scope);
|
||||||
|
if (arg0_value == irb->codegen->invalid_instruction)
|
||||||
|
return arg0_value;
|
||||||
|
|
||||||
|
AstNode *arg1_node = node->data.fn_call_expr.params.at(1);
|
||||||
|
IrInstruction *arg1_value = ir_gen_node(irb, arg1_node, scope);
|
||||||
|
if (arg1_value == irb->codegen->invalid_instruction)
|
||||||
|
return arg1_value;
|
||||||
|
|
||||||
|
IrInstruction *result = ir_build_bswap(irb, scope, node, arg0_value, arg1_value);
|
||||||
|
return ir_lval_wrap(irb, scope, result, lval);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
zig_unreachable();
|
zig_unreachable();
|
||||||
}
|
}
|
||||||
@ -13674,18 +13704,55 @@ static Error ir_read_const_ptr(IrAnalyze *ira, AstNode *source_node,
|
|||||||
return ErrorNone;
|
return ErrorNone;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dst_size > src_size) {
|
if (dst_size <= src_size) {
|
||||||
ir_add_error_node(ira, source_node,
|
Buf buf = BUF_INIT;
|
||||||
buf_sprintf("attempt to read %zu bytes from pointer to %s which is %zu bytes",
|
buf_resize(&buf, src_size);
|
||||||
dst_size, buf_ptr(&pointee->type->name), src_size));
|
buf_write_value_bytes(ira->codegen, (uint8_t*)buf_ptr(&buf), pointee);
|
||||||
return ErrorSemanticAnalyzeFail;
|
buf_read_value_bytes(ira->codegen, (uint8_t*)buf_ptr(&buf), out_val);
|
||||||
|
return ErrorNone;
|
||||||
}
|
}
|
||||||
|
|
||||||
Buf buf = BUF_INIT;
|
switch (ptr_val->data.x_ptr.special) {
|
||||||
buf_resize(&buf, src_size);
|
case ConstPtrSpecialInvalid:
|
||||||
buf_write_value_bytes(ira->codegen, (uint8_t*)buf_ptr(&buf), pointee);
|
zig_unreachable();
|
||||||
buf_read_value_bytes(ira->codegen, (uint8_t*)buf_ptr(&buf), out_val);
|
case ConstPtrSpecialRef: {
|
||||||
return ErrorNone;
|
ir_add_error_node(ira, source_node,
|
||||||
|
buf_sprintf("attempt to read %zu bytes from pointer to %s which is %zu bytes",
|
||||||
|
dst_size, buf_ptr(&pointee->type->name), src_size));
|
||||||
|
return ErrorSemanticAnalyzeFail;
|
||||||
|
}
|
||||||
|
case ConstPtrSpecialBaseArray: {
|
||||||
|
ConstExprValue *array_val = ptr_val->data.x_ptr.data.base_array.array_val;
|
||||||
|
assert(array_val->type->id == ZigTypeIdArray);
|
||||||
|
if (array_val->data.x_array.special != ConstArraySpecialNone)
|
||||||
|
zig_panic("TODO");
|
||||||
|
size_t elem_size = src_size;
|
||||||
|
src_size = elem_size *
|
||||||
|
(array_val->type->data.array.len - ptr_val->data.x_ptr.data.base_array.elem_index);
|
||||||
|
if (dst_size > src_size) {
|
||||||
|
ir_add_error_node(ira, source_node,
|
||||||
|
buf_sprintf("attempt to read %zu bytes from %s at index %" ZIG_PRI_usize " which is %zu bytes",
|
||||||
|
dst_size, buf_ptr(&array_val->type->name), ptr_val->data.x_ptr.data.base_array.elem_index,
|
||||||
|
src_size));
|
||||||
|
return ErrorSemanticAnalyzeFail;
|
||||||
|
}
|
||||||
|
size_t elem_count = (dst_size % elem_size == 0) ? (dst_size / elem_size) : (dst_size / elem_size + 1);
|
||||||
|
Buf buf = BUF_INIT;
|
||||||
|
buf_resize(&buf, elem_count * elem_size);
|
||||||
|
for (size_t i = 0; i < elem_count; i += 1) {
|
||||||
|
ConstExprValue *elem_val = &array_val->data.x_array.data.s_none.elements[i];
|
||||||
|
buf_write_value_bytes(ira->codegen, (uint8_t*)buf_ptr(&buf) + (i * elem_size), elem_val);
|
||||||
|
}
|
||||||
|
buf_read_value_bytes(ira->codegen, (uint8_t*)buf_ptr(&buf), out_val);
|
||||||
|
return ErrorNone;
|
||||||
|
}
|
||||||
|
case ConstPtrSpecialBaseStruct:
|
||||||
|
case ConstPtrSpecialDiscard:
|
||||||
|
case ConstPtrSpecialHardCodedAddr:
|
||||||
|
case ConstPtrSpecialFunction:
|
||||||
|
zig_panic("TODO");
|
||||||
|
}
|
||||||
|
zig_unreachable();
|
||||||
}
|
}
|
||||||
|
|
||||||
static IrInstruction *ir_analyze_maybe(IrAnalyze *ira, IrInstructionUnOp *un_op_instruction) {
|
static IrInstruction *ir_analyze_maybe(IrAnalyze *ira, IrInstructionUnOp *un_op_instruction) {
|
||||||
@ -18054,6 +18121,12 @@ static IrInstruction *ir_analyze_instruction_truncate(IrAnalyze *ira, IrInstruct
|
|||||||
return ira->codegen->invalid_instruction;
|
return ira->codegen->invalid_instruction;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (src_type->data.integral.bit_count == 0) {
|
||||||
|
IrInstruction *result = ir_const(ira, &instruction->base, dest_type);
|
||||||
|
bigint_init_unsigned(&result->value.data.x_bigint, 0);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
if (src_type->data.integral.is_signed != dest_type->data.integral.is_signed) {
|
if (src_type->data.integral.is_signed != dest_type->data.integral.is_signed) {
|
||||||
const char *sign_str = dest_type->data.integral.is_signed ? "signed" : "unsigned";
|
const char *sign_str = dest_type->data.integral.is_signed ? "signed" : "unsigned";
|
||||||
ir_add_error(ira, target, buf_sprintf("expected %s integer type, found '%s'", sign_str, buf_ptr(&src_type->name)));
|
ir_add_error(ira, target, buf_sprintf("expected %s integer type, found '%s'", sign_str, buf_ptr(&src_type->name)));
|
||||||
@ -20299,6 +20372,9 @@ static IrInstruction *ir_analyze_instruction_ptr_type(IrAnalyze *ira, IrInstruct
|
|||||||
return ira->codegen->invalid_instruction;
|
return ira->codegen->invalid_instruction;
|
||||||
if ((err = type_resolve(ira->codegen, child_type, ResolveStatusAlignmentKnown)))
|
if ((err = type_resolve(ira->codegen, child_type, ResolveStatusAlignmentKnown)))
|
||||||
return ira->codegen->invalid_instruction;
|
return ira->codegen->invalid_instruction;
|
||||||
|
if (!type_has_bits(child_type)) {
|
||||||
|
align_bytes = 0;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
if ((err = type_resolve(ira->codegen, child_type, ResolveStatusZeroBitsKnown)))
|
if ((err = type_resolve(ira->codegen, child_type, ResolveStatusZeroBitsKnown)))
|
||||||
return ira->codegen->invalid_instruction;
|
return ira->codegen->invalid_instruction;
|
||||||
@ -20898,6 +20974,63 @@ static IrInstruction *ir_analyze_instruction_sqrt(IrAnalyze *ira, IrInstructionS
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static IrInstruction *ir_analyze_instruction_bswap(IrAnalyze *ira, IrInstructionBswap *instruction) {
|
||||||
|
ZigType *int_type = ir_resolve_type(ira, instruction->type->child);
|
||||||
|
if (type_is_invalid(int_type))
|
||||||
|
return ira->codegen->invalid_instruction;
|
||||||
|
|
||||||
|
IrInstruction *op = instruction->op->child;
|
||||||
|
if (type_is_invalid(op->value.type))
|
||||||
|
return ira->codegen->invalid_instruction;
|
||||||
|
|
||||||
|
if (int_type->id != ZigTypeIdInt) {
|
||||||
|
ir_add_error(ira, instruction->type,
|
||||||
|
buf_sprintf("expected integer type, found '%s'", buf_ptr(&int_type->name)));
|
||||||
|
return ira->codegen->invalid_instruction;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (int_type->data.integral.bit_count % 8 != 0) {
|
||||||
|
ir_add_error(ira, instruction->type,
|
||||||
|
buf_sprintf("@bswap integer type '%s' has %" PRIu32 " bits which is not evenly divisible by 8",
|
||||||
|
buf_ptr(&int_type->name), int_type->data.integral.bit_count));
|
||||||
|
return ira->codegen->invalid_instruction;
|
||||||
|
}
|
||||||
|
|
||||||
|
IrInstruction *casted_op = ir_implicit_cast(ira, op, int_type);
|
||||||
|
if (type_is_invalid(casted_op->value.type))
|
||||||
|
return ira->codegen->invalid_instruction;
|
||||||
|
|
||||||
|
if (int_type->data.integral.bit_count == 0) {
|
||||||
|
IrInstruction *result = ir_const(ira, &instruction->base, int_type);
|
||||||
|
bigint_init_unsigned(&result->value.data.x_bigint, 0);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (int_type->data.integral.bit_count == 8) {
|
||||||
|
return casted_op;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (instr_is_comptime(casted_op)) {
|
||||||
|
ConstExprValue *val = ir_resolve_const(ira, casted_op, UndefBad);
|
||||||
|
if (!val)
|
||||||
|
return ira->codegen->invalid_instruction;
|
||||||
|
|
||||||
|
IrInstruction *result = ir_const(ira, &instruction->base, int_type);
|
||||||
|
size_t buf_size = int_type->data.integral.bit_count / 8;
|
||||||
|
uint8_t *buf = allocate_nonzero<uint8_t>(buf_size);
|
||||||
|
bigint_write_twos_complement(&val->data.x_bigint, buf, int_type->data.integral.bit_count, true);
|
||||||
|
bigint_read_twos_complement(&result->value.data.x_bigint, buf, int_type->data.integral.bit_count, false,
|
||||||
|
int_type->data.integral.is_signed);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
IrInstruction *result = ir_build_bswap(&ira->new_irb, instruction->base.scope,
|
||||||
|
instruction->base.source_node, nullptr, casted_op);
|
||||||
|
result->value.type = int_type;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static IrInstruction *ir_analyze_instruction_enum_to_int(IrAnalyze *ira, IrInstructionEnumToInt *instruction) {
|
static IrInstruction *ir_analyze_instruction_enum_to_int(IrAnalyze *ira, IrInstructionEnumToInt *instruction) {
|
||||||
Error err;
|
Error err;
|
||||||
IrInstruction *target = instruction->target->child;
|
IrInstruction *target = instruction->target->child;
|
||||||
@ -21233,6 +21366,8 @@ static IrInstruction *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructio
|
|||||||
return ir_analyze_instruction_mark_err_ret_trace_ptr(ira, (IrInstructionMarkErrRetTracePtr *)instruction);
|
return ir_analyze_instruction_mark_err_ret_trace_ptr(ira, (IrInstructionMarkErrRetTracePtr *)instruction);
|
||||||
case IrInstructionIdSqrt:
|
case IrInstructionIdSqrt:
|
||||||
return ir_analyze_instruction_sqrt(ira, (IrInstructionSqrt *)instruction);
|
return ir_analyze_instruction_sqrt(ira, (IrInstructionSqrt *)instruction);
|
||||||
|
case IrInstructionIdBswap:
|
||||||
|
return ir_analyze_instruction_bswap(ira, (IrInstructionBswap *)instruction);
|
||||||
case IrInstructionIdIntToErr:
|
case IrInstructionIdIntToErr:
|
||||||
return ir_analyze_instruction_int_to_err(ira, (IrInstructionIntToErr *)instruction);
|
return ir_analyze_instruction_int_to_err(ira, (IrInstructionIntToErr *)instruction);
|
||||||
case IrInstructionIdErrToInt:
|
case IrInstructionIdErrToInt:
|
||||||
@ -21454,6 +21589,7 @@ bool ir_has_side_effects(IrInstruction *instruction) {
|
|||||||
case IrInstructionIdCoroPromise:
|
case IrInstructionIdCoroPromise:
|
||||||
case IrInstructionIdPromiseResultType:
|
case IrInstructionIdPromiseResultType:
|
||||||
case IrInstructionIdSqrt:
|
case IrInstructionIdSqrt:
|
||||||
|
case IrInstructionIdBswap:
|
||||||
case IrInstructionIdAtomicLoad:
|
case IrInstructionIdAtomicLoad:
|
||||||
case IrInstructionIdIntCast:
|
case IrInstructionIdIntCast:
|
||||||
case IrInstructionIdFloatCast:
|
case IrInstructionIdFloatCast:
|
||||||
|
@ -1323,6 +1323,18 @@ static void ir_print_sqrt(IrPrint *irp, IrInstructionSqrt *instruction) {
|
|||||||
fprintf(irp->f, ")");
|
fprintf(irp->f, ")");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void ir_print_bswap(IrPrint *irp, IrInstructionBswap *instruction) {
|
||||||
|
fprintf(irp->f, "@bswap(");
|
||||||
|
if (instruction->type != nullptr) {
|
||||||
|
ir_print_other_instruction(irp, instruction->type);
|
||||||
|
} else {
|
||||||
|
fprintf(irp->f, "null");
|
||||||
|
}
|
||||||
|
fprintf(irp->f, ",");
|
||||||
|
ir_print_other_instruction(irp, instruction->op);
|
||||||
|
fprintf(irp->f, ")");
|
||||||
|
}
|
||||||
|
|
||||||
static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
|
static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
|
||||||
ir_print_prefix(irp, instruction);
|
ir_print_prefix(irp, instruction);
|
||||||
switch (instruction->id) {
|
switch (instruction->id) {
|
||||||
@ -1736,6 +1748,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
|
|||||||
case IrInstructionIdSqrt:
|
case IrInstructionIdSqrt:
|
||||||
ir_print_sqrt(irp, (IrInstructionSqrt *)instruction);
|
ir_print_sqrt(irp, (IrInstructionSqrt *)instruction);
|
||||||
break;
|
break;
|
||||||
|
case IrInstructionIdBswap:
|
||||||
|
ir_print_bswap(irp, (IrInstructionBswap *)instruction);
|
||||||
|
break;
|
||||||
case IrInstructionIdAtomicLoad:
|
case IrInstructionIdAtomicLoad:
|
||||||
ir_print_atomic_load(irp, (IrInstructionAtomicLoad *)instruction);
|
ir_print_atomic_load(irp, (IrInstructionAtomicLoad *)instruction);
|
||||||
break;
|
break;
|
||||||
|
44
std/coff.zig
44
std/coff.zig
@ -51,7 +51,7 @@ pub const Coff = struct {
|
|||||||
|
|
||||||
// Seek to PE File Header (coff header)
|
// Seek to PE File Header (coff header)
|
||||||
try self.in_file.seekTo(pe_pointer_offset);
|
try self.in_file.seekTo(pe_pointer_offset);
|
||||||
const pe_magic_offset = try in.readIntLe(u32);
|
const pe_magic_offset = try in.readIntLittle(u32);
|
||||||
try self.in_file.seekTo(pe_magic_offset);
|
try self.in_file.seekTo(pe_magic_offset);
|
||||||
|
|
||||||
var pe_header_magic: [4]u8 = undefined;
|
var pe_header_magic: [4]u8 = undefined;
|
||||||
@ -60,13 +60,13 @@ pub const Coff = struct {
|
|||||||
return error.InvalidPEHeader;
|
return error.InvalidPEHeader;
|
||||||
|
|
||||||
self.coff_header = CoffHeader{
|
self.coff_header = CoffHeader{
|
||||||
.machine = try in.readIntLe(u16),
|
.machine = try in.readIntLittle(u16),
|
||||||
.number_of_sections = try in.readIntLe(u16),
|
.number_of_sections = try in.readIntLittle(u16),
|
||||||
.timedate_stamp = try in.readIntLe(u32),
|
.timedate_stamp = try in.readIntLittle(u32),
|
||||||
.pointer_to_symbol_table = try in.readIntLe(u32),
|
.pointer_to_symbol_table = try in.readIntLittle(u32),
|
||||||
.number_of_symbols = try in.readIntLe(u32),
|
.number_of_symbols = try in.readIntLittle(u32),
|
||||||
.size_of_optional_header = try in.readIntLe(u16),
|
.size_of_optional_header = try in.readIntLittle(u16),
|
||||||
.characteristics = try in.readIntLe(u16),
|
.characteristics = try in.readIntLittle(u16),
|
||||||
};
|
};
|
||||||
|
|
||||||
switch (self.coff_header.machine) {
|
switch (self.coff_header.machine) {
|
||||||
@ -79,7 +79,7 @@ pub const Coff = struct {
|
|||||||
|
|
||||||
fn loadOptionalHeader(self: *Coff, file_stream: *os.File.InStream) !void {
|
fn loadOptionalHeader(self: *Coff, file_stream: *os.File.InStream) !void {
|
||||||
const in = &file_stream.stream;
|
const in = &file_stream.stream;
|
||||||
self.pe_header.magic = try in.readIntLe(u16);
|
self.pe_header.magic = try in.readIntLittle(u16);
|
||||||
// For now we're only interested in finding the reference to the .pdb,
|
// For now we're only interested in finding the reference to the .pdb,
|
||||||
// so we'll skip most of this header, which size is different in 32
|
// so we'll skip most of this header, which size is different in 32
|
||||||
// 64 bits by the way.
|
// 64 bits by the way.
|
||||||
@ -93,14 +93,14 @@ pub const Coff = struct {
|
|||||||
|
|
||||||
try self.in_file.seekForward(skip_size);
|
try self.in_file.seekForward(skip_size);
|
||||||
|
|
||||||
const number_of_rva_and_sizes = try in.readIntLe(u32);
|
const number_of_rva_and_sizes = try in.readIntLittle(u32);
|
||||||
if (number_of_rva_and_sizes != IMAGE_NUMBEROF_DIRECTORY_ENTRIES)
|
if (number_of_rva_and_sizes != IMAGE_NUMBEROF_DIRECTORY_ENTRIES)
|
||||||
return error.InvalidPEHeader;
|
return error.InvalidPEHeader;
|
||||||
|
|
||||||
for (self.pe_header.data_directory) |*data_dir| {
|
for (self.pe_header.data_directory) |*data_dir| {
|
||||||
data_dir.* = OptionalHeader.DataDirectory{
|
data_dir.* = OptionalHeader.DataDirectory{
|
||||||
.virtual_address = try in.readIntLe(u32),
|
.virtual_address = try in.readIntLittle(u32),
|
||||||
.size = try in.readIntLe(u32),
|
.size = try in.readIntLittle(u32),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -124,7 +124,7 @@ pub const Coff = struct {
|
|||||||
if (!mem.eql(u8, cv_signature, "RSDS"))
|
if (!mem.eql(u8, cv_signature, "RSDS"))
|
||||||
return error.InvalidPEMagic;
|
return error.InvalidPEMagic;
|
||||||
try in.readNoEof(self.guid[0..]);
|
try in.readNoEof(self.guid[0..]);
|
||||||
self.age = try in.readIntLe(u32);
|
self.age = try in.readIntLittle(u32);
|
||||||
|
|
||||||
// Finally read the null-terminated string.
|
// Finally read the null-terminated string.
|
||||||
var byte = try in.readByte();
|
var byte = try in.readByte();
|
||||||
@ -157,15 +157,15 @@ pub const Coff = struct {
|
|||||||
try self.sections.append(Section{
|
try self.sections.append(Section{
|
||||||
.header = SectionHeader{
|
.header = SectionHeader{
|
||||||
.name = name,
|
.name = name,
|
||||||
.misc = SectionHeader.Misc{ .physical_address = try in.readIntLe(u32) },
|
.misc = SectionHeader.Misc{ .physical_address = try in.readIntLittle(u32) },
|
||||||
.virtual_address = try in.readIntLe(u32),
|
.virtual_address = try in.readIntLittle(u32),
|
||||||
.size_of_raw_data = try in.readIntLe(u32),
|
.size_of_raw_data = try in.readIntLittle(u32),
|
||||||
.pointer_to_raw_data = try in.readIntLe(u32),
|
.pointer_to_raw_data = try in.readIntLittle(u32),
|
||||||
.pointer_to_relocations = try in.readIntLe(u32),
|
.pointer_to_relocations = try in.readIntLittle(u32),
|
||||||
.pointer_to_line_numbers = try in.readIntLe(u32),
|
.pointer_to_line_numbers = try in.readIntLittle(u32),
|
||||||
.number_of_relocations = try in.readIntLe(u16),
|
.number_of_relocations = try in.readIntLittle(u16),
|
||||||
.number_of_line_numbers = try in.readIntLe(u16),
|
.number_of_line_numbers = try in.readIntLittle(u16),
|
||||||
.characteristics = try in.readIntLe(u32),
|
.characteristics = try in.readIntLittle(u32),
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -123,7 +123,8 @@ fn Blake2s(comptime out_len: usize) type {
|
|||||||
const rr = d.h[0 .. out_len / 32];
|
const rr = d.h[0 .. out_len / 32];
|
||||||
|
|
||||||
for (rr) |s, j| {
|
for (rr) |s, j| {
|
||||||
mem.writeInt(out[4 * j .. 4 * j + 4], s, builtin.Endian.Little);
|
// TODO https://github.com/ziglang/zig/issues/863
|
||||||
|
mem.writeIntSliceLittle(u32, out[4 * j .. 4 * j + 4], s);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -134,7 +135,8 @@ fn Blake2s(comptime out_len: usize) type {
|
|||||||
var v: [16]u32 = undefined;
|
var v: [16]u32 = undefined;
|
||||||
|
|
||||||
for (m) |*r, i| {
|
for (m) |*r, i| {
|
||||||
r.* = mem.readIntLE(u32, b[4 * i .. 4 * i + 4]);
|
// TODO https://github.com/ziglang/zig/issues/863
|
||||||
|
r.* = mem.readIntSliceLittle(u32, b[4 * i .. 4 * i + 4]);
|
||||||
}
|
}
|
||||||
|
|
||||||
var k: usize = 0;
|
var k: usize = 0;
|
||||||
@ -356,7 +358,8 @@ fn Blake2b(comptime out_len: usize) type {
|
|||||||
const rr = d.h[0 .. out_len / 64];
|
const rr = d.h[0 .. out_len / 64];
|
||||||
|
|
||||||
for (rr) |s, j| {
|
for (rr) |s, j| {
|
||||||
mem.writeInt(out[8 * j .. 8 * j + 8], s, builtin.Endian.Little);
|
// TODO https://github.com/ziglang/zig/issues/863
|
||||||
|
mem.writeIntSliceLittle(u64, out[8 * j .. 8 * j + 8], s);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -367,7 +370,7 @@ fn Blake2b(comptime out_len: usize) type {
|
|||||||
var v: [16]u64 = undefined;
|
var v: [16]u64 = undefined;
|
||||||
|
|
||||||
for (m) |*r, i| {
|
for (m) |*r, i| {
|
||||||
r.* = mem.readIntLE(u64, b[8 * i .. 8 * i + 8]);
|
r.* = mem.readIntSliceLittle(u64, b[8 * i .. 8 * i + 8]);
|
||||||
}
|
}
|
||||||
|
|
||||||
var k: usize = 0;
|
var k: usize = 0;
|
||||||
|
@ -59,7 +59,8 @@ fn salsa20_wordtobyte(out: []u8, input: [16]u32) void {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (x) |_, i| {
|
for (x) |_, i| {
|
||||||
mem.writeInt(out[4 * i .. 4 * i + 4], x[i] +% input[i], builtin.Endian.Little);
|
// TODO https://github.com/ziglang/zig/issues/863
|
||||||
|
mem.writeIntSliceLittle(u32, out[4 * i .. 4 * i + 4], x[i] +% input[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -70,10 +71,10 @@ fn chaCha20_internal(out: []u8, in: []const u8, key: [8]u32, counter: [4]u32) vo
|
|||||||
|
|
||||||
const c = "expand 32-byte k";
|
const c = "expand 32-byte k";
|
||||||
const constant_le = []u32{
|
const constant_le = []u32{
|
||||||
mem.readIntLE(u32, c[0..4]),
|
mem.readIntSliceLittle(u32, c[0..4]),
|
||||||
mem.readIntLE(u32, c[4..8]),
|
mem.readIntSliceLittle(u32, c[4..8]),
|
||||||
mem.readIntLE(u32, c[8..12]),
|
mem.readIntSliceLittle(u32, c[8..12]),
|
||||||
mem.readIntLE(u32, c[12..16]),
|
mem.readIntSliceLittle(u32, c[12..16]),
|
||||||
};
|
};
|
||||||
|
|
||||||
mem.copy(u32, ctx[0..], constant_le[0..4]);
|
mem.copy(u32, ctx[0..], constant_le[0..4]);
|
||||||
@ -117,19 +118,19 @@ pub fn chaCha20IETF(out: []u8, in: []const u8, counter: u32, key: [32]u8, nonce:
|
|||||||
var k: [8]u32 = undefined;
|
var k: [8]u32 = undefined;
|
||||||
var c: [4]u32 = undefined;
|
var c: [4]u32 = undefined;
|
||||||
|
|
||||||
k[0] = mem.readIntLE(u32, key[0..4]);
|
k[0] = mem.readIntSliceLittle(u32, key[0..4]);
|
||||||
k[1] = mem.readIntLE(u32, key[4..8]);
|
k[1] = mem.readIntSliceLittle(u32, key[4..8]);
|
||||||
k[2] = mem.readIntLE(u32, key[8..12]);
|
k[2] = mem.readIntSliceLittle(u32, key[8..12]);
|
||||||
k[3] = mem.readIntLE(u32, key[12..16]);
|
k[3] = mem.readIntSliceLittle(u32, key[12..16]);
|
||||||
k[4] = mem.readIntLE(u32, key[16..20]);
|
k[4] = mem.readIntSliceLittle(u32, key[16..20]);
|
||||||
k[5] = mem.readIntLE(u32, key[20..24]);
|
k[5] = mem.readIntSliceLittle(u32, key[20..24]);
|
||||||
k[6] = mem.readIntLE(u32, key[24..28]);
|
k[6] = mem.readIntSliceLittle(u32, key[24..28]);
|
||||||
k[7] = mem.readIntLE(u32, key[28..32]);
|
k[7] = mem.readIntSliceLittle(u32, key[28..32]);
|
||||||
|
|
||||||
c[0] = counter;
|
c[0] = counter;
|
||||||
c[1] = mem.readIntLE(u32, nonce[0..4]);
|
c[1] = mem.readIntSliceLittle(u32, nonce[0..4]);
|
||||||
c[2] = mem.readIntLE(u32, nonce[4..8]);
|
c[2] = mem.readIntSliceLittle(u32, nonce[4..8]);
|
||||||
c[3] = mem.readIntLE(u32, nonce[8..12]);
|
c[3] = mem.readIntSliceLittle(u32, nonce[8..12]);
|
||||||
chaCha20_internal(out, in, k, c);
|
chaCha20_internal(out, in, k, c);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -144,19 +145,19 @@ pub fn chaCha20With64BitNonce(out: []u8, in: []const u8, counter: u64, key: [32]
|
|||||||
var k: [8]u32 = undefined;
|
var k: [8]u32 = undefined;
|
||||||
var c: [4]u32 = undefined;
|
var c: [4]u32 = undefined;
|
||||||
|
|
||||||
k[0] = mem.readIntLE(u32, key[0..4]);
|
k[0] = mem.readIntSliceLittle(u32, key[0..4]);
|
||||||
k[1] = mem.readIntLE(u32, key[4..8]);
|
k[1] = mem.readIntSliceLittle(u32, key[4..8]);
|
||||||
k[2] = mem.readIntLE(u32, key[8..12]);
|
k[2] = mem.readIntSliceLittle(u32, key[8..12]);
|
||||||
k[3] = mem.readIntLE(u32, key[12..16]);
|
k[3] = mem.readIntSliceLittle(u32, key[12..16]);
|
||||||
k[4] = mem.readIntLE(u32, key[16..20]);
|
k[4] = mem.readIntSliceLittle(u32, key[16..20]);
|
||||||
k[5] = mem.readIntLE(u32, key[20..24]);
|
k[5] = mem.readIntSliceLittle(u32, key[20..24]);
|
||||||
k[6] = mem.readIntLE(u32, key[24..28]);
|
k[6] = mem.readIntSliceLittle(u32, key[24..28]);
|
||||||
k[7] = mem.readIntLE(u32, key[28..32]);
|
k[7] = mem.readIntSliceLittle(u32, key[28..32]);
|
||||||
|
|
||||||
c[0] = @truncate(u32, counter);
|
c[0] = @truncate(u32, counter);
|
||||||
c[1] = @truncate(u32, counter >> 32);
|
c[1] = @truncate(u32, counter >> 32);
|
||||||
c[2] = mem.readIntLE(u32, nonce[0..4]);
|
c[2] = mem.readIntSliceLittle(u32, nonce[0..4]);
|
||||||
c[3] = mem.readIntLE(u32, nonce[4..8]);
|
c[3] = mem.readIntSliceLittle(u32, nonce[4..8]);
|
||||||
|
|
||||||
const block_size = (1 << 6);
|
const block_size = (1 << 6);
|
||||||
const big_block = (block_size << 32);
|
const big_block = (block_size << 32);
|
||||||
|
@ -112,7 +112,8 @@ pub const Md5 = struct {
|
|||||||
d.round(d.buf[0..]);
|
d.round(d.buf[0..]);
|
||||||
|
|
||||||
for (d.s) |s, j| {
|
for (d.s) |s, j| {
|
||||||
mem.writeInt(out[4 * j .. 4 * j + 4], s, builtin.Endian.Little);
|
// TODO https://github.com/ziglang/zig/issues/863
|
||||||
|
mem.writeIntSliceLittle(u32, out[4 * j .. 4 * j + 4], s);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,8 +6,8 @@ const std = @import("../index.zig");
|
|||||||
const builtin = @import("builtin");
|
const builtin = @import("builtin");
|
||||||
|
|
||||||
const Endian = builtin.Endian;
|
const Endian = builtin.Endian;
|
||||||
const readInt = std.mem.readInt;
|
const readIntSliceLittle = std.mem.readIntSliceLittle;
|
||||||
const writeInt = std.mem.writeInt;
|
const writeIntSliceLittle = std.mem.writeIntSliceLittle;
|
||||||
|
|
||||||
pub const Poly1305 = struct {
|
pub const Poly1305 = struct {
|
||||||
const Self = @This();
|
const Self = @This();
|
||||||
@ -59,19 +59,19 @@ pub const Poly1305 = struct {
|
|||||||
{
|
{
|
||||||
var i: usize = 0;
|
var i: usize = 0;
|
||||||
while (i < 1) : (i += 1) {
|
while (i < 1) : (i += 1) {
|
||||||
ctx.r[0] = readInt(key[0..4], u32, Endian.Little) & 0x0fffffff;
|
ctx.r[0] = readIntSliceLittle(u32, key[0..4]) & 0x0fffffff;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
var i: usize = 1;
|
var i: usize = 1;
|
||||||
while (i < 4) : (i += 1) {
|
while (i < 4) : (i += 1) {
|
||||||
ctx.r[i] = readInt(key[i * 4 .. i * 4 + 4], u32, Endian.Little) & 0x0ffffffc;
|
ctx.r[i] = readIntSliceLittle(u32, key[i * 4 .. i * 4 + 4]) & 0x0ffffffc;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
var i: usize = 0;
|
var i: usize = 0;
|
||||||
while (i < 4) : (i += 1) {
|
while (i < 4) : (i += 1) {
|
||||||
ctx.pad[i] = readInt(key[i * 4 + 16 .. i * 4 + 16 + 4], u32, Endian.Little);
|
ctx.pad[i] = readIntSliceLittle(u32, key[i * 4 + 16 .. i * 4 + 16 + 4]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -168,10 +168,10 @@ pub const Poly1305 = struct {
|
|||||||
const nb_blocks = nmsg.len >> 4;
|
const nb_blocks = nmsg.len >> 4;
|
||||||
var i: usize = 0;
|
var i: usize = 0;
|
||||||
while (i < nb_blocks) : (i += 1) {
|
while (i < nb_blocks) : (i += 1) {
|
||||||
ctx.c[0] = readInt(nmsg[0..4], u32, Endian.Little);
|
ctx.c[0] = readIntSliceLittle(u32, nmsg[0..4]);
|
||||||
ctx.c[1] = readInt(nmsg[4..8], u32, Endian.Little);
|
ctx.c[1] = readIntSliceLittle(u32, nmsg[4..8]);
|
||||||
ctx.c[2] = readInt(nmsg[8..12], u32, Endian.Little);
|
ctx.c[2] = readIntSliceLittle(u32, nmsg[8..12]);
|
||||||
ctx.c[3] = readInt(nmsg[12..16], u32, Endian.Little);
|
ctx.c[3] = readIntSliceLittle(u32, nmsg[12..16]);
|
||||||
polyBlock(ctx);
|
polyBlock(ctx);
|
||||||
nmsg = nmsg[16..];
|
nmsg = nmsg[16..];
|
||||||
}
|
}
|
||||||
@ -210,10 +210,11 @@ pub const Poly1305 = struct {
|
|||||||
const uu2 = (uu1 >> 32) + ctx.h[2] + ctx.pad[2]; // <= 2_00000000
|
const uu2 = (uu1 >> 32) + ctx.h[2] + ctx.pad[2]; // <= 2_00000000
|
||||||
const uu3 = (uu2 >> 32) + ctx.h[3] + ctx.pad[3]; // <= 2_00000000
|
const uu3 = (uu2 >> 32) + ctx.h[3] + ctx.pad[3]; // <= 2_00000000
|
||||||
|
|
||||||
writeInt(out[0..], @truncate(u32, uu0), Endian.Little);
|
// TODO https://github.com/ziglang/zig/issues/863
|
||||||
writeInt(out[4..], @truncate(u32, uu1), Endian.Little);
|
writeIntSliceLittle(u32, out[0..], @truncate(u32, uu0));
|
||||||
writeInt(out[8..], @truncate(u32, uu2), Endian.Little);
|
writeIntSliceLittle(u32, out[4..], @truncate(u32, uu1));
|
||||||
writeInt(out[12..], @truncate(u32, uu3), Endian.Little);
|
writeIntSliceLittle(u32, out[8..], @truncate(u32, uu2));
|
||||||
|
writeIntSliceLittle(u32, out[12..], @truncate(u32, uu3));
|
||||||
|
|
||||||
ctx.secureZero();
|
ctx.secureZero();
|
||||||
}
|
}
|
||||||
|
@ -109,7 +109,8 @@ pub const Sha1 = struct {
|
|||||||
d.round(d.buf[0..]);
|
d.round(d.buf[0..]);
|
||||||
|
|
||||||
for (d.s) |s, j| {
|
for (d.s) |s, j| {
|
||||||
mem.writeInt(out[4 * j .. 4 * j + 4], s, builtin.Endian.Big);
|
// TODO https://github.com/ziglang/zig/issues/863
|
||||||
|
mem.writeIntSliceBig(u32, out[4 * j .. 4 * j + 4], s);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -167,7 +167,8 @@ fn Sha2_32(comptime params: Sha2Params32) type {
|
|||||||
const rr = d.s[0 .. params.out_len / 32];
|
const rr = d.s[0 .. params.out_len / 32];
|
||||||
|
|
||||||
for (rr) |s, j| {
|
for (rr) |s, j| {
|
||||||
mem.writeInt(out[4 * j .. 4 * j + 4], s, builtin.Endian.Big);
|
// TODO https://github.com/ziglang/zig/issues/863
|
||||||
|
mem.writeIntSliceBig(u32, out[4 * j .. 4 * j + 4], s);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -508,7 +509,8 @@ fn Sha2_64(comptime params: Sha2Params64) type {
|
|||||||
const rr = d.s[0 .. params.out_len / 64];
|
const rr = d.s[0 .. params.out_len / 64];
|
||||||
|
|
||||||
for (rr) |s, j| {
|
for (rr) |s, j| {
|
||||||
mem.writeInt(out[8 * j .. 8 * j + 8], s, builtin.Endian.Big);
|
// TODO https://github.com/ziglang/zig/issues/863
|
||||||
|
mem.writeIntSliceBig(u64, out[8 * j .. 8 * j + 8], s);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -120,7 +120,7 @@ fn keccak_f(comptime F: usize, d: []u8) void {
|
|||||||
var c = []const u64{0} ** 5;
|
var c = []const u64{0} ** 5;
|
||||||
|
|
||||||
for (s) |*r, i| {
|
for (s) |*r, i| {
|
||||||
r.* = mem.readIntLE(u64, d[8 * i .. 8 * i + 8]);
|
r.* = mem.readIntSliceLittle(u64, d[8 * i .. 8 * i + 8]);
|
||||||
}
|
}
|
||||||
|
|
||||||
comptime var x: usize = 0;
|
comptime var x: usize = 0;
|
||||||
@ -167,7 +167,8 @@ fn keccak_f(comptime F: usize, d: []u8) void {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (s) |r, i| {
|
for (s) |r, i| {
|
||||||
mem.writeInt(d[8 * i .. 8 * i + 8], r, builtin.Endian.Little);
|
// TODO https://github.com/ziglang/zig/issues/863
|
||||||
|
mem.writeIntSliceLittle(u64, d[8 * i .. 8 * i + 8], r);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7,8 +7,8 @@ const builtin = @import("builtin");
|
|||||||
const fmt = std.fmt;
|
const fmt = std.fmt;
|
||||||
|
|
||||||
const Endian = builtin.Endian;
|
const Endian = builtin.Endian;
|
||||||
const readInt = std.mem.readInt;
|
const readIntSliceLittle = std.mem.readIntSliceLittle;
|
||||||
const writeInt = std.mem.writeInt;
|
const writeIntSliceLittle = std.mem.writeIntSliceLittle;
|
||||||
|
|
||||||
// Based on Supercop's ref10 implementation.
|
// Based on Supercop's ref10 implementation.
|
||||||
pub const X25519 = struct {
|
pub const X25519 = struct {
|
||||||
@ -255,16 +255,16 @@ const Fe = struct {
|
|||||||
|
|
||||||
var t: [10]i64 = undefined;
|
var t: [10]i64 = undefined;
|
||||||
|
|
||||||
t[0] = readInt(s[0..4], u32, Endian.Little);
|
t[0] = readIntSliceLittle(u32, s[0..4]);
|
||||||
t[1] = readInt(s[4..7], u32, Endian.Little) << 6;
|
t[1] = u32(readIntSliceLittle(u24, s[4..7])) << 6;
|
||||||
t[2] = readInt(s[7..10], u32, Endian.Little) << 5;
|
t[2] = u32(readIntSliceLittle(u24, s[7..10])) << 5;
|
||||||
t[3] = readInt(s[10..13], u32, Endian.Little) << 3;
|
t[3] = u32(readIntSliceLittle(u24, s[10..13])) << 3;
|
||||||
t[4] = readInt(s[13..16], u32, Endian.Little) << 2;
|
t[4] = u32(readIntSliceLittle(u24, s[13..16])) << 2;
|
||||||
t[5] = readInt(s[16..20], u32, Endian.Little);
|
t[5] = readIntSliceLittle(u32, s[16..20]);
|
||||||
t[6] = readInt(s[20..23], u32, Endian.Little) << 7;
|
t[6] = u32(readIntSliceLittle(u24, s[20..23])) << 7;
|
||||||
t[7] = readInt(s[23..26], u32, Endian.Little) << 5;
|
t[7] = u32(readIntSliceLittle(u24, s[23..26])) << 5;
|
||||||
t[8] = readInt(s[26..29], u32, Endian.Little) << 4;
|
t[8] = u32(readIntSliceLittle(u24, s[26..29])) << 4;
|
||||||
t[9] = (readInt(s[29..32], u32, Endian.Little) & 0x7fffff) << 2;
|
t[9] = (u32(readIntSliceLittle(u24, s[29..32])) & 0x7fffff) << 2;
|
||||||
|
|
||||||
carry1(h, t[0..]);
|
carry1(h, t[0..]);
|
||||||
}
|
}
|
||||||
@ -544,14 +544,15 @@ const Fe = struct {
|
|||||||
ut[i] = @bitCast(u32, @intCast(i32, t[i]));
|
ut[i] = @bitCast(u32, @intCast(i32, t[i]));
|
||||||
}
|
}
|
||||||
|
|
||||||
writeInt(s[0..], (ut[0] >> 0) | (ut[1] << 26), Endian.Little);
|
// TODO https://github.com/ziglang/zig/issues/863
|
||||||
writeInt(s[4..], (ut[1] >> 6) | (ut[2] << 19), Endian.Little);
|
writeIntSliceLittle(u32, s[0..4], (ut[0] >> 0) | (ut[1] << 26));
|
||||||
writeInt(s[8..], (ut[2] >> 13) | (ut[3] << 13), Endian.Little);
|
writeIntSliceLittle(u32, s[4..8], (ut[1] >> 6) | (ut[2] << 19));
|
||||||
writeInt(s[12..], (ut[3] >> 19) | (ut[4] << 6), Endian.Little);
|
writeIntSliceLittle(u32, s[8..12], (ut[2] >> 13) | (ut[3] << 13));
|
||||||
writeInt(s[16..], (ut[5] >> 0) | (ut[6] << 25), Endian.Little);
|
writeIntSliceLittle(u32, s[12..16], (ut[3] >> 19) | (ut[4] << 6));
|
||||||
writeInt(s[20..], (ut[6] >> 7) | (ut[7] << 19), Endian.Little);
|
writeIntSliceLittle(u32, s[16..20], (ut[5] >> 0) | (ut[6] << 25));
|
||||||
writeInt(s[24..], (ut[7] >> 13) | (ut[8] << 12), Endian.Little);
|
writeIntSliceLittle(u32, s[20..24], (ut[6] >> 7) | (ut[7] << 19));
|
||||||
writeInt(s[28..], (ut[8] >> 20) | (ut[9] << 6), Endian.Little);
|
writeIntSliceLittle(u32, s[24..28], (ut[7] >> 13) | (ut[8] << 12));
|
||||||
|
writeIntSliceLittle(u32, s[28..], (ut[8] >> 20) | (ut[9] << 6));
|
||||||
|
|
||||||
std.mem.secureZero(i64, t[0..]);
|
std.mem.secureZero(i64, t[0..]);
|
||||||
}
|
}
|
||||||
|
@ -523,7 +523,7 @@ fn populateModule(di: *DebugInfo, mod: *Module) !void {
|
|||||||
|
|
||||||
const modi = di.pdb.getStreamById(mod.mod_info.ModuleSymStream) orelse return error.MissingDebugInfo;
|
const modi = di.pdb.getStreamById(mod.mod_info.ModuleSymStream) orelse return error.MissingDebugInfo;
|
||||||
|
|
||||||
const signature = try modi.stream.readIntLe(u32);
|
const signature = try modi.stream.readIntLittle(u32);
|
||||||
if (signature != 4)
|
if (signature != 4)
|
||||||
return error.InvalidDebugInfo;
|
return error.InvalidDebugInfo;
|
||||||
|
|
||||||
@ -757,9 +757,9 @@ fn openSelfDebugInfoWindows(allocator: *mem.Allocator) !DebugInfo {
|
|||||||
try di.pdb.openFile(di.coff, path);
|
try di.pdb.openFile(di.coff, path);
|
||||||
|
|
||||||
var pdb_stream = di.pdb.getStream(pdb.StreamType.Pdb) orelse return error.InvalidDebugInfo;
|
var pdb_stream = di.pdb.getStream(pdb.StreamType.Pdb) orelse return error.InvalidDebugInfo;
|
||||||
const version = try pdb_stream.stream.readIntLe(u32);
|
const version = try pdb_stream.stream.readIntLittle(u32);
|
||||||
const signature = try pdb_stream.stream.readIntLe(u32);
|
const signature = try pdb_stream.stream.readIntLittle(u32);
|
||||||
const age = try pdb_stream.stream.readIntLe(u32);
|
const age = try pdb_stream.stream.readIntLittle(u32);
|
||||||
var guid: [16]u8 = undefined;
|
var guid: [16]u8 = undefined;
|
||||||
try pdb_stream.stream.readNoEof(guid[0..]);
|
try pdb_stream.stream.readNoEof(guid[0..]);
|
||||||
if (!mem.eql(u8, di.coff.guid, guid) or di.coff.age != age)
|
if (!mem.eql(u8, di.coff.guid, guid) or di.coff.age != age)
|
||||||
@ -767,7 +767,7 @@ fn openSelfDebugInfoWindows(allocator: *mem.Allocator) !DebugInfo {
|
|||||||
// We validated the executable and pdb match.
|
// We validated the executable and pdb match.
|
||||||
|
|
||||||
const string_table_index = str_tab_index: {
|
const string_table_index = str_tab_index: {
|
||||||
const name_bytes_len = try pdb_stream.stream.readIntLe(u32);
|
const name_bytes_len = try pdb_stream.stream.readIntLittle(u32);
|
||||||
const name_bytes = try allocator.alloc(u8, name_bytes_len);
|
const name_bytes = try allocator.alloc(u8, name_bytes_len);
|
||||||
try pdb_stream.stream.readNoEof(name_bytes);
|
try pdb_stream.stream.readNoEof(name_bytes);
|
||||||
|
|
||||||
@ -797,8 +797,8 @@ fn openSelfDebugInfoWindows(allocator: *mem.Allocator) !DebugInfo {
|
|||||||
};
|
};
|
||||||
const bucket_list = try allocator.alloc(Bucket, present.len);
|
const bucket_list = try allocator.alloc(Bucket, present.len);
|
||||||
for (present) |_| {
|
for (present) |_| {
|
||||||
const name_offset = try pdb_stream.stream.readIntLe(u32);
|
const name_offset = try pdb_stream.stream.readIntLittle(u32);
|
||||||
const name_index = try pdb_stream.stream.readIntLe(u32);
|
const name_index = try pdb_stream.stream.readIntLittle(u32);
|
||||||
const name = mem.toSlice(u8, name_bytes.ptr + name_offset);
|
const name = mem.toSlice(u8, name_bytes.ptr + name_offset);
|
||||||
if (mem.eql(u8, name, "/names")) {
|
if (mem.eql(u8, name, "/names")) {
|
||||||
break :str_tab_index name_index;
|
break :str_tab_index name_index;
|
||||||
@ -859,7 +859,7 @@ fn openSelfDebugInfoWindows(allocator: *mem.Allocator) !DebugInfo {
|
|||||||
var sect_contribs = ArrayList(pdb.SectionContribEntry).init(allocator);
|
var sect_contribs = ArrayList(pdb.SectionContribEntry).init(allocator);
|
||||||
var sect_cont_offset: usize = 0;
|
var sect_cont_offset: usize = 0;
|
||||||
if (section_contrib_size != 0) {
|
if (section_contrib_size != 0) {
|
||||||
const ver = @intToEnum(pdb.SectionContrSubstreamVersion, try dbi.stream.readIntLe(u32));
|
const ver = @intToEnum(pdb.SectionContrSubstreamVersion, try dbi.stream.readIntLittle(u32));
|
||||||
if (ver != pdb.SectionContrSubstreamVersion.Ver60)
|
if (ver != pdb.SectionContrSubstreamVersion.Ver60)
|
||||||
return error.InvalidDebugInfo;
|
return error.InvalidDebugInfo;
|
||||||
sect_cont_offset += @sizeOf(u32);
|
sect_cont_offset += @sizeOf(u32);
|
||||||
@ -879,11 +879,11 @@ fn openSelfDebugInfoWindows(allocator: *mem.Allocator) !DebugInfo {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn readSparseBitVector(stream: var, allocator: *mem.Allocator) ![]usize {
|
fn readSparseBitVector(stream: var, allocator: *mem.Allocator) ![]usize {
|
||||||
const num_words = try stream.readIntLe(u32);
|
const num_words = try stream.readIntLittle(u32);
|
||||||
var word_i: usize = 0;
|
var word_i: usize = 0;
|
||||||
var list = ArrayList(usize).init(allocator);
|
var list = ArrayList(usize).init(allocator);
|
||||||
while (word_i != num_words) : (word_i += 1) {
|
while (word_i != num_words) : (word_i += 1) {
|
||||||
const word = try stream.readIntLe(u32);
|
const word = try stream.readIntLittle(u32);
|
||||||
var bit_i: u5 = 0;
|
var bit_i: u5 = 0;
|
||||||
while (true) : (bit_i += 1) {
|
while (true) : (bit_i += 1) {
|
||||||
if (word & (u32(1) << bit_i) != 0) {
|
if (word & (u32(1) << bit_i) != 0) {
|
||||||
@ -1200,7 +1200,7 @@ const Constant = struct {
|
|||||||
fn asUnsignedLe(self: *const Constant) !u64 {
|
fn asUnsignedLe(self: *const Constant) !u64 {
|
||||||
if (self.payload.len > @sizeOf(u64)) return error.InvalidDebugInfo;
|
if (self.payload.len > @sizeOf(u64)) return error.InvalidDebugInfo;
|
||||||
if (self.signed) return error.InvalidDebugInfo;
|
if (self.signed) return error.InvalidDebugInfo;
|
||||||
return mem.readInt(self.payload, u64, builtin.Endian.Little);
|
return mem.readIntSliceLittle(u64, self.payload);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1381,7 +1381,7 @@ fn parseFormValueBlockLen(allocator: *mem.Allocator, in_stream: var, size: usize
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn parseFormValueBlock(allocator: *mem.Allocator, in_stream: var, size: usize) !FormValue {
|
fn parseFormValueBlock(allocator: *mem.Allocator, in_stream: var, size: usize) !FormValue {
|
||||||
const block_len = try in_stream.readVarInt(builtin.Endian.Little, usize, size);
|
const block_len = try in_stream.readVarInt(usize, builtin.Endian.Little, size);
|
||||||
return parseFormValueBlockLen(allocator, in_stream, block_len);
|
return parseFormValueBlockLen(allocator, in_stream, block_len);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1395,11 +1395,11 @@ fn parseFormValueConstant(allocator: *mem.Allocator, in_stream: var, signed: boo
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn parseFormValueDwarfOffsetSize(in_stream: var, is_64: bool) !u64 {
|
fn parseFormValueDwarfOffsetSize(in_stream: var, is_64: bool) !u64 {
|
||||||
return if (is_64) try in_stream.readIntLe(u64) else u64(try in_stream.readIntLe(u32));
|
return if (is_64) try in_stream.readIntLittle(u64) else u64(try in_stream.readIntLittle(u32));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parseFormValueTargetAddrSize(in_stream: var) !u64 {
|
fn parseFormValueTargetAddrSize(in_stream: var) !u64 {
|
||||||
return if (@sizeOf(usize) == 4) u64(try in_stream.readIntLe(u32)) else if (@sizeOf(usize) == 8) try in_stream.readIntLe(u64) else unreachable;
|
return if (@sizeOf(usize) == 4) u64(try in_stream.readIntLittle(u32)) else if (@sizeOf(usize) == 8) try in_stream.readIntLittle(u64) else unreachable;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parseFormValueRefLen(allocator: *mem.Allocator, in_stream: var, size: usize) !FormValue {
|
fn parseFormValueRefLen(allocator: *mem.Allocator, in_stream: var, size: usize) !FormValue {
|
||||||
@ -1408,7 +1408,7 @@ fn parseFormValueRefLen(allocator: *mem.Allocator, in_stream: var, size: usize)
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn parseFormValueRef(allocator: *mem.Allocator, in_stream: var, comptime T: type) !FormValue {
|
fn parseFormValueRef(allocator: *mem.Allocator, in_stream: var, comptime T: type) !FormValue {
|
||||||
const block_len = try in_stream.readIntLe(T);
|
const block_len = try in_stream.readIntLittle(T);
|
||||||
return parseFormValueRefLen(allocator, in_stream, block_len);
|
return parseFormValueRefLen(allocator, in_stream, block_len);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1450,7 +1450,7 @@ fn parseFormValue(allocator: *mem.Allocator, in_stream: var, form_id: u64, is_64
|
|||||||
},
|
},
|
||||||
|
|
||||||
DW.FORM_ref_addr => FormValue{ .RefAddr = try parseFormValueDwarfOffsetSize(in_stream, is_64) },
|
DW.FORM_ref_addr => FormValue{ .RefAddr = try parseFormValueDwarfOffsetSize(in_stream, is_64) },
|
||||||
DW.FORM_ref_sig8 => FormValue{ .RefSig8 = try in_stream.readIntLe(u64) },
|
DW.FORM_ref_sig8 => FormValue{ .RefSig8 = try in_stream.readIntLittle(u64) },
|
||||||
|
|
||||||
DW.FORM_string => FormValue{ .String = try readStringRaw(allocator, in_stream) },
|
DW.FORM_string => FormValue{ .String = try readStringRaw(allocator, in_stream) },
|
||||||
DW.FORM_strp => FormValue{ .StrPtr = try parseFormValueDwarfOffsetSize(in_stream, is_64) },
|
DW.FORM_strp => FormValue{ .StrPtr = try parseFormValueDwarfOffsetSize(in_stream, is_64) },
|
||||||
@ -1747,11 +1747,11 @@ fn getLineNumberInfoDwarf(di: *DwarfInfo, compile_unit: CompileUnit, target_addr
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
const version = try di.dwarf_in_stream.readInt(di.endian, u16);
|
const version = try di.dwarf_in_stream.readInt(u16, di.endian);
|
||||||
// TODO support 3 and 5
|
// TODO support 3 and 5
|
||||||
if (version != 2 and version != 4) return error.InvalidDebugInfo;
|
if (version != 2 and version != 4) return error.InvalidDebugInfo;
|
||||||
|
|
||||||
const prologue_length = if (is_64) try di.dwarf_in_stream.readInt(di.endian, u64) else try di.dwarf_in_stream.readInt(di.endian, u32);
|
const prologue_length = if (is_64) try di.dwarf_in_stream.readInt(u64, di.endian) else try di.dwarf_in_stream.readInt(u32, di.endian);
|
||||||
const prog_start_offset = (try di.dwarf_seekable_stream.getPos()) + prologue_length;
|
const prog_start_offset = (try di.dwarf_seekable_stream.getPos()) + prologue_length;
|
||||||
|
|
||||||
const minimum_instruction_length = try di.dwarf_in_stream.readByte();
|
const minimum_instruction_length = try di.dwarf_in_stream.readByte();
|
||||||
@ -1820,7 +1820,7 @@ fn getLineNumberInfoDwarf(di: *DwarfInfo, compile_unit: CompileUnit, target_addr
|
|||||||
return error.MissingDebugInfo;
|
return error.MissingDebugInfo;
|
||||||
},
|
},
|
||||||
DW.LNE_set_address => {
|
DW.LNE_set_address => {
|
||||||
const addr = try di.dwarf_in_stream.readInt(di.endian, usize);
|
const addr = try di.dwarf_in_stream.readInt(usize, di.endian);
|
||||||
prog.address = addr;
|
prog.address = addr;
|
||||||
},
|
},
|
||||||
DW.LNE_define_file => {
|
DW.LNE_define_file => {
|
||||||
@ -1882,7 +1882,7 @@ fn getLineNumberInfoDwarf(di: *DwarfInfo, compile_unit: CompileUnit, target_addr
|
|||||||
prog.address += inc_addr;
|
prog.address += inc_addr;
|
||||||
},
|
},
|
||||||
DW.LNS_fixed_advance_pc => {
|
DW.LNS_fixed_advance_pc => {
|
||||||
const arg = try di.dwarf_in_stream.readInt(di.endian, u16);
|
const arg = try di.dwarf_in_stream.readInt(u16, di.endian);
|
||||||
prog.address += arg;
|
prog.address += arg;
|
||||||
},
|
},
|
||||||
DW.LNS_set_prologue_end => {},
|
DW.LNS_set_prologue_end => {},
|
||||||
@ -1914,10 +1914,10 @@ fn scanAllCompileUnits(di: *DwarfInfo) !void {
|
|||||||
if (unit_length == 0) return;
|
if (unit_length == 0) return;
|
||||||
const next_offset = unit_length + (if (is_64) usize(12) else usize(4));
|
const next_offset = unit_length + (if (is_64) usize(12) else usize(4));
|
||||||
|
|
||||||
const version = try di.dwarf_in_stream.readInt(di.endian, u16);
|
const version = try di.dwarf_in_stream.readInt(u16, di.endian);
|
||||||
if (version < 2 or version > 5) return error.InvalidDebugInfo;
|
if (version < 2 or version > 5) return error.InvalidDebugInfo;
|
||||||
|
|
||||||
const debug_abbrev_offset = if (is_64) try di.dwarf_in_stream.readInt(di.endian, u64) else try di.dwarf_in_stream.readInt(di.endian, u32);
|
const debug_abbrev_offset = if (is_64) try di.dwarf_in_stream.readInt(u64, di.endian) else try di.dwarf_in_stream.readInt(u32, di.endian);
|
||||||
|
|
||||||
const address_size = try di.dwarf_in_stream.readByte();
|
const address_size = try di.dwarf_in_stream.readByte();
|
||||||
if (address_size != @sizeOf(usize)) return error.InvalidDebugInfo;
|
if (address_size != @sizeOf(usize)) return error.InvalidDebugInfo;
|
||||||
@ -1978,8 +1978,8 @@ fn findCompileUnit(di: *DwarfInfo, target_address: u64) !*const CompileUnit {
|
|||||||
if (di.debug_ranges) |debug_ranges| {
|
if (di.debug_ranges) |debug_ranges| {
|
||||||
try di.dwarf_seekable_stream.seekTo(debug_ranges.offset + ranges_offset);
|
try di.dwarf_seekable_stream.seekTo(debug_ranges.offset + ranges_offset);
|
||||||
while (true) {
|
while (true) {
|
||||||
const begin_addr = try di.dwarf_in_stream.readIntLe(usize);
|
const begin_addr = try di.dwarf_in_stream.readIntLittle(usize);
|
||||||
const end_addr = try di.dwarf_in_stream.readIntLe(usize);
|
const end_addr = try di.dwarf_in_stream.readIntLittle(usize);
|
||||||
if (begin_addr == 0 and end_addr == 0) {
|
if (begin_addr == 0 and end_addr == 0) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -2001,7 +2001,8 @@ fn findCompileUnit(di: *DwarfInfo, target_address: u64) !*const CompileUnit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn readIntMem(ptr: *[*]const u8, comptime T: type, endian: builtin.Endian) T {
|
fn readIntMem(ptr: *[*]const u8, comptime T: type, endian: builtin.Endian) T {
|
||||||
const result = mem.readInt(ptr.*[0..@sizeOf(T)], T, endian);
|
// TODO https://github.com/ziglang/zig/issues/863
|
||||||
|
const result = mem.readIntSlice(T, ptr.*[0..@sizeOf(T)], endian);
|
||||||
ptr.* += @sizeOf(T);
|
ptr.* += @sizeOf(T);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@ -2017,11 +2018,12 @@ fn readByteSignedMem(ptr: *[*]const u8) i8 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn readInitialLengthMem(ptr: *[*]const u8, is_64: *bool) !u64 {
|
fn readInitialLengthMem(ptr: *[*]const u8, is_64: *bool) !u64 {
|
||||||
const first_32_bits = mem.readIntLE(u32, ptr.*[0..4]);
|
// TODO this code can be improved with https://github.com/ziglang/zig/issues/863
|
||||||
|
const first_32_bits = mem.readIntSliceLittle(u32, ptr.*[0..4]);
|
||||||
is_64.* = (first_32_bits == 0xffffffff);
|
is_64.* = (first_32_bits == 0xffffffff);
|
||||||
if (is_64.*) {
|
if (is_64.*) {
|
||||||
ptr.* += 4;
|
ptr.* += 4;
|
||||||
const result = mem.readIntLE(u64, ptr.*[0..8]);
|
const result = mem.readIntSliceLittle(u64, ptr.*[0..8]);
|
||||||
ptr.* += 8;
|
ptr.* += 8;
|
||||||
return result;
|
return result;
|
||||||
} else {
|
} else {
|
||||||
@ -2084,10 +2086,10 @@ fn readILeb128Mem(ptr: *[*]const u8) !i64 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn readInitialLength(comptime E: type, in_stream: *io.InStream(E), is_64: *bool) !u64 {
|
fn readInitialLength(comptime E: type, in_stream: *io.InStream(E), is_64: *bool) !u64 {
|
||||||
const first_32_bits = try in_stream.readIntLe(u32);
|
const first_32_bits = try in_stream.readIntLittle(u32);
|
||||||
is_64.* = (first_32_bits == 0xffffffff);
|
is_64.* = (first_32_bits == 0xffffffff);
|
||||||
if (is_64.*) {
|
if (is_64.*) {
|
||||||
return in_stream.readIntLe(u64);
|
return in_stream.readIntLittle(u64);
|
||||||
} else {
|
} else {
|
||||||
if (first_32_bits >= 0xfffffff0) return error.InvalidDebugInfo;
|
if (first_32_bits >= 0xfffffff0) return error.InvalidDebugInfo;
|
||||||
return u64(first_32_bits);
|
return u64(first_32_bits);
|
||||||
|
70
std/elf.zig
70
std/elf.zig
@ -412,7 +412,7 @@ pub const Elf = struct {
|
|||||||
// skip over padding
|
// skip over padding
|
||||||
try seekable_stream.seekForward(9);
|
try seekable_stream.seekForward(9);
|
||||||
|
|
||||||
elf.file_type = switch (try in.readInt(elf.endian, u16)) {
|
elf.file_type = switch (try in.readInt(u16, elf.endian)) {
|
||||||
1 => FileType.Relocatable,
|
1 => FileType.Relocatable,
|
||||||
2 => FileType.Executable,
|
2 => FileType.Executable,
|
||||||
3 => FileType.Shared,
|
3 => FileType.Shared,
|
||||||
@ -420,7 +420,7 @@ pub const Elf = struct {
|
|||||||
else => return error.InvalidFormat,
|
else => return error.InvalidFormat,
|
||||||
};
|
};
|
||||||
|
|
||||||
elf.arch = switch (try in.readInt(elf.endian, u16)) {
|
elf.arch = switch (try in.readInt(u16, elf.endian)) {
|
||||||
0x02 => Arch.Sparc,
|
0x02 => Arch.Sparc,
|
||||||
0x03 => Arch.x86,
|
0x03 => Arch.x86,
|
||||||
0x08 => Arch.Mips,
|
0x08 => Arch.Mips,
|
||||||
@ -433,32 +433,32 @@ pub const Elf = struct {
|
|||||||
else => return error.InvalidFormat,
|
else => return error.InvalidFormat,
|
||||||
};
|
};
|
||||||
|
|
||||||
const elf_version = try in.readInt(elf.endian, u32);
|
const elf_version = try in.readInt(u32, elf.endian);
|
||||||
if (elf_version != 1) return error.InvalidFormat;
|
if (elf_version != 1) return error.InvalidFormat;
|
||||||
|
|
||||||
if (elf.is_64) {
|
if (elf.is_64) {
|
||||||
elf.entry_addr = try in.readInt(elf.endian, u64);
|
elf.entry_addr = try in.readInt(u64, elf.endian);
|
||||||
elf.program_header_offset = try in.readInt(elf.endian, u64);
|
elf.program_header_offset = try in.readInt(u64, elf.endian);
|
||||||
elf.section_header_offset = try in.readInt(elf.endian, u64);
|
elf.section_header_offset = try in.readInt(u64, elf.endian);
|
||||||
} else {
|
} else {
|
||||||
elf.entry_addr = u64(try in.readInt(elf.endian, u32));
|
elf.entry_addr = u64(try in.readInt(u32, elf.endian));
|
||||||
elf.program_header_offset = u64(try in.readInt(elf.endian, u32));
|
elf.program_header_offset = u64(try in.readInt(u32, elf.endian));
|
||||||
elf.section_header_offset = u64(try in.readInt(elf.endian, u32));
|
elf.section_header_offset = u64(try in.readInt(u32, elf.endian));
|
||||||
}
|
}
|
||||||
|
|
||||||
// skip over flags
|
// skip over flags
|
||||||
try seekable_stream.seekForward(4);
|
try seekable_stream.seekForward(4);
|
||||||
|
|
||||||
const header_size = try in.readInt(elf.endian, u16);
|
const header_size = try in.readInt(u16, elf.endian);
|
||||||
if ((elf.is_64 and header_size != 64) or (!elf.is_64 and header_size != 52)) {
|
if ((elf.is_64 and header_size != 64) or (!elf.is_64 and header_size != 52)) {
|
||||||
return error.InvalidFormat;
|
return error.InvalidFormat;
|
||||||
}
|
}
|
||||||
|
|
||||||
const ph_entry_size = try in.readInt(elf.endian, u16);
|
const ph_entry_size = try in.readInt(u16, elf.endian);
|
||||||
const ph_entry_count = try in.readInt(elf.endian, u16);
|
const ph_entry_count = try in.readInt(u16, elf.endian);
|
||||||
const sh_entry_size = try in.readInt(elf.endian, u16);
|
const sh_entry_size = try in.readInt(u16, elf.endian);
|
||||||
const sh_entry_count = try in.readInt(elf.endian, u16);
|
const sh_entry_count = try in.readInt(u16, elf.endian);
|
||||||
elf.string_section_index = u64(try in.readInt(elf.endian, u16));
|
elf.string_section_index = u64(try in.readInt(u16, elf.endian));
|
||||||
|
|
||||||
if (elf.string_section_index >= sh_entry_count) return error.InvalidFormat;
|
if (elf.string_section_index >= sh_entry_count) return error.InvalidFormat;
|
||||||
|
|
||||||
@ -481,32 +481,32 @@ pub const Elf = struct {
|
|||||||
if (sh_entry_size != 64) return error.InvalidFormat;
|
if (sh_entry_size != 64) return error.InvalidFormat;
|
||||||
|
|
||||||
for (elf.section_headers) |*elf_section| {
|
for (elf.section_headers) |*elf_section| {
|
||||||
elf_section.name = try in.readInt(elf.endian, u32);
|
elf_section.name = try in.readInt(u32, elf.endian);
|
||||||
elf_section.sh_type = try in.readInt(elf.endian, u32);
|
elf_section.sh_type = try in.readInt(u32, elf.endian);
|
||||||
elf_section.flags = try in.readInt(elf.endian, u64);
|
elf_section.flags = try in.readInt(u64, elf.endian);
|
||||||
elf_section.addr = try in.readInt(elf.endian, u64);
|
elf_section.addr = try in.readInt(u64, elf.endian);
|
||||||
elf_section.offset = try in.readInt(elf.endian, u64);
|
elf_section.offset = try in.readInt(u64, elf.endian);
|
||||||
elf_section.size = try in.readInt(elf.endian, u64);
|
elf_section.size = try in.readInt(u64, elf.endian);
|
||||||
elf_section.link = try in.readInt(elf.endian, u32);
|
elf_section.link = try in.readInt(u32, elf.endian);
|
||||||
elf_section.info = try in.readInt(elf.endian, u32);
|
elf_section.info = try in.readInt(u32, elf.endian);
|
||||||
elf_section.addr_align = try in.readInt(elf.endian, u64);
|
elf_section.addr_align = try in.readInt(u64, elf.endian);
|
||||||
elf_section.ent_size = try in.readInt(elf.endian, u64);
|
elf_section.ent_size = try in.readInt(u64, elf.endian);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (sh_entry_size != 40) return error.InvalidFormat;
|
if (sh_entry_size != 40) return error.InvalidFormat;
|
||||||
|
|
||||||
for (elf.section_headers) |*elf_section| {
|
for (elf.section_headers) |*elf_section| {
|
||||||
// TODO (multiple occurrences) allow implicit cast from %u32 -> %u64 ?
|
// TODO (multiple occurrences) allow implicit cast from %u32 -> %u64 ?
|
||||||
elf_section.name = try in.readInt(elf.endian, u32);
|
elf_section.name = try in.readInt(u32, elf.endian);
|
||||||
elf_section.sh_type = try in.readInt(elf.endian, u32);
|
elf_section.sh_type = try in.readInt(u32, elf.endian);
|
||||||
elf_section.flags = u64(try in.readInt(elf.endian, u32));
|
elf_section.flags = u64(try in.readInt(u32, elf.endian));
|
||||||
elf_section.addr = u64(try in.readInt(elf.endian, u32));
|
elf_section.addr = u64(try in.readInt(u32, elf.endian));
|
||||||
elf_section.offset = u64(try in.readInt(elf.endian, u32));
|
elf_section.offset = u64(try in.readInt(u32, elf.endian));
|
||||||
elf_section.size = u64(try in.readInt(elf.endian, u32));
|
elf_section.size = u64(try in.readInt(u32, elf.endian));
|
||||||
elf_section.link = try in.readInt(elf.endian, u32);
|
elf_section.link = try in.readInt(u32, elf.endian);
|
||||||
elf_section.info = try in.readInt(elf.endian, u32);
|
elf_section.info = try in.readInt(u32, elf.endian);
|
||||||
elf_section.addr_align = u64(try in.readInt(elf.endian, u32));
|
elf_section.addr_align = u64(try in.readInt(u32, elf.endian));
|
||||||
elf_section.ent_size = u64(try in.readInt(elf.endian, u32));
|
elf_section.ent_size = u64(try in.readInt(u32, elf.endian));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -39,18 +39,22 @@ pub fn InStream(comptime ReadError: type) type {
|
|||||||
if (amt_read < buf.len) return error.EndOfStream;
|
if (amt_read < buf.len) return error.EndOfStream;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn readIntLe(self: *Self, comptime T: type) !T {
|
pub async fn readIntLittle(self: *Self, comptime T: type) !T {
|
||||||
return await (async self.readInt(builtin.Endian.Little, T) catch unreachable);
|
var bytes: [@sizeOf(T)]u8 = undefined;
|
||||||
|
try await (async self.readNoEof(bytes[0..]) catch unreachable);
|
||||||
|
return mem.readIntLittle(T, &bytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn readIntBe(self: *Self, comptime T: type) !T {
|
pub async fn readIntBe(self: *Self, comptime T: type) !T {
|
||||||
return await (async self.readInt(builtin.Endian.Big, T) catch unreachable);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn readInt(self: *Self, endian: builtin.Endian, comptime T: type) !T {
|
|
||||||
var bytes: [@sizeOf(T)]u8 = undefined;
|
var bytes: [@sizeOf(T)]u8 = undefined;
|
||||||
try await (async self.readNoEof(bytes[0..]) catch unreachable);
|
try await (async self.readNoEof(bytes[0..]) catch unreachable);
|
||||||
return mem.readInt(bytes, T, endian);
|
return mem.readIntBig(T, &bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn readInt(self: *Self, comptime T: type, endian: builtin.Endian) !T {
|
||||||
|
var bytes: [@sizeOf(T)]u8 = undefined;
|
||||||
|
try await (async self.readNoEof(bytes[0..]) catch unreachable);
|
||||||
|
return mem.readInt(T, &bytes, endian);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn readStruct(self: *Self, comptime T: type) !T {
|
pub async fn readStruct(self: *Self, comptime T: type) !T {
|
||||||
|
@ -42,8 +42,8 @@ fn SipHash(comptime T: type, comptime c_rounds: usize, comptime d_rounds: usize)
|
|||||||
pub fn init(key: []const u8) Self {
|
pub fn init(key: []const u8) Self {
|
||||||
debug.assert(key.len >= 16);
|
debug.assert(key.len >= 16);
|
||||||
|
|
||||||
const k0 = mem.readInt(key[0..8], u64, Endian.Little);
|
const k0 = mem.readIntSliceLittle(u64, key[0..8]);
|
||||||
const k1 = mem.readInt(key[8..16], u64, Endian.Little);
|
const k1 = mem.readIntSliceLittle(u64, key[8..16]);
|
||||||
|
|
||||||
var d = Self{
|
var d = Self{
|
||||||
.v0 = k0 ^ 0x736f6d6570736575,
|
.v0 = k0 ^ 0x736f6d6570736575,
|
||||||
@ -121,7 +121,7 @@ fn SipHash(comptime T: type, comptime c_rounds: usize, comptime d_rounds: usize)
|
|||||||
fn round(d: *Self, b: []const u8) void {
|
fn round(d: *Self, b: []const u8) void {
|
||||||
debug.assert(b.len == 8);
|
debug.assert(b.len == 8);
|
||||||
|
|
||||||
const m = mem.readInt(b[0..], u64, Endian.Little);
|
const m = mem.readIntSliceLittle(u64, b[0..]);
|
||||||
d.v3 ^= m;
|
d.v3 ^= m;
|
||||||
|
|
||||||
comptime var i: usize = 0;
|
comptime var i: usize = 0;
|
||||||
@ -162,7 +162,7 @@ fn SipHash(comptime T: type, comptime c_rounds: usize, comptime d_rounds: usize)
|
|||||||
const test_key = "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f";
|
const test_key = "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f";
|
||||||
|
|
||||||
test "siphash64-2-4 sanity" {
|
test "siphash64-2-4 sanity" {
|
||||||
const vectors = [][]const u8{
|
const vectors = [][8]u8{
|
||||||
"\x31\x0e\x0e\xdd\x47\xdb\x6f\x72", // ""
|
"\x31\x0e\x0e\xdd\x47\xdb\x6f\x72", // ""
|
||||||
"\xfd\x67\xdc\x93\xc5\x39\xf8\x74", // "\x00"
|
"\xfd\x67\xdc\x93\xc5\x39\xf8\x74", // "\x00"
|
||||||
"\x5a\x4f\xa9\xd9\x09\x80\x6c\x0d", // "\x00\x01" ... etc
|
"\x5a\x4f\xa9\xd9\x09\x80\x6c\x0d", // "\x00\x01" ... etc
|
||||||
@ -235,13 +235,13 @@ test "siphash64-2-4 sanity" {
|
|||||||
for (vectors) |vector, i| {
|
for (vectors) |vector, i| {
|
||||||
buffer[i] = @intCast(u8, i);
|
buffer[i] = @intCast(u8, i);
|
||||||
|
|
||||||
const expected = mem.readInt(vector, u64, Endian.Little);
|
const expected = mem.readIntLittle(u64, &vector);
|
||||||
debug.assert(siphash.hash(test_key, buffer[0..i]) == expected);
|
debug.assert(siphash.hash(test_key, buffer[0..i]) == expected);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
test "siphash128-2-4 sanity" {
|
test "siphash128-2-4 sanity" {
|
||||||
const vectors = [][]const u8{
|
const vectors = [][16]u8{
|
||||||
"\xa3\x81\x7f\x04\xba\x25\xa8\xe6\x6d\xf6\x72\x14\xc7\x55\x02\x93",
|
"\xa3\x81\x7f\x04\xba\x25\xa8\xe6\x6d\xf6\x72\x14\xc7\x55\x02\x93",
|
||||||
"\xda\x87\xc1\xd8\x6b\x99\xaf\x44\x34\x76\x59\x11\x9b\x22\xfc\x45",
|
"\xda\x87\xc1\xd8\x6b\x99\xaf\x44\x34\x76\x59\x11\x9b\x22\xfc\x45",
|
||||||
"\x81\x77\x22\x8d\xa4\xa4\x5d\xc7\xfc\xa3\x8b\xde\xf6\x0a\xff\xe4",
|
"\x81\x77\x22\x8d\xa4\xa4\x5d\xc7\xfc\xa3\x8b\xde\xf6\x0a\xff\xe4",
|
||||||
@ -314,7 +314,7 @@ test "siphash128-2-4 sanity" {
|
|||||||
for (vectors) |vector, i| {
|
for (vectors) |vector, i| {
|
||||||
buffer[i] = @intCast(u8, i);
|
buffer[i] = @intCast(u8, i);
|
||||||
|
|
||||||
const expected = mem.readInt(vector, u128, Endian.Little);
|
const expected = mem.readIntLittle(u128, &vector);
|
||||||
debug.assert(siphash.hash(test_key, buffer[0..i]) == expected);
|
debug.assert(siphash.hash(test_key, buffer[0..i]) == expected);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -66,7 +66,7 @@ pub const DirectAllocator = struct {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn alloc(allocator: *Allocator, n: usize, alignment: u29) ![]u8 {
|
fn alloc(allocator: *Allocator, n: usize, alignment: u29) error{OutOfMemory}![]u8 {
|
||||||
const self = @fieldParentPtr(DirectAllocator, "allocator", allocator);
|
const self = @fieldParentPtr(DirectAllocator, "allocator", allocator);
|
||||||
|
|
||||||
switch (builtin.os) {
|
switch (builtin.os) {
|
||||||
|
68
std/io.zig
68
std/io.zig
@ -152,35 +152,42 @@ pub fn InStream(comptime ReadError: type) type {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Reads a native-endian integer
|
/// Reads a native-endian integer
|
||||||
pub fn readIntNe(self: *Self, comptime T: type) !T {
|
pub fn readIntNative(self: *Self, comptime T: type) !T {
|
||||||
return self.readInt(builtin.endian, T);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn readIntLe(self: *Self, comptime T: type) !T {
|
|
||||||
var bytes: [@sizeOf(T)]u8 = undefined;
|
var bytes: [@sizeOf(T)]u8 = undefined;
|
||||||
try self.readNoEof(bytes[0..]);
|
try self.readNoEof(bytes[0..]);
|
||||||
return mem.readIntLE(T, bytes);
|
return mem.readIntSliceNative(T, bytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn readIntBe(self: *Self, comptime T: type) !T {
|
/// Reads a foreign-endian integer
|
||||||
|
pub fn readIntForeign(self: *Self, comptime T: type) !T {
|
||||||
var bytes: [@sizeOf(T)]u8 = undefined;
|
var bytes: [@sizeOf(T)]u8 = undefined;
|
||||||
try self.readNoEof(bytes[0..]);
|
try self.readNoEof(bytes[0..]);
|
||||||
return mem.readIntBE(T, bytes);
|
return mem.readIntSliceForeign(T, bytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn readInt(self: *Self, endian: builtin.Endian, comptime T: type) !T {
|
pub fn readIntLittle(self: *Self, comptime T: type) !T {
|
||||||
var bytes: [@sizeOf(T)]u8 = undefined;
|
var bytes: [@sizeOf(T)]u8 = undefined;
|
||||||
try self.readNoEof(bytes[0..]);
|
try self.readNoEof(bytes[0..]);
|
||||||
return mem.readInt(bytes, T, endian);
|
return mem.readIntSliceLittle(T, bytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn readVarInt(self: *Self, endian: builtin.Endian, comptime T: type, size: usize) !T {
|
pub fn readIntBig(self: *Self, comptime T: type) !T {
|
||||||
|
var bytes: [@sizeOf(T)]u8 = undefined;
|
||||||
|
try self.readNoEof(bytes[0..]);
|
||||||
|
return mem.readIntSliceBig(T, bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn readInt(self: *Self, comptime T: type, endian: builtin.Endian) !T {
|
||||||
|
var bytes: [@sizeOf(T)]u8 = undefined;
|
||||||
|
try self.readNoEof(bytes[0..]);
|
||||||
|
return mem.readIntSlice(T, bytes, endian);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn readVarInt(self: *Self, comptime T: type, endian: builtin.Endian, size: usize) !T {
|
||||||
assert(size <= @sizeOf(T));
|
assert(size <= @sizeOf(T));
|
||||||
assert(size <= 8);
|
var bytes: [@sizeOf(T)]u8 = undefined;
|
||||||
var input_buf: [8]u8 = undefined;
|
try self.readNoEof(bytes[0..]);
|
||||||
const input_slice = input_buf[0..size];
|
return mem.readIntSlice(T, bytes, endian);
|
||||||
try self.readNoEof(input_slice);
|
|
||||||
return mem.readInt(input_slice, T, endian);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn skipBytes(self: *Self, num_bytes: usize) !void {
|
pub fn skipBytes(self: *Self, num_bytes: usize) !void {
|
||||||
@ -229,25 +236,34 @@ pub fn OutStream(comptime WriteError: type) type {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Write a native-endian integer.
|
/// Write a native-endian integer.
|
||||||
pub fn writeIntNe(self: *Self, comptime T: type, value: T) Error!void {
|
pub fn writeIntNative(self: *Self, comptime T: type, value: T) Error!void {
|
||||||
return self.writeInt(builtin.endian, T, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn writeIntLe(self: *Self, comptime T: type, value: T) Error!void {
|
|
||||||
var bytes: [@sizeOf(T)]u8 = undefined;
|
var bytes: [@sizeOf(T)]u8 = undefined;
|
||||||
mem.writeIntLE(T, &bytes, value);
|
mem.writeIntNative(T, &bytes, value);
|
||||||
return self.writeFn(self, bytes);
|
return self.writeFn(self, bytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn writeIntBe(self: *Self, comptime T: type, value: T) Error!void {
|
/// Write a foreign-endian integer.
|
||||||
|
pub fn writeIntForeign(self: *Self, comptime T: type, value: T) Error!void {
|
||||||
var bytes: [@sizeOf(T)]u8 = undefined;
|
var bytes: [@sizeOf(T)]u8 = undefined;
|
||||||
mem.writeIntBE(T, &bytes, value);
|
mem.writeIntForeign(T, &bytes, value);
|
||||||
return self.writeFn(self, bytes);
|
return self.writeFn(self, bytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn writeInt(self: *Self, endian: builtin.Endian, comptime T: type, value: T) Error!void {
|
pub fn writeIntLittle(self: *Self, comptime T: type, value: T) Error!void {
|
||||||
var bytes: [@sizeOf(T)]u8 = undefined;
|
var bytes: [@sizeOf(T)]u8 = undefined;
|
||||||
mem.writeInt(bytes[0..], value, endian);
|
mem.writeIntLittle(T, &bytes, value);
|
||||||
|
return self.writeFn(self, bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn writeIntBig(self: *Self, comptime T: type, value: T) Error!void {
|
||||||
|
var bytes: [@sizeOf(T)]u8 = undefined;
|
||||||
|
mem.writeIntBig(T, &bytes, value);
|
||||||
|
return self.writeFn(self, bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn writeInt(self: *Self, comptime T: type, value: T, endian: builtin.Endian) Error!void {
|
||||||
|
var bytes: [@sizeOf(T)]u8 = undefined;
|
||||||
|
mem.writeInt(T, &bytes, value, endian);
|
||||||
return self.writeFn(self, bytes);
|
return self.writeFn(self, bytes);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
457
std/mem.zig
457
std/mem.zig
@ -407,186 +407,250 @@ test "mem.indexOf" {
|
|||||||
assert(lastIndexOfScalar(u8, "boo", 'o').? == 2);
|
assert(lastIndexOfScalar(u8, "boo", 'o').? == 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Reads an integer from memory with size equal to bytes.len.
|
/// Reads an integer from memory with bit count specified by T.
|
||||||
/// T specifies the return type, which must be large enough to store
|
/// The bit count of T must be evenly divisible by 8.
|
||||||
/// the result.
|
/// This function cannot fail and cannot cause undefined behavior.
|
||||||
/// See also ::readIntBE or ::readIntLE.
|
/// Assumes the endianness of memory is native. This means the function can
|
||||||
pub fn readInt(bytes: []const u8, comptime T: type, endian: builtin.Endian) T {
|
/// simply pointer cast memory.
|
||||||
if (T.bit_count == 8) {
|
pub fn readIntNative(comptime T: type, bytes: *const [@sizeOf(T)]u8) T {
|
||||||
return bytes[0];
|
comptime assert(T.bit_count % 8 == 0);
|
||||||
}
|
return @ptrCast(*align(1) const T, bytes).*;
|
||||||
var result: T = 0;
|
|
||||||
switch (endian) {
|
|
||||||
builtin.Endian.Big => {
|
|
||||||
for (bytes) |b| {
|
|
||||||
result = (result << 8) | b;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
builtin.Endian.Little => {
|
|
||||||
const ShiftType = math.Log2Int(T);
|
|
||||||
for (bytes) |b, index| {
|
|
||||||
result = result | (T(b) << @intCast(ShiftType, index * 8));
|
|
||||||
}
|
|
||||||
},
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Reads a big-endian int of type T from bytes.
|
/// Reads an integer from memory with bit count specified by T.
|
||||||
/// bytes.len must be exactly @sizeOf(T).
|
/// The bit count of T must be evenly divisible by 8.
|
||||||
pub fn readIntBE(comptime T: type, bytes: []const u8) T {
|
/// This function cannot fail and cannot cause undefined behavior.
|
||||||
if (T.is_signed) {
|
/// Assumes the endianness of memory is foreign, so it must byte-swap.
|
||||||
return @bitCast(T, readIntBE(@IntType(false, T.bit_count), bytes));
|
pub fn readIntForeign(comptime T: type, bytes: *const [@sizeOf(T)]u8) T {
|
||||||
}
|
comptime assert(T.bit_count % 8 == 0);
|
||||||
assert(bytes.len == @sizeOf(T));
|
return @bswap(T, @ptrCast(*align(1) const T, bytes).*);
|
||||||
if (T == u8) return bytes[0];
|
|
||||||
var result: T = 0;
|
|
||||||
{
|
|
||||||
comptime var i = 0;
|
|
||||||
inline while (i < @sizeOf(T)) : (i += 1) {
|
|
||||||
result = (result << 8) | T(bytes[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Reads a little-endian int of type T from bytes.
|
pub const readIntLittle = switch (builtin.endian) {
|
||||||
/// bytes.len must be exactly @sizeOf(T).
|
builtin.Endian.Little => readIntNative,
|
||||||
pub fn readIntLE(comptime T: type, bytes: []const u8) T {
|
builtin.Endian.Big => readIntForeign,
|
||||||
if (T.is_signed) {
|
};
|
||||||
return @bitCast(T, readIntLE(@IntType(false, T.bit_count), bytes));
|
|
||||||
}
|
pub const readIntBig = switch (builtin.endian) {
|
||||||
assert(bytes.len == @sizeOf(T));
|
builtin.Endian.Little => readIntForeign,
|
||||||
if (T == u8) return bytes[0];
|
builtin.Endian.Big => readIntNative,
|
||||||
var result: T = 0;
|
};
|
||||||
{
|
|
||||||
comptime var i = 0;
|
/// Asserts that bytes.len >= @sizeOf(T). Reads the integer starting from index 0
|
||||||
inline while (i < @sizeOf(T)) : (i += 1) {
|
/// and ignores extra bytes.
|
||||||
result |= T(bytes[i]) << i * 8;
|
/// Note that @sizeOf(u24) is 3.
|
||||||
}
|
/// The bit count of T must be evenly divisible by 8.
|
||||||
}
|
/// Assumes the endianness of memory is native. This means the function can
|
||||||
return result;
|
/// simply pointer cast memory.
|
||||||
|
pub fn readIntSliceNative(comptime T: type, bytes: []const u8) T {
|
||||||
|
assert(@sizeOf(u24) == 3);
|
||||||
|
assert(bytes.len >= @sizeOf(T));
|
||||||
|
// TODO https://github.com/ziglang/zig/issues/863
|
||||||
|
return readIntNative(T, @ptrCast(*const [@sizeOf(T)]u8, bytes.ptr));
|
||||||
}
|
}
|
||||||
|
|
||||||
test "readIntBE/LE" {
|
/// Asserts that bytes.len >= @sizeOf(T). Reads the integer starting from index 0
|
||||||
assert(readIntBE(u0, []u8{}) == 0x0);
|
/// and ignores extra bytes.
|
||||||
assert(readIntLE(u0, []u8{}) == 0x0);
|
/// Note that @sizeOf(u24) is 3.
|
||||||
|
/// The bit count of T must be evenly divisible by 8.
|
||||||
assert(readIntBE(u8, []u8{0x32}) == 0x32);
|
/// Assumes the endianness of memory is foreign, so it must byte-swap.
|
||||||
assert(readIntLE(u8, []u8{0x12}) == 0x12);
|
pub fn readIntSliceForeign(comptime T: type, bytes: []const u8) T {
|
||||||
|
assert(@sizeOf(u24) == 3);
|
||||||
assert(readIntBE(u16, []u8{ 0x12, 0x34 }) == 0x1234);
|
assert(bytes.len >= @sizeOf(T));
|
||||||
assert(readIntLE(u16, []u8{ 0x12, 0x34 }) == 0x3412);
|
// TODO https://github.com/ziglang/zig/issues/863
|
||||||
|
return readIntForeign(T, @ptrCast(*const [@sizeOf(T)]u8, bytes.ptr));
|
||||||
assert(readIntBE(u72, []u8{ 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x24 }) == 0x123456789abcdef024);
|
|
||||||
assert(readIntLE(u72, []u8{ 0xec, 0x10, 0x32, 0x54, 0x76, 0x98, 0xba, 0xdc, 0xfe }) == 0xfedcba9876543210ec);
|
|
||||||
|
|
||||||
assert(readIntBE(i8, []u8{0xff}) == -1);
|
|
||||||
assert(readIntLE(i8, []u8{0xfe}) == -2);
|
|
||||||
|
|
||||||
assert(readIntBE(i16, []u8{ 0xff, 0xfd }) == -3);
|
|
||||||
assert(readIntLE(i16, []u8{ 0xfc, 0xff }) == -4);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Writes an integer to memory with size equal to bytes.len. Pads with zeroes
|
pub const readIntSliceLittle = switch (builtin.endian) {
|
||||||
/// to fill the entire buffer provided.
|
builtin.Endian.Little => readIntSliceNative,
|
||||||
/// value must be an integer.
|
builtin.Endian.Big => readIntSliceForeign,
|
||||||
pub fn writeInt(buf: []u8, value: var, endian: builtin.Endian) void {
|
};
|
||||||
const uint = @IntType(false, @typeOf(value).bit_count);
|
|
||||||
|
pub const readIntSliceBig = switch (builtin.endian) {
|
||||||
|
builtin.Endian.Little => readIntSliceForeign,
|
||||||
|
builtin.Endian.Big => readIntSliceNative,
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Reads an integer from memory with bit count specified by T.
|
||||||
|
/// The bit count of T must be evenly divisible by 8.
|
||||||
|
/// This function cannot fail and cannot cause undefined behavior.
|
||||||
|
pub fn readInt(comptime T: type, bytes: *const [@sizeOf(T)]u8, endian: builtin.Endian) T {
|
||||||
|
if (endian == builtin.endian) {
|
||||||
|
return readIntNative(T, bytes);
|
||||||
|
} else {
|
||||||
|
return readIntForeign(T, bytes);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Asserts that bytes.len >= @sizeOf(T). Reads the integer starting from index 0
|
||||||
|
/// and ignores extra bytes.
|
||||||
|
/// Note that @sizeOf(u24) is 3.
|
||||||
|
/// The bit count of T must be evenly divisible by 8.
|
||||||
|
pub fn readIntSlice(comptime T: type, bytes: []const u8, endian: builtin.Endian) T {
|
||||||
|
assert(@sizeOf(u24) == 3);
|
||||||
|
assert(bytes.len >= @sizeOf(T));
|
||||||
|
// TODO https://github.com/ziglang/zig/issues/863
|
||||||
|
return readInt(T, @ptrCast(*const [@sizeOf(T)]u8, bytes.ptr), endian);
|
||||||
|
}
|
||||||
|
|
||||||
|
test "readIntBig and readIntLittle" {
|
||||||
|
assert(readIntSliceBig(u0, []u8{}) == 0x0);
|
||||||
|
assert(readIntSliceLittle(u0, []u8{}) == 0x0);
|
||||||
|
|
||||||
|
assert(readIntSliceBig(u8, []u8{0x32}) == 0x32);
|
||||||
|
assert(readIntSliceLittle(u8, []u8{0x12}) == 0x12);
|
||||||
|
|
||||||
|
assert(readIntSliceBig(u16, []u8{ 0x12, 0x34 }) == 0x1234);
|
||||||
|
assert(readIntSliceLittle(u16, []u8{ 0x12, 0x34 }) == 0x3412);
|
||||||
|
|
||||||
|
assert(readIntSliceBig(u72, []u8{ 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x24 }) == 0x123456789abcdef024);
|
||||||
|
assert(readIntSliceLittle(u72, []u8{ 0xec, 0x10, 0x32, 0x54, 0x76, 0x98, 0xba, 0xdc, 0xfe }) == 0xfedcba9876543210ec);
|
||||||
|
|
||||||
|
assert(readIntSliceBig(i8, []u8{0xff}) == -1);
|
||||||
|
assert(readIntSliceLittle(i8, []u8{0xfe}) == -2);
|
||||||
|
|
||||||
|
assert(readIntSliceBig(i16, []u8{ 0xff, 0xfd }) == -3);
|
||||||
|
assert(readIntSliceLittle(i16, []u8{ 0xfc, 0xff }) == -4);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Writes an integer to memory, storing it in twos-complement.
|
||||||
|
/// This function always succeeds, has defined behavior for all inputs, and
|
||||||
|
/// accepts any integer bit width.
|
||||||
|
/// This function stores in native endian, which means it is implemented as a simple
|
||||||
|
/// memory store.
|
||||||
|
pub fn writeIntNative(comptime T: type, buf: *[@sizeOf(T)]u8, value: T) void {
|
||||||
|
@ptrCast(*align(1) T, buf).* = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Writes an integer to memory, storing it in twos-complement.
|
||||||
|
/// This function always succeeds, has defined behavior for all inputs, but
|
||||||
|
/// the integer bit width must be divisible by 8.
|
||||||
|
/// This function stores in foreign endian, which means it does a @bswap first.
|
||||||
|
pub fn writeIntForeign(comptime T: type, buf: *[@sizeOf(T)]u8, value: T) void {
|
||||||
|
@ptrCast(*align(1) T, buf).* = @bswap(T, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub const writeIntLittle = switch (builtin.endian) {
|
||||||
|
builtin.Endian.Little => writeIntNative,
|
||||||
|
builtin.Endian.Big => writeIntForeign,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const writeIntBig = switch (builtin.endian) {
|
||||||
|
builtin.Endian.Little => writeIntForeign,
|
||||||
|
builtin.Endian.Big => writeIntNative,
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Writes an integer to memory, storing it in twos-complement.
|
||||||
|
/// This function always succeeds, has defined behavior for all inputs, but
|
||||||
|
/// the integer bit width must be divisible by 8.
|
||||||
|
pub fn writeInt(comptime T: type, buffer: *[@sizeOf(T)]u8, value: T, endian: builtin.Endian) void {
|
||||||
|
comptime assert(T.bit_count % 8 == 0);
|
||||||
|
if (endian == builtin.endian) {
|
||||||
|
return writeIntNative(T, buffer, value);
|
||||||
|
} else {
|
||||||
|
return writeIntForeign(T, buffer, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Writes a twos-complement little-endian integer to memory.
|
||||||
|
/// Asserts that buf.len >= @sizeOf(T). Note that @sizeOf(u24) is 3.
|
||||||
|
/// The bit count of T must be divisible by 8.
|
||||||
|
/// 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 {
|
||||||
|
comptime assert(@sizeOf(u24) == 3);
|
||||||
|
comptime assert(T.bit_count % 8 == 0);
|
||||||
|
assert(buffer.len >= @sizeOf(T));
|
||||||
|
|
||||||
|
// TODO I want to call writeIntLittle here but comptime eval facilities aren't good enough
|
||||||
|
const uint = @IntType(false, T.bit_count);
|
||||||
var bits = @truncate(uint, value);
|
var bits = @truncate(uint, value);
|
||||||
switch (endian) {
|
for (buffer) |*b| {
|
||||||
builtin.Endian.Big => {
|
|
||||||
var index: usize = buf.len;
|
|
||||||
while (index != 0) {
|
|
||||||
index -= 1;
|
|
||||||
|
|
||||||
buf[index] = @truncate(u8, bits);
|
|
||||||
bits >>= 8;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
builtin.Endian.Little => {
|
|
||||||
for (buf) |*b| {
|
|
||||||
b.* = @truncate(u8, bits);
|
|
||||||
bits >>= 8;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
}
|
|
||||||
assert(bits == 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn writeIntBE(comptime T: type, buf: *[@sizeOf(T)]u8, value: T) void {
|
|
||||||
assert(T.bit_count % 8 == 0);
|
|
||||||
const uint = @IntType(false, T.bit_count);
|
|
||||||
if (uint == u0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
var bits = @bitCast(uint, value);
|
|
||||||
if (uint == u8) {
|
|
||||||
buf[0] = bits;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
var index: usize = buf.len;
|
|
||||||
while (index != 0) {
|
|
||||||
index -= 1;
|
|
||||||
|
|
||||||
buf[index] = @truncate(u8, bits);
|
|
||||||
bits >>= 8;
|
|
||||||
}
|
|
||||||
assert(bits == 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn writeIntLE(comptime T: type, buf: *[@sizeOf(T)]u8, value: T) void {
|
|
||||||
assert(T.bit_count % 8 == 0);
|
|
||||||
const uint = @IntType(false, T.bit_count);
|
|
||||||
if (uint == u0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
var bits = @bitCast(uint, value);
|
|
||||||
if (uint == u8) {
|
|
||||||
buf[0] = bits;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
for (buf) |*b| {
|
|
||||||
b.* = @truncate(u8, bits);
|
b.* = @truncate(u8, bits);
|
||||||
bits >>= 8;
|
bits >>= 8;
|
||||||
}
|
}
|
||||||
assert(bits == 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
test "writeIntBE/LE" {
|
/// Writes a twos-complement big-endian integer to memory.
|
||||||
|
/// Asserts that buffer.len >= @sizeOf(T). Note that @sizeOf(u24) is 3.
|
||||||
|
/// 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 {
|
||||||
|
comptime assert(@sizeOf(u24) == 3);
|
||||||
|
comptime assert(T.bit_count % 8 == 0);
|
||||||
|
assert(buffer.len >= @sizeOf(T));
|
||||||
|
|
||||||
|
// TODO I want to call writeIntBig here but comptime eval facilities aren't good enough
|
||||||
|
const uint = @IntType(false, T.bit_count);
|
||||||
|
var bits = @truncate(uint, value);
|
||||||
|
var index: usize = buffer.len;
|
||||||
|
while (index != 0) {
|
||||||
|
index -= 1;
|
||||||
|
buffer[index] = @truncate(u8, bits);
|
||||||
|
bits >>= 8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub const writeIntSliceNative = switch (builtin.endian) {
|
||||||
|
builtin.Endian.Little => writeIntSliceLittle,
|
||||||
|
builtin.Endian.Big => writeIntSliceBig,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const writeIntSliceForeign = switch (builtin.endian) {
|
||||||
|
builtin.Endian.Little => writeIntSliceBig,
|
||||||
|
builtin.Endian.Big => writeIntSliceLittle,
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Writes a twos-complement integer to memory, with the specified endianness.
|
||||||
|
/// Asserts that buf.len >= @sizeOf(T). Note that @sizeOf(u24) is 3.
|
||||||
|
/// The bit count of T must be evenly divisible by 8.
|
||||||
|
/// Any extra bytes in buffer not part of the integer are set to zero, with
|
||||||
|
/// respect to endianness. To avoid the branch to check for extra buffer bytes,
|
||||||
|
/// use writeInt instead.
|
||||||
|
pub fn writeIntSlice(comptime T: type, buffer: []u8, value: T, endian: builtin.Endian) void {
|
||||||
|
comptime assert(T.bit_count % 8 == 0);
|
||||||
|
switch (endian) {
|
||||||
|
builtin.Endian.Little => return writeIntSliceLittle(T, buffer, value),
|
||||||
|
builtin.Endian.Big => return writeIntSliceBig(T, buffer, value),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
test "writeIntBig and writeIntLittle" {
|
||||||
var buf0: [0]u8 = undefined;
|
var buf0: [0]u8 = undefined;
|
||||||
var buf1: [1]u8 = undefined;
|
var buf1: [1]u8 = undefined;
|
||||||
var buf2: [2]u8 = undefined;
|
var buf2: [2]u8 = undefined;
|
||||||
var buf9: [9]u8 = undefined;
|
var buf9: [9]u8 = undefined;
|
||||||
|
|
||||||
writeIntBE(u0, &buf0, 0x0);
|
writeIntBig(u0, &buf0, 0x0);
|
||||||
assert(eql_slice_u8(buf0[0..], []u8{}));
|
assert(eql_slice_u8(buf0[0..], []u8{}));
|
||||||
writeIntLE(u0, &buf0, 0x0);
|
writeIntLittle(u0, &buf0, 0x0);
|
||||||
assert(eql_slice_u8(buf0[0..], []u8{}));
|
assert(eql_slice_u8(buf0[0..], []u8{}));
|
||||||
|
|
||||||
writeIntBE(u8, &buf1, 0x12);
|
writeIntBig(u8, &buf1, 0x12);
|
||||||
assert(eql_slice_u8(buf1[0..], []u8{0x12}));
|
assert(eql_slice_u8(buf1[0..], []u8{0x12}));
|
||||||
writeIntLE(u8, &buf1, 0x34);
|
writeIntLittle(u8, &buf1, 0x34);
|
||||||
assert(eql_slice_u8(buf1[0..], []u8{0x34}));
|
assert(eql_slice_u8(buf1[0..], []u8{0x34}));
|
||||||
|
|
||||||
writeIntBE(u16, &buf2, 0x1234);
|
writeIntBig(u16, &buf2, 0x1234);
|
||||||
assert(eql_slice_u8(buf2[0..], []u8{ 0x12, 0x34 }));
|
assert(eql_slice_u8(buf2[0..], []u8{ 0x12, 0x34 }));
|
||||||
writeIntLE(u16, &buf2, 0x5678);
|
writeIntLittle(u16, &buf2, 0x5678);
|
||||||
assert(eql_slice_u8(buf2[0..], []u8{ 0x78, 0x56 }));
|
assert(eql_slice_u8(buf2[0..], []u8{ 0x78, 0x56 }));
|
||||||
|
|
||||||
writeIntBE(u72, &buf9, 0x123456789abcdef024);
|
writeIntBig(u72, &buf9, 0x123456789abcdef024);
|
||||||
assert(eql_slice_u8(buf9[0..], []u8{ 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x24 }));
|
assert(eql_slice_u8(buf9[0..], []u8{ 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x24 }));
|
||||||
writeIntLE(u72, &buf9, 0xfedcba9876543210ec);
|
writeIntLittle(u72, &buf9, 0xfedcba9876543210ec);
|
||||||
assert(eql_slice_u8(buf9[0..], []u8{ 0xec, 0x10, 0x32, 0x54, 0x76, 0x98, 0xba, 0xdc, 0xfe }));
|
assert(eql_slice_u8(buf9[0..], []u8{ 0xec, 0x10, 0x32, 0x54, 0x76, 0x98, 0xba, 0xdc, 0xfe }));
|
||||||
|
|
||||||
writeIntBE(i8, &buf1, -1);
|
writeIntBig(i8, &buf1, -1);
|
||||||
assert(eql_slice_u8(buf1[0..], []u8{0xff}));
|
assert(eql_slice_u8(buf1[0..], []u8{0xff}));
|
||||||
writeIntLE(i8, &buf1, -2);
|
writeIntLittle(i8, &buf1, -2);
|
||||||
assert(eql_slice_u8(buf1[0..], []u8{0xfe}));
|
assert(eql_slice_u8(buf1[0..], []u8{0xfe}));
|
||||||
|
|
||||||
writeIntBE(i16, &buf2, -3);
|
writeIntBig(i16, &buf2, -3);
|
||||||
assert(eql_slice_u8(buf2[0..], []u8{ 0xff, 0xfd }));
|
assert(eql_slice_u8(buf2[0..], []u8{ 0xff, 0xfd }));
|
||||||
writeIntLE(i16, &buf2, -4);
|
writeIntLittle(i16, &buf2, -4);
|
||||||
assert(eql_slice_u8(buf2[0..], []u8{ 0xfc, 0xff }));
|
assert(eql_slice_u8(buf2[0..], []u8{ 0xfc, 0xff }));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -735,12 +799,12 @@ fn testReadIntImpl() void {
|
|||||||
0x56,
|
0x56,
|
||||||
0x78,
|
0x78,
|
||||||
};
|
};
|
||||||
assert(readInt(bytes, u32, builtin.Endian.Big) == 0x12345678);
|
assert(readInt(u32, &bytes, builtin.Endian.Big) == 0x12345678);
|
||||||
assert(readIntBE(u32, bytes) == 0x12345678);
|
assert(readIntBig(u32, &bytes) == 0x12345678);
|
||||||
assert(readIntBE(i32, bytes) == 0x12345678);
|
assert(readIntBig(i32, &bytes) == 0x12345678);
|
||||||
assert(readInt(bytes, u32, builtin.Endian.Little) == 0x78563412);
|
assert(readInt(u32, &bytes, builtin.Endian.Little) == 0x78563412);
|
||||||
assert(readIntLE(u32, bytes) == 0x78563412);
|
assert(readIntLittle(u32, &bytes) == 0x78563412);
|
||||||
assert(readIntLE(i32, bytes) == 0x78563412);
|
assert(readIntLittle(i32, &bytes) == 0x78563412);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
const buf = []u8{
|
const buf = []u8{
|
||||||
@ -749,7 +813,7 @@ fn testReadIntImpl() void {
|
|||||||
0x12,
|
0x12,
|
||||||
0x34,
|
0x34,
|
||||||
};
|
};
|
||||||
const answer = readInt(buf, u64, builtin.Endian.Big);
|
const answer = readInt(u32, &buf, builtin.Endian.Big);
|
||||||
assert(answer == 0x00001234);
|
assert(answer == 0x00001234);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
@ -759,7 +823,7 @@ fn testReadIntImpl() void {
|
|||||||
0x00,
|
0x00,
|
||||||
0x00,
|
0x00,
|
||||||
};
|
};
|
||||||
const answer = readInt(buf, u64, builtin.Endian.Little);
|
const answer = readInt(u32, &buf, builtin.Endian.Little);
|
||||||
assert(answer == 0x00003412);
|
assert(answer == 0x00003412);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
@ -767,21 +831,33 @@ fn testReadIntImpl() void {
|
|||||||
0xff,
|
0xff,
|
||||||
0xfe,
|
0xfe,
|
||||||
};
|
};
|
||||||
assert(readIntBE(u16, bytes) == 0xfffe);
|
assert(readIntBig(u16, &bytes) == 0xfffe);
|
||||||
assert(readIntBE(i16, bytes) == -0x0002);
|
assert(readIntBig(i16, &bytes) == -0x0002);
|
||||||
assert(readIntLE(u16, bytes) == 0xfeff);
|
assert(readIntLittle(u16, &bytes) == 0xfeff);
|
||||||
assert(readIntLE(i16, bytes) == -0x0101);
|
assert(readIntLittle(i16, &bytes) == -0x0101);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
test "testWriteInt" {
|
test "std.mem.writeIntSlice" {
|
||||||
testWriteIntImpl();
|
testWriteIntImpl();
|
||||||
comptime testWriteIntImpl();
|
comptime testWriteIntImpl();
|
||||||
}
|
}
|
||||||
fn testWriteIntImpl() void {
|
fn testWriteIntImpl() void {
|
||||||
var bytes: [8]u8 = undefined;
|
var bytes: [8]u8 = undefined;
|
||||||
|
|
||||||
writeInt(bytes[0..], u64(0x12345678CAFEBABE), builtin.Endian.Big);
|
writeIntSlice(u0, bytes[0..], 0, builtin.Endian.Big);
|
||||||
|
assert(eql(u8, bytes, []u8{
|
||||||
|
0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00,
|
||||||
|
}));
|
||||||
|
|
||||||
|
writeIntSlice(u0, bytes[0..], 0, builtin.Endian.Little);
|
||||||
|
assert(eql(u8, bytes, []u8{
|
||||||
|
0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00,
|
||||||
|
}));
|
||||||
|
|
||||||
|
writeIntSlice(u64, bytes[0..], 0x12345678CAFEBABE, builtin.Endian.Big);
|
||||||
assert(eql(u8, bytes, []u8{
|
assert(eql(u8, bytes, []u8{
|
||||||
0x12,
|
0x12,
|
||||||
0x34,
|
0x34,
|
||||||
@ -793,7 +869,7 @@ fn testWriteIntImpl() void {
|
|||||||
0xBE,
|
0xBE,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
writeInt(bytes[0..], u64(0xBEBAFECA78563412), builtin.Endian.Little);
|
writeIntSlice(u64, bytes[0..], 0xBEBAFECA78563412, builtin.Endian.Little);
|
||||||
assert(eql(u8, bytes, []u8{
|
assert(eql(u8, bytes, []u8{
|
||||||
0x12,
|
0x12,
|
||||||
0x34,
|
0x34,
|
||||||
@ -805,7 +881,7 @@ fn testWriteIntImpl() void {
|
|||||||
0xBE,
|
0xBE,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
writeInt(bytes[0..], u32(0x12345678), builtin.Endian.Big);
|
writeIntSlice(u32, bytes[0..], 0x12345678, builtin.Endian.Big);
|
||||||
assert(eql(u8, bytes, []u8{
|
assert(eql(u8, bytes, []u8{
|
||||||
0x00,
|
0x00,
|
||||||
0x00,
|
0x00,
|
||||||
@ -817,7 +893,7 @@ fn testWriteIntImpl() void {
|
|||||||
0x78,
|
0x78,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
writeInt(bytes[0..], u32(0x78563412), builtin.Endian.Little);
|
writeIntSlice(u32, bytes[0..], 0x78563412, builtin.Endian.Little);
|
||||||
assert(eql(u8, bytes, []u8{
|
assert(eql(u8, bytes, []u8{
|
||||||
0x12,
|
0x12,
|
||||||
0x34,
|
0x34,
|
||||||
@ -829,7 +905,7 @@ fn testWriteIntImpl() void {
|
|||||||
0x00,
|
0x00,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
writeInt(bytes[0..], u16(0x1234), builtin.Endian.Big);
|
writeIntSlice(u16, bytes[0..], 0x1234, builtin.Endian.Big);
|
||||||
assert(eql(u8, bytes, []u8{
|
assert(eql(u8, bytes, []u8{
|
||||||
0x00,
|
0x00,
|
||||||
0x00,
|
0x00,
|
||||||
@ -841,7 +917,7 @@ fn testWriteIntImpl() void {
|
|||||||
0x34,
|
0x34,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
writeInt(bytes[0..], u16(0x1234), builtin.Endian.Little);
|
writeIntSlice(u16, bytes[0..], 0x1234, builtin.Endian.Little);
|
||||||
assert(eql(u8, bytes, []u8{
|
assert(eql(u8, bytes, []u8{
|
||||||
0x34,
|
0x34,
|
||||||
0x12,
|
0x12,
|
||||||
@ -939,29 +1015,52 @@ test "std.mem.rotate" {
|
|||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: When https://github.com/ziglang/zig/issues/649 is solved these can be done by
|
/// Converts a little-endian integer to host endianness.
|
||||||
// endian-casting the pointer and then dereferencing
|
pub fn littleToNative(comptime T: type, x: T) T {
|
||||||
|
return switch (builtin.endian) {
|
||||||
pub fn endianSwapIfLe(comptime T: type, x: T) T {
|
builtin.Endian.Little => x,
|
||||||
return endianSwapIf(builtin.Endian.Little, T, x);
|
builtin.Endian.Big => @bswap(T, x),
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn endianSwapIfBe(comptime T: type, x: T) T {
|
/// Converts a big-endian integer to host endianness.
|
||||||
return endianSwapIf(builtin.Endian.Big, T, x);
|
pub fn bigToNative(comptime T: type, x: T) T {
|
||||||
|
return switch (builtin.endian) {
|
||||||
|
builtin.Endian.Little => @bswap(T, x),
|
||||||
|
builtin.Endian.Big => x,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn endianSwapIf(endian: builtin.Endian, comptime T: type, x: T) T {
|
/// Converts an integer from specified endianness to host endianness.
|
||||||
return if (builtin.endian == endian) endianSwap(T, x) else x;
|
pub fn toNative(comptime T: type, x: T, endianness_of_x: builtin.Endian) T {
|
||||||
|
return switch (endianness_of_x) {
|
||||||
|
builtin.Endian.Little => littleToNative(T, x),
|
||||||
|
builtin.Endian.Big => bigToNative(T, x),
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn endianSwap(comptime T: type, x: T) T {
|
/// Converts an integer which has host endianness to the desired endianness.
|
||||||
var buf: [@sizeOf(T)]u8 = undefined;
|
pub fn nativeTo(comptime T: type, x: T, desired_endianness: builtin.Endian) T {
|
||||||
mem.writeInt(buf[0..], x, builtin.Endian.Little);
|
return switch (desired_endianness) {
|
||||||
return mem.readInt(buf, T, builtin.Endian.Big);
|
builtin.Endian.Little => nativeToLittle(T, x),
|
||||||
|
builtin.Endian.Big => nativeToBig(T, x),
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
test "std.mem.endianSwap" {
|
/// Converts an integer which has host endianness to little endian.
|
||||||
assert(endianSwap(u32, 0xDEADBEEF) == 0xEFBEADDE);
|
pub fn nativeToLittle(comptime T: type, x: T) T {
|
||||||
|
return switch (builtin.endian) {
|
||||||
|
builtin.Endian.Little => x,
|
||||||
|
builtin.Endian.Big => @bswap(T, x),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Converts an integer which has host endianness to big endian.
|
||||||
|
pub fn nativeToBig(comptime T: type, x: T) T {
|
||||||
|
return switch (builtin.endian) {
|
||||||
|
builtin.Endian.Little => @bswap(T, x),
|
||||||
|
builtin.Endian.Big => x,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
fn AsBytesReturnType(comptime P: type) type {
|
fn AsBytesReturnType(comptime P: type) type {
|
||||||
|
12
std/net.zig
12
std/net.zig
@ -23,7 +23,7 @@ pub const Address = struct {
|
|||||||
.os_addr = posix.sockaddr{
|
.os_addr = posix.sockaddr{
|
||||||
.in = posix.sockaddr_in{
|
.in = posix.sockaddr_in{
|
||||||
.family = posix.AF_INET,
|
.family = posix.AF_INET,
|
||||||
.port = std.mem.endianSwapIfLe(u16, _port),
|
.port = mem.nativeToBig(u16, _port),
|
||||||
.addr = ip4,
|
.addr = ip4,
|
||||||
.zero = []u8{0} ** 8,
|
.zero = []u8{0} ** 8,
|
||||||
},
|
},
|
||||||
@ -37,7 +37,7 @@ pub const Address = struct {
|
|||||||
.os_addr = posix.sockaddr{
|
.os_addr = posix.sockaddr{
|
||||||
.in6 = posix.sockaddr_in6{
|
.in6 = posix.sockaddr_in6{
|
||||||
.family = posix.AF_INET6,
|
.family = posix.AF_INET6,
|
||||||
.port = std.mem.endianSwapIfLe(u16, _port),
|
.port = mem.nativeToBig(u16, _port),
|
||||||
.flowinfo = 0,
|
.flowinfo = 0,
|
||||||
.addr = ip6.addr,
|
.addr = ip6.addr,
|
||||||
.scope_id = ip6.scope_id,
|
.scope_id = ip6.scope_id,
|
||||||
@ -47,7 +47,7 @@ pub const Address = struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn port(self: Address) u16 {
|
pub fn port(self: Address) u16 {
|
||||||
return std.mem.endianSwapIfLe(u16, self.os_addr.in.port);
|
return mem.bigToNative(u16, self.os_addr.in.port);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn initPosix(addr: posix.sockaddr) Address {
|
pub fn initPosix(addr: posix.sockaddr) Address {
|
||||||
@ -57,12 +57,12 @@ pub const Address = struct {
|
|||||||
pub fn format(self: *const Address, out_stream: var) !void {
|
pub fn format(self: *const Address, out_stream: var) !void {
|
||||||
switch (self.os_addr.in.family) {
|
switch (self.os_addr.in.family) {
|
||||||
posix.AF_INET => {
|
posix.AF_INET => {
|
||||||
const native_endian_port = std.mem.endianSwapIfLe(u16, self.os_addr.in.port);
|
const native_endian_port = mem.bigToNative(u16, self.os_addr.in.port);
|
||||||
const bytes = ([]const u8)((*self.os_addr.in.addr)[0..1]);
|
const bytes = ([]const u8)((*self.os_addr.in.addr)[0..1]);
|
||||||
try out_stream.print("{}.{}.{}.{}:{}", bytes[0], bytes[1], bytes[2], bytes[3], native_endian_port);
|
try out_stream.print("{}.{}.{}.{}:{}", bytes[0], bytes[1], bytes[2], bytes[3], native_endian_port);
|
||||||
},
|
},
|
||||||
posix.AF_INET6 => {
|
posix.AF_INET6 => {
|
||||||
const native_endian_port = std.mem.endianSwapIfLe(u16, self.os_addr.in6.port);
|
const native_endian_port = mem.bigToNative(u16, self.os_addr.in6.port);
|
||||||
try out_stream.print("[TODO render ip6 address]:{}", native_endian_port);
|
try out_stream.print("[TODO render ip6 address]:{}", native_endian_port);
|
||||||
},
|
},
|
||||||
else => try out_stream.write("(unrecognized address family)"),
|
else => try out_stream.write("(unrecognized address family)"),
|
||||||
@ -193,7 +193,7 @@ pub fn parseIp6(buf: []const u8) !Ip6Addr {
|
|||||||
}
|
}
|
||||||
|
|
||||||
test "std.net.parseIp4" {
|
test "std.net.parseIp4" {
|
||||||
assert((try parseIp4("127.0.0.1")) == std.mem.endianSwapIfLe(u32, 0x7f000001));
|
assert((try parseIp4("127.0.0.1")) == mem.bigToNative(u32, 0x7f000001));
|
||||||
|
|
||||||
testParseIp4Fail("256.0.0.1", error.Overflow);
|
testParseIp4Fail("256.0.0.1", error.Overflow);
|
||||||
testParseIp4Fail("x.0.0.1", error.InvalidCharacter);
|
testParseIp4Fail("x.0.0.1", error.InvalidCharacter);
|
||||||
|
@ -807,10 +807,10 @@ const ErrInt = @IntType(false, @sizeOf(anyerror) * 8);
|
|||||||
|
|
||||||
fn writeIntFd(fd: i32, value: ErrInt) !void {
|
fn writeIntFd(fd: i32, value: ErrInt) !void {
|
||||||
const stream = &os.File.openHandle(fd).outStream().stream;
|
const stream = &os.File.openHandle(fd).outStream().stream;
|
||||||
stream.writeIntNe(ErrInt, value) catch return error.SystemResources;
|
stream.writeIntNative(ErrInt, value) catch return error.SystemResources;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn readIntFd(fd: i32) !ErrInt {
|
fn readIntFd(fd: i32) !ErrInt {
|
||||||
const stream = &os.File.openHandle(fd).inStream().stream;
|
const stream = &os.File.openHandle(fd).inStream().stream;
|
||||||
return stream.readIntNe(ErrInt) catch return error.SystemResources;
|
return stream.readIntNative(ErrInt) catch return error.SystemResources;
|
||||||
}
|
}
|
||||||
|
@ -98,12 +98,12 @@ pub nakedcc fn restore_rt() void {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub const msghdr = extern struct {
|
pub const msghdr = extern struct {
|
||||||
msg_name: &u8,
|
msg_name: *u8,
|
||||||
msg_namelen: socklen_t,
|
msg_namelen: socklen_t,
|
||||||
msg_iov: &iovec,
|
msg_iov: *iovec,
|
||||||
msg_iovlen: i32,
|
msg_iovlen: i32,
|
||||||
__pad1: i32,
|
__pad1: i32,
|
||||||
msg_control: &u8,
|
msg_control: *u8,
|
||||||
msg_controllen: socklen_t,
|
msg_controllen: socklen_t,
|
||||||
__pad2: socklen_t,
|
__pad2: socklen_t,
|
||||||
msg_flags: i32,
|
msg_flags: i32,
|
||||||
|
@ -508,11 +508,11 @@ const Msf = struct {
|
|||||||
allocator,
|
allocator,
|
||||||
);
|
);
|
||||||
|
|
||||||
const stream_count = try self.directory.stream.readIntLe(u32);
|
const stream_count = try self.directory.stream.readIntLittle(u32);
|
||||||
|
|
||||||
const stream_sizes = try allocator.alloc(u32, stream_count);
|
const stream_sizes = try allocator.alloc(u32, stream_count);
|
||||||
for (stream_sizes) |*s| {
|
for (stream_sizes) |*s| {
|
||||||
const size = try self.directory.stream.readIntLe(u32);
|
const size = try self.directory.stream.readIntLittle(u32);
|
||||||
s.* = blockCountFromSize(size, superblock.BlockSize);
|
s.* = blockCountFromSize(size, superblock.BlockSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -603,7 +603,7 @@ const MsfStream = struct {
|
|||||||
|
|
||||||
var i: u32 = 0;
|
var i: u32 = 0;
|
||||||
while (i < block_count) : (i += 1) {
|
while (i < block_count) : (i += 1) {
|
||||||
stream.blocks[i] = try in.readIntLe(u32);
|
stream.blocks[i] = try in.readIntLittle(u32);
|
||||||
}
|
}
|
||||||
|
|
||||||
return stream;
|
return stream;
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
// ```
|
// ```
|
||||||
// var buf: [8]u8 = undefined;
|
// var buf: [8]u8 = undefined;
|
||||||
// try std.os.getRandomBytes(buf[0..]);
|
// try std.os.getRandomBytes(buf[0..]);
|
||||||
// const seed = mem.readIntLE(u64, buf[0..8]);
|
// const seed = mem.readIntSliceLittle(u64, buf[0..8]);
|
||||||
//
|
//
|
||||||
// var r = DefaultPrng.init(seed);
|
// var r = DefaultPrng.init(seed);
|
||||||
//
|
//
|
||||||
@ -52,7 +52,7 @@ pub const Random = struct {
|
|||||||
// use LE instead of native endian for better portability maybe?
|
// use LE instead of native endian for better portability maybe?
|
||||||
// TODO: endian portability is pointless if the underlying prng isn't endian portable.
|
// TODO: endian portability is pointless if the underlying prng isn't endian portable.
|
||||||
// TODO: document the endian portability of this library.
|
// TODO: document the endian portability of this library.
|
||||||
const byte_aligned_result = mem.readIntLE(ByteAlignedT, rand_bytes);
|
const byte_aligned_result = mem.readIntSliceLittle(ByteAlignedT, rand_bytes);
|
||||||
const unsigned_result = @truncate(UnsignedT, byte_aligned_result);
|
const unsigned_result = @truncate(UnsignedT, byte_aligned_result);
|
||||||
return @bitCast(T, unsigned_result);
|
return @bitCast(T, unsigned_result);
|
||||||
}
|
}
|
||||||
@ -69,6 +69,7 @@ pub const Random = struct {
|
|||||||
return @intCast(T, limitRangeBiased(u64, r.int(u64), less_than));
|
return @intCast(T, limitRangeBiased(u64, r.int(u64), less_than));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns an evenly distributed random unsigned integer `0 <= i < less_than`.
|
/// Returns an evenly distributed random unsigned integer `0 <= i < less_than`.
|
||||||
/// This function assumes that the underlying ::fillFn produces evenly distributed values.
|
/// This function assumes that the underlying ::fillFn produces evenly distributed values.
|
||||||
/// Within this assumption, the runtime of this function is exponentially distributed.
|
/// Within this assumption, the runtime of this function is exponentially distributed.
|
||||||
@ -123,6 +124,7 @@ pub const Random = struct {
|
|||||||
}
|
}
|
||||||
return r.uintLessThanBiased(T, at_most + 1);
|
return r.uintLessThanBiased(T, at_most + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns an evenly distributed random unsigned integer `0 <= i <= at_most`.
|
/// Returns an evenly distributed random unsigned integer `0 <= i <= at_most`.
|
||||||
/// See ::uintLessThan, which this function uses in most cases,
|
/// See ::uintLessThan, which this function uses in most cases,
|
||||||
/// for commentary on the runtime of this function.
|
/// for commentary on the runtime of this function.
|
||||||
@ -151,6 +153,7 @@ pub const Random = struct {
|
|||||||
return at_least + r.uintLessThanBiased(T, less_than - at_least);
|
return at_least + r.uintLessThanBiased(T, less_than - at_least);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns an evenly distributed random integer `at_least <= i < less_than`.
|
/// Returns an evenly distributed random integer `at_least <= i < less_than`.
|
||||||
/// See ::uintLessThan, which this function uses in most cases,
|
/// See ::uintLessThan, which this function uses in most cases,
|
||||||
/// for commentary on the runtime of this function.
|
/// for commentary on the runtime of this function.
|
||||||
@ -185,6 +188,7 @@ pub const Random = struct {
|
|||||||
return at_least + r.uintAtMostBiased(T, at_most - at_least);
|
return at_least + r.uintAtMostBiased(T, at_most - at_least);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns an evenly distributed random integer `at_least <= i <= at_most`.
|
/// Returns an evenly distributed random integer `at_least <= i <= at_most`.
|
||||||
/// See ::uintLessThan, which this function uses in most cases,
|
/// See ::uintLessThan, which this function uses in most cases,
|
||||||
/// for commentary on the runtime of this function.
|
/// for commentary on the runtime of this function.
|
||||||
|
@ -249,12 +249,12 @@ pub const Utf16LeIterator = struct {
|
|||||||
pub fn nextCodepoint(it: *Utf16LeIterator) !?u32 {
|
pub fn nextCodepoint(it: *Utf16LeIterator) !?u32 {
|
||||||
assert(it.i <= it.bytes.len);
|
assert(it.i <= it.bytes.len);
|
||||||
if (it.i == it.bytes.len) return null;
|
if (it.i == it.bytes.len) return null;
|
||||||
const c0: u32 = mem.readIntLE(u16, it.bytes[it.i .. it.i + 2]);
|
const c0: u32 = mem.readIntSliceLittle(u16, it.bytes[it.i .. it.i + 2]);
|
||||||
if (c0 & ~u32(0x03ff) == 0xd800) {
|
if (c0 & ~u32(0x03ff) == 0xd800) {
|
||||||
// surrogate pair
|
// surrogate pair
|
||||||
it.i += 2;
|
it.i += 2;
|
||||||
if (it.i >= it.bytes.len) return error.DanglingSurrogateHalf;
|
if (it.i >= it.bytes.len) return error.DanglingSurrogateHalf;
|
||||||
const c1: u32 = mem.readIntLE(u16, it.bytes[it.i .. it.i + 2]);
|
const c1: u32 = mem.readIntSliceLittle(u16, it.bytes[it.i .. it.i + 2]);
|
||||||
if (c1 & ~u32(0x03ff) != 0xdc00) return error.ExpectedSecondSurrogateHalf;
|
if (c1 & ~u32(0x03ff) != 0xdc00) return error.ExpectedSecondSurrogateHalf;
|
||||||
it.i += 2;
|
it.i += 2;
|
||||||
return 0x10000 + (((c0 & 0x03ff) << 10) | (c1 & 0x03ff));
|
return 0x10000 + (((c0 & 0x03ff) << 10) | (c1 & 0x03ff));
|
||||||
@ -510,46 +510,46 @@ test "utf16leToUtf8" {
|
|||||||
const utf16le_as_bytes = @sliceToBytes(utf16le[0..]);
|
const utf16le_as_bytes = @sliceToBytes(utf16le[0..]);
|
||||||
|
|
||||||
{
|
{
|
||||||
mem.writeInt(utf16le_as_bytes[0..], u16('A'), builtin.Endian.Little);
|
mem.writeIntSliceLittle(u16, utf16le_as_bytes[0..], 'A');
|
||||||
mem.writeInt(utf16le_as_bytes[2..], u16('a'), builtin.Endian.Little);
|
mem.writeIntSliceLittle(u16, utf16le_as_bytes[2..], 'a');
|
||||||
const utf8 = try utf16leToUtf8Alloc(std.debug.global_allocator, utf16le);
|
const utf8 = try utf16leToUtf8Alloc(std.debug.global_allocator, utf16le);
|
||||||
assert(mem.eql(u8, utf8, "Aa"));
|
assert(mem.eql(u8, utf8, "Aa"));
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
mem.writeInt(utf16le_as_bytes[0..], u16(0x80), builtin.Endian.Little);
|
mem.writeIntSliceLittle(u16, utf16le_as_bytes[0..], 0x80);
|
||||||
mem.writeInt(utf16le_as_bytes[2..], u16(0xffff), builtin.Endian.Little);
|
mem.writeIntSliceLittle(u16, utf16le_as_bytes[2..], 0xffff);
|
||||||
const utf8 = try utf16leToUtf8Alloc(std.debug.global_allocator, utf16le);
|
const utf8 = try utf16leToUtf8Alloc(std.debug.global_allocator, utf16le);
|
||||||
assert(mem.eql(u8, utf8, "\xc2\x80" ++ "\xef\xbf\xbf"));
|
assert(mem.eql(u8, utf8, "\xc2\x80" ++ "\xef\xbf\xbf"));
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
// the values just outside the surrogate half range
|
// the values just outside the surrogate half range
|
||||||
mem.writeInt(utf16le_as_bytes[0..], u16(0xd7ff), builtin.Endian.Little);
|
mem.writeIntSliceLittle(u16, utf16le_as_bytes[0..], 0xd7ff);
|
||||||
mem.writeInt(utf16le_as_bytes[2..], u16(0xe000), builtin.Endian.Little);
|
mem.writeIntSliceLittle(u16, utf16le_as_bytes[2..], 0xe000);
|
||||||
const utf8 = try utf16leToUtf8Alloc(std.debug.global_allocator, utf16le);
|
const utf8 = try utf16leToUtf8Alloc(std.debug.global_allocator, utf16le);
|
||||||
assert(mem.eql(u8, utf8, "\xed\x9f\xbf" ++ "\xee\x80\x80"));
|
assert(mem.eql(u8, utf8, "\xed\x9f\xbf" ++ "\xee\x80\x80"));
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
// smallest surrogate pair
|
// smallest surrogate pair
|
||||||
mem.writeInt(utf16le_as_bytes[0..], u16(0xd800), builtin.Endian.Little);
|
mem.writeIntSliceLittle(u16, utf16le_as_bytes[0..], 0xd800);
|
||||||
mem.writeInt(utf16le_as_bytes[2..], u16(0xdc00), builtin.Endian.Little);
|
mem.writeIntSliceLittle(u16, utf16le_as_bytes[2..], 0xdc00);
|
||||||
const utf8 = try utf16leToUtf8Alloc(std.debug.global_allocator, utf16le);
|
const utf8 = try utf16leToUtf8Alloc(std.debug.global_allocator, utf16le);
|
||||||
assert(mem.eql(u8, utf8, "\xf0\x90\x80\x80"));
|
assert(mem.eql(u8, utf8, "\xf0\x90\x80\x80"));
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
// largest surrogate pair
|
// largest surrogate pair
|
||||||
mem.writeInt(utf16le_as_bytes[0..], u16(0xdbff), builtin.Endian.Little);
|
mem.writeIntSliceLittle(u16, utf16le_as_bytes[0..], 0xdbff);
|
||||||
mem.writeInt(utf16le_as_bytes[2..], u16(0xdfff), builtin.Endian.Little);
|
mem.writeIntSliceLittle(u16, utf16le_as_bytes[2..], 0xdfff);
|
||||||
const utf8 = try utf16leToUtf8Alloc(std.debug.global_allocator, utf16le);
|
const utf8 = try utf16leToUtf8Alloc(std.debug.global_allocator, utf16le);
|
||||||
assert(mem.eql(u8, utf8, "\xf4\x8f\xbf\xbf"));
|
assert(mem.eql(u8, utf8, "\xf4\x8f\xbf\xbf"));
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
mem.writeInt(utf16le_as_bytes[0..], u16(0xdbff), builtin.Endian.Little);
|
mem.writeIntSliceLittle(u16, utf16le_as_bytes[0..], 0xdbff);
|
||||||
mem.writeInt(utf16le_as_bytes[2..], u16(0xdc00), builtin.Endian.Little);
|
mem.writeIntSliceLittle(u16, utf16le_as_bytes[2..], 0xdc00);
|
||||||
const utf8 = try utf16leToUtf8Alloc(std.debug.global_allocator, utf16le);
|
const utf8 = try utf16leToUtf8Alloc(std.debug.global_allocator, utf16le);
|
||||||
assert(mem.eql(u8, utf8, "\xf4\x8f\xb0\x80"));
|
assert(mem.eql(u8, utf8, "\xf4\x8f\xb0\x80"));
|
||||||
}
|
}
|
||||||
@ -583,7 +583,7 @@ pub fn utf8ToUtf16Le(utf16le: []u16, utf8: []const u8) !usize {
|
|||||||
while (it.nextCodepoint()) |codepoint| {
|
while (it.nextCodepoint()) |codepoint| {
|
||||||
if (end_index == utf16le_as_bytes.len) return (end_index / 2) + 1;
|
if (end_index == utf16le_as_bytes.len) return (end_index / 2) + 1;
|
||||||
// TODO surrogate pairs
|
// TODO surrogate pairs
|
||||||
mem.writeInt(utf16le_as_bytes[end_index..], @intCast(u16, codepoint), builtin.Endian.Little);
|
mem.writeIntSliceLittle(u16, utf16le_as_bytes[end_index..], @intCast(u16, codepoint));
|
||||||
end_index += 2;
|
end_index += 2;
|
||||||
}
|
}
|
||||||
return end_index / 2;
|
return end_index / 2;
|
||||||
|
@ -8,6 +8,7 @@ comptime {
|
|||||||
_ = @import("cases/atomics.zig");
|
_ = @import("cases/atomics.zig");
|
||||||
_ = @import("cases/bitcast.zig");
|
_ = @import("cases/bitcast.zig");
|
||||||
_ = @import("cases/bool.zig");
|
_ = @import("cases/bool.zig");
|
||||||
|
_ = @import("cases/bswap.zig");
|
||||||
_ = @import("cases/bugs/1076.zig");
|
_ = @import("cases/bugs/1076.zig");
|
||||||
_ = @import("cases/bugs/1111.zig");
|
_ = @import("cases/bugs/1111.zig");
|
||||||
_ = @import("cases/bugs/1277.zig");
|
_ = @import("cases/bugs/1277.zig");
|
||||||
@ -64,6 +65,7 @@ comptime {
|
|||||||
_ = @import("cases/switch_prong_implicit_cast.zig");
|
_ = @import("cases/switch_prong_implicit_cast.zig");
|
||||||
_ = @import("cases/syntax.zig");
|
_ = @import("cases/syntax.zig");
|
||||||
_ = @import("cases/this.zig");
|
_ = @import("cases/this.zig");
|
||||||
|
_ = @import("cases/truncate.zig");
|
||||||
_ = @import("cases/try.zig");
|
_ = @import("cases/try.zig");
|
||||||
_ = @import("cases/type_info.zig");
|
_ = @import("cases/type_info.zig");
|
||||||
_ = @import("cases/undefined.zig");
|
_ = @import("cases/undefined.zig");
|
||||||
|
32
test/cases/bswap.zig
Normal file
32
test/cases/bswap.zig
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
const std = @import("std");
|
||||||
|
const assert = std.debug.assert;
|
||||||
|
|
||||||
|
test "@bswap" {
|
||||||
|
comptime testByteSwap();
|
||||||
|
testByteSwap();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn testByteSwap() void {
|
||||||
|
assert(@bswap(u0, 0) == 0);
|
||||||
|
assert(@bswap(u8, 0x12) == 0x12);
|
||||||
|
assert(@bswap(u16, 0x1234) == 0x3412);
|
||||||
|
assert(@bswap(u24, 0x123456) == 0x563412);
|
||||||
|
assert(@bswap(u32, 0x12345678) == 0x78563412);
|
||||||
|
assert(@bswap(u40, 0x123456789a) == 0x9a78563412);
|
||||||
|
assert(@bswap(u48, 0x123456789abc) == 0xbc9a78563412);
|
||||||
|
assert(@bswap(u56, 0x123456789abcde) == 0xdebc9a78563412);
|
||||||
|
assert(@bswap(u64, 0x123456789abcdef1) == 0xf1debc9a78563412);
|
||||||
|
assert(@bswap(u128, 0x123456789abcdef11121314151617181) == 0x8171615141312111f1debc9a78563412);
|
||||||
|
|
||||||
|
assert(@bswap(i0, 0) == 0);
|
||||||
|
assert(@bswap(i8, -50) == -50);
|
||||||
|
assert(@bswap(i16, @bitCast(i16, u16(0x1234))) == @bitCast(i16, u16(0x3412)));
|
||||||
|
assert(@bswap(i24, @bitCast(i24, u24(0x123456))) == @bitCast(i24, u24(0x563412)));
|
||||||
|
assert(@bswap(i32, @bitCast(i32, u32(0x12345678))) == @bitCast(i32, u32(0x78563412)));
|
||||||
|
assert(@bswap(i40, @bitCast(i40, u40(0x123456789a))) == @bitCast(i40, u40(0x9a78563412)));
|
||||||
|
assert(@bswap(i48, @bitCast(i48, u48(0x123456789abc))) == @bitCast(i48, u48(0xbc9a78563412)));
|
||||||
|
assert(@bswap(i56, @bitCast(i56, u56(0x123456789abcde))) == @bitCast(i56, u56(0xdebc9a78563412)));
|
||||||
|
assert(@bswap(i64, @bitCast(i64, u64(0x123456789abcdef1))) == @bitCast(i64, u64(0xf1debc9a78563412)));
|
||||||
|
assert(@bswap(i128, @bitCast(i128, u128(0x123456789abcdef11121314151617181))) ==
|
||||||
|
@bitCast(i128, u128(0x8171615141312111f1debc9a78563412)));
|
||||||
|
}
|
8
test/cases/truncate.zig
Normal file
8
test/cases/truncate.zig
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
const std = @import("std");
|
||||||
|
const assert = std.debug.assert;
|
||||||
|
|
||||||
|
test "truncate u0 to larger integer allowed and has comptime known result" {
|
||||||
|
var x: u0 = 0;
|
||||||
|
const y = @truncate(u8, x);
|
||||||
|
comptime assert(y == 0);
|
||||||
|
}
|
@ -1,6 +1,18 @@
|
|||||||
const tests = @import("tests.zig");
|
const tests = @import("tests.zig");
|
||||||
|
|
||||||
pub fn addCases(cases: *tests.CompileErrorContext) void {
|
pub fn addCases(cases: *tests.CompileErrorContext) void {
|
||||||
|
cases.add(
|
||||||
|
"reading past end of pointer casted array",
|
||||||
|
\\comptime {
|
||||||
|
\\ const array = "aoeu";
|
||||||
|
\\ const slice = array[2..];
|
||||||
|
\\ const int_ptr = @ptrCast(*const u24, slice.ptr);
|
||||||
|
\\ const deref = int_ptr.*;
|
||||||
|
\\}
|
||||||
|
,
|
||||||
|
".tmp_source.zig:5:26: error: attempt to read 3 bytes from [4]u8 at index 2 which is 2 bytes",
|
||||||
|
);
|
||||||
|
|
||||||
cases.add(
|
cases.add(
|
||||||
"error note for function parameter incompatibility",
|
"error note for function parameter incompatibility",
|
||||||
\\fn do_the_thing(func: fn (arg: i32) void) void {}
|
\\fn do_the_thing(func: fn (arg: i32) void) void {}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user