diff --git a/src/ani.zig b/src/ani.zig index 7b8b055..7703513 100644 --- a/src/ani.zig +++ b/src/ani.zig @@ -25,14 +25,14 @@ fn getAniheaderFlags(reader: anytype) !u32 { const riff_header = try reader.readBytesNoEof(4); if (!std.mem.eql(u8, &riff_header, "RIFF")) return error.InvalidFormat; - _ = try reader.readIntLittle(u32); // size of RIFF chunk + _ = try reader.readInt(u32, .little); // size of RIFF chunk const form_type = try reader.readBytesNoEof(4); if (!std.mem.eql(u8, &form_type, "ACON")) return error.InvalidFormat; while (true) { const chunk_id = try reader.readBytesNoEof(4); - const chunk_len = try reader.readIntLittle(u32); + const chunk_len = try reader.readInt(u32, .little); if (!std.mem.eql(u8, &chunk_id, "anih")) { // TODO: Move file cursor instead of skipBytes try reader.skipBytes(chunk_len, .{}); diff --git a/src/bmp.zig b/src/bmp.zig index 0b3205c..1c7e0f6 100644 --- a/src/bmp.zig +++ b/src/bmp.zig @@ -20,8 +20,10 @@ const std = @import("std"); const BitmapHeader = @import("ico.zig").BitmapHeader; +const builtin = @import("builtin"); +const native_endian = builtin.cpu.arch.endian(); -pub const windows_format_id = std.mem.readIntNative(u16, "BM"); +pub const windows_format_id = std.mem.readInt(u16, "BM", native_endian); pub const file_header_len = 14; pub const ReadError = error{ @@ -89,19 +91,19 @@ pub fn read(reader: anytype, max_size: u64) ReadError!BitmapInfo { var bitmap_info: BitmapInfo = undefined; const file_header = reader.readBytesNoEof(file_header_len) catch return error.UnexpectedEOF; - const id = std.mem.readIntNative(u16, file_header[0..2]); + const id = std.mem.readInt(u16, file_header[0..2], native_endian); if (id != windows_format_id) return error.InvalidFileHeader; - bitmap_info.pixel_data_offset = std.mem.readIntLittle(u32, file_header[10..14]); + bitmap_info.pixel_data_offset = std.mem.readInt(u32, file_header[10..14], .little); if (bitmap_info.pixel_data_offset > max_size) return error.ImpossiblePixelDataOffset; - bitmap_info.dib_header_size = reader.readIntLittle(u32) catch return error.UnexpectedEOF; + bitmap_info.dib_header_size = reader.readInt(u32, .little) catch return error.UnexpectedEOF; if (bitmap_info.pixel_data_offset < file_header_len + bitmap_info.dib_header_size) return error.ImpossiblePixelDataOffset; const dib_version = BitmapHeader.Version.get(bitmap_info.dib_header_size); switch (dib_version) { .@"nt3.1", .@"nt4.0", .@"nt5.0" => { var dib_header_buf: [@sizeOf(BITMAPINFOHEADER)]u8 align(@alignOf(BITMAPINFOHEADER)) = undefined; - std.mem.writeIntLittle(u32, dib_header_buf[0..4], bitmap_info.dib_header_size); + std.mem.writeInt(u32, dib_header_buf[0..4], bitmap_info.dib_header_size, .little); reader.readNoEof(dib_header_buf[4..]) catch return error.UnexpectedEOF; var dib_header: *BITMAPINFOHEADER = @ptrCast(&dib_header_buf); structFieldsLittleToNative(BITMAPINFOHEADER, dib_header); @@ -116,7 +118,7 @@ pub fn read(reader: anytype, max_size: u64) ReadError!BitmapInfo { }, .@"win2.0" => { var dib_header_buf: [@sizeOf(BITMAPCOREHEADER)]u8 align(@alignOf(BITMAPCOREHEADER)) = undefined; - std.mem.writeIntLittle(u32, dib_header_buf[0..4], bitmap_info.dib_header_size); + std.mem.writeInt(u32, dib_header_buf[0..4], bitmap_info.dib_header_size, .little); reader.readNoEof(dib_header_buf[4..]) catch return error.UnexpectedEOF; var dib_header: *BITMAPCOREHEADER = @ptrCast(&dib_header_buf); structFieldsLittleToNative(BITMAPCOREHEADER, dib_header); diff --git a/src/compile.zig b/src/compile.zig index e315431..f75b699 100644 --- a/src/compile.zig +++ b/src/compile.zig @@ -28,6 +28,7 @@ const windows1252 = @import("windows1252.zig"); const lang = @import("lang.zig"); const code_pages = @import("code_pages.zig"); const errors = @import("errors.zig"); +const native_endian = builtin.cpu.arch.endian(); pub const CompileOptions = struct { cwd: std.fs.Dir, @@ -653,8 +654,8 @@ pub const Compiler = struct { // > resource if a RESDIR structure contains information about a cursor. // where LOCALHEADER is `struct { WORD xHotSpot; WORD yHotSpot; }` if (icon_dir.image_type == .cursor) { - try writer.writeIntLittle(u16, entry.type_specific_data.cursor.hotspot_x); - try writer.writeIntLittle(u16, entry.type_specific_data.cursor.hotspot_y); + try writer.writeInt(u16, entry.type_specific_data.cursor.hotspot_x, .little); + try writer.writeInt(u16, entry.type_specific_data.cursor.hotspot_y, .little); } try file.seekTo(entry.data_offset_from_start_of_file); @@ -735,7 +736,7 @@ pub const Compiler = struct { }, .dib => { var bitmap_header: *ico.BitmapHeader = @ptrCast(@alignCast(&header_bytes)); - if (builtin.cpu.arch.endian() == .Big) { + if (native_endian == .big) { std.mem.byteSwapAllFields(ico.BitmapHeader, bitmap_header); } const bitmap_version = ico.BitmapHeader.Version.get(bitmap_header.bcSize); @@ -846,7 +847,7 @@ pub const Compiler = struct { if (bitmap_info.getActualPaletteByteLen() > bitmap_info.getExpectedPaletteByteLen()) { const num_ignored_bytes = bitmap_info.getActualPaletteByteLen() - bitmap_info.getExpectedPaletteByteLen(); var number_as_bytes: [8]u8 = undefined; - std.mem.writeIntNative(u64, &number_as_bytes, num_ignored_bytes); + std.mem.writeInt(u64, &number_as_bytes, num_ignored_bytes, native_endian); const value_string_index = try self.diagnostics.putString(&number_as_bytes); try self.addErrorDetails(.{ .err = .bmp_ignored_palette_bytes, @@ -861,8 +862,8 @@ pub const Compiler = struct { const max_missing_bytes = 4096; if (num_padding_bytes > max_missing_bytes) { var numbers_as_bytes: [16]u8 = undefined; - std.mem.writeIntNative(u64, numbers_as_bytes[0..8], num_padding_bytes); - std.mem.writeIntNative(u64, numbers_as_bytes[8..16], max_missing_bytes); + std.mem.writeInt(u64, numbers_as_bytes[0..8], num_padding_bytes, native_endian); + std.mem.writeInt(u64, numbers_as_bytes[8..16], max_missing_bytes, native_endian); const values_string_index = try self.diagnostics.putString(&numbers_as_bytes); try self.addErrorDetails(.{ .err = .bmp_too_many_missing_palette_bytes, @@ -878,7 +879,7 @@ pub const Compiler = struct { } var number_as_bytes: [8]u8 = undefined; - std.mem.writeIntNative(u64, &number_as_bytes, num_padding_bytes); + std.mem.writeInt(u64, &number_as_bytes, num_padding_bytes, native_endian); const value_string_index = try self.diagnostics.putString(&number_as_bytes); try self.addErrorDetails(.{ .err = .bmp_missing_palette_bytes, @@ -889,7 +890,7 @@ pub const Compiler = struct { const pixel_data_len = bitmap_info.getPixelDataLen(file_size); if (pixel_data_len > 0) { const miscompiled_bytes = @min(pixel_data_len, num_padding_bytes); - std.mem.writeIntNative(u64, &number_as_bytes, miscompiled_bytes); + std.mem.writeInt(u64, &number_as_bytes, miscompiled_bytes, native_endian); const miscompiled_bytes_string_index = try self.diagnostics.putString(&number_as_bytes); try self.addErrorDetails(.{ .err = .rc_would_miscompile_bmp_palette_padding, @@ -1053,8 +1054,8 @@ pub const Compiler = struct { pub fn write(self: Data, writer: anytype) !void { switch (self) { .number => |number| switch (number.is_long) { - false => try writer.writeIntLittle(WORD, number.asWord()), - true => try writer.writeIntLittle(DWORD, number.value), + false => try writer.writeInt(WORD, number.asWord(), .little), + true => try writer.writeInt(DWORD, number.value, .little), }, .ascii_string => |ascii_string| { try writer.writeAll(ascii_string); @@ -1384,9 +1385,9 @@ pub const Compiler = struct { try data_writer.writeByte(modifiers.value); try data_writer.writeByte(0); // padding - try data_writer.writeIntLittle(u16, key); - try data_writer.writeIntLittle(u16, cmd_id.asWord()); - try data_writer.writeIntLittle(u16, 0); // padding + try data_writer.writeInt(u16, key, .little); + try data_writer.writeInt(u16, cmd_id.asWord(), .little); + try data_writer.writeInt(u16, 0, .little); // padding } } @@ -1770,34 +1771,34 @@ pub const Compiler = struct { if (node.help_id == null) break :help_id 0; break :help_id evaluateNumberExpression(node.help_id.?, self.source, self.input_code_pages).value; }; - try data_writer.writeIntLittle(u16, 1); // version number, always 1 - try data_writer.writeIntLittle(u16, 0xFFFF); // signature, always 0xFFFF - try data_writer.writeIntLittle(u32, help_id); - try data_writer.writeIntLittle(u32, optional_statement_values.exstyle); - try data_writer.writeIntLittle(u32, optional_statement_values.style); + try data_writer.writeInt(u16, 1, .little); // version number, always 1 + try data_writer.writeInt(u16, 0xFFFF, .little); // signature, always 0xFFFF + try data_writer.writeInt(u32, help_id, .little); + try data_writer.writeInt(u32, optional_statement_values.exstyle, .little); + try data_writer.writeInt(u32, optional_statement_values.style, .little); } else { - try data_writer.writeIntLittle(u32, optional_statement_values.style); - try data_writer.writeIntLittle(u32, optional_statement_values.exstyle); + try data_writer.writeInt(u32, optional_statement_values.style, .little); + try data_writer.writeInt(u32, optional_statement_values.exstyle, .little); } // This limit is enforced by the parser, so we know the number of controls // is within the range of a u16. - try data_writer.writeIntLittle(u16, @as(u16, @intCast(node.controls.len))); - try data_writer.writeIntLittle(u16, x.asWord()); - try data_writer.writeIntLittle(u16, y.asWord()); - try data_writer.writeIntLittle(u16, width.asWord()); - try data_writer.writeIntLittle(u16, height.asWord()); + try data_writer.writeInt(u16, @as(u16, @intCast(node.controls.len)), .little); + try data_writer.writeInt(u16, x.asWord(), .little); + try data_writer.writeInt(u16, y.asWord(), .little); + try data_writer.writeInt(u16, width.asWord(), .little); + try data_writer.writeInt(u16, height.asWord(), .little); // Menu if (optional_statement_values.menu) |menu| { try menu.write(data_writer); } else { - try data_writer.writeIntLittle(u16, 0); + try data_writer.writeInt(u16, 0, .little); } // Class if (optional_statement_values.class) |class| { try class.write(data_writer); } else { - try data_writer.writeIntLittle(u16, 0); + try data_writer.writeInt(u16, 0, .little); } // Caption if (optional_statement_values.caption) |caption| { @@ -1805,7 +1806,7 @@ pub const Compiler = struct { defer self.allocator.free(parsed); try data_writer.writeAll(std.mem.sliceAsBytes(parsed[0 .. parsed.len + 1])); } else { - try data_writer.writeIntLittle(u16, 0); + try data_writer.writeInt(u16, 0, .little); } // Font if (optional_statement_values.font) |font| { @@ -1856,18 +1857,18 @@ pub const Compiler = struct { switch (resource) { .dialog => { // Note: Reverse order from DIALOGEX - try data_writer.writeIntLittle(u32, style); - try data_writer.writeIntLittle(u32, exstyle); + try data_writer.writeInt(u32, style, .little); + try data_writer.writeInt(u32, exstyle, .little); }, .dialogex => { const help_id: u32 = if (control.help_id) |help_id_expression| evaluateNumberExpression(help_id_expression, self.source, self.input_code_pages).value else 0; - try data_writer.writeIntLittle(u32, help_id); + try data_writer.writeInt(u32, help_id, .little); // Note: Reverse order from DIALOG - try data_writer.writeIntLittle(u32, exstyle); - try data_writer.writeIntLittle(u32, style); + try data_writer.writeInt(u32, exstyle, .little); + try data_writer.writeInt(u32, style, .little); }, else => unreachable, } @@ -1877,15 +1878,15 @@ pub const Compiler = struct { const control_width = evaluateNumberExpression(control.width, self.source, self.input_code_pages); const control_height = evaluateNumberExpression(control.height, self.source, self.input_code_pages); - try data_writer.writeIntLittle(u16, control_x.asWord()); - try data_writer.writeIntLittle(u16, control_y.asWord()); - try data_writer.writeIntLittle(u16, control_width.asWord()); - try data_writer.writeIntLittle(u16, control_height.asWord()); + try data_writer.writeInt(u16, control_x.asWord(), .little); + try data_writer.writeInt(u16, control_y.asWord(), .little); + try data_writer.writeInt(u16, control_width.asWord(), .little); + try data_writer.writeInt(u16, control_height.asWord(), .little); const control_id = evaluateNumberExpression(control.id, self.source, self.input_code_pages); switch (resource) { - .dialog => try data_writer.writeIntLittle(u16, control_id.asWord()), - .dialogex => try data_writer.writeIntLittle(u32, control_id.value), + .dialog => try data_writer.writeInt(u16, control_id.asWord(), .little), + .dialogex => try data_writer.writeInt(u32, control_id.value, .little), else => unreachable, } @@ -2018,7 +2019,7 @@ pub const Compiler = struct { } // We know the extra_data_buf size fits within a u16. const extra_data_size: u16 = @intCast(extra_data_buf.items.len); - try data_writer.writeIntLittle(u16, extra_data_size); + try data_writer.writeInt(u16, extra_data_size, .little); try data_writer.writeAll(extra_data_buf.items); } @@ -2032,22 +2033,22 @@ pub const Compiler = struct { // I'm assuming this is some sort of version // TODO: Try to find something mentioning this - try data_writer.writeIntLittle(u16, 1); - try data_writer.writeIntLittle(u16, button_width.asWord()); - try data_writer.writeIntLittle(u16, button_height.asWord()); + try data_writer.writeInt(u16, 1, .little); + try data_writer.writeInt(u16, button_width.asWord(), .little); + try data_writer.writeInt(u16, button_height.asWord(), .little); // Number of buttons is guaranteed by the parser to be within maxInt(u16). - try data_writer.writeIntLittle(u16, @as(u16, @intCast(node.buttons.len))); + try data_writer.writeInt(u16, @as(u16, @intCast(node.buttons.len)), .little); for (node.buttons) |button_or_sep| { switch (button_or_sep.id) { .literal => { // This is always SEPARATOR std.debug.assert(button_or_sep.cast(.literal).?.token.id == .literal); - try data_writer.writeIntLittle(u16, 0); + try data_writer.writeInt(u16, 0, .little); }, .simple_statement => { const value_node = button_or_sep.cast(.simple_statement).?.value; const value = evaluateNumberExpression(value_node, self.source, self.input_code_pages); - try data_writer.writeIntLittle(u16, value.asWord()); + try data_writer.writeInt(u16, value.asWord(), .little); }, else => unreachable, // This is a bug in the parser } @@ -2078,21 +2079,21 @@ pub const Compiler = struct { pub fn writeDialogFont(self: *Compiler, resource: Resource, values: FontStatementValues, writer: anytype) !void { const node = values.node; const point_size = evaluateNumberExpression(node.point_size, self.source, self.input_code_pages); - try writer.writeIntLittle(u16, point_size.asWord()); + try writer.writeInt(u16, point_size.asWord(), .little); if (resource == .dialogex) { - try writer.writeIntLittle(u16, values.weight); + try writer.writeInt(u16, values.weight, .little); } if (resource == .dialogex) { - try writer.writeIntLittle(u8, @intFromBool(values.italic)); + try writer.writeInt(u8, @intFromBool(values.italic), .little); } if (node.char_set) |char_set| { const value = evaluateNumberExpression(char_set, self.source, self.input_code_pages); - try writer.writeIntLittle(u8, @as(u8, @truncate(value.value))); + try writer.writeInt(u8, @as(u8, @truncate(value.value)), .little); } else if (resource == .dialogex) { - try writer.writeIntLittle(u8, 1); // DEFAULT_CHARSET + try writer.writeInt(u8, 1, .little); // DEFAULT_CHARSET } const typeface = try self.parseQuotedStringAsWideString(node.typeface); @@ -2147,9 +2148,9 @@ pub const Compiler = struct { pub fn writeMenuData(self: *Compiler, node: *Node.Menu, data_writer: anytype, resource: Resource) !void { // menu header const version: u16 = if (resource == .menu) 0 else 1; - try data_writer.writeIntLittle(u16, version); + try data_writer.writeInt(u16, version, .little); const header_size: u16 = if (resource == .menu) 0 else 4; - try data_writer.writeIntLittle(u16, header_size); // cbHeaderSize + try data_writer.writeInt(u16, header_size, .little); // cbHeaderSize // Note: There can be extra bytes at the end of this header (`rgbExtra`), // but they are always zero-length for us, so we don't write anything // (the length of the rgbExtra field is inferred from the header_size). @@ -2159,9 +2160,9 @@ pub const Compiler = struct { if (resource == .menuex) { if (node.help_id) |help_id_node| { const help_id = evaluateNumberExpression(help_id_node, self.source, self.input_code_pages); - try data_writer.writeIntLittle(u32, help_id.value); + try data_writer.writeInt(u32, help_id.value, .little); } else { - try data_writer.writeIntLittle(u32, 0); + try data_writer.writeInt(u32, 0, .little); } } @@ -2181,9 +2182,9 @@ pub const Compiler = struct { // compiler still uses this alternate form, so that's what we use too. var flags = res.MenuItemFlags{}; if (is_last_of_parent) flags.markLast(); - try writer.writeIntLittle(u16, flags.value); - try writer.writeIntLittle(u16, 0); // id - try writer.writeIntLittle(u16, 0); // null-terminated UTF-16 text + try writer.writeInt(u16, flags.value, .little); + try writer.writeInt(u16, 0, .little); // id + try writer.writeInt(u16, 0, .little); // null-terminated UTF-16 text }, .menu_item => { const menu_item = @fieldParentPtr(Node.MenuItem, "base", node); @@ -2194,10 +2195,10 @@ pub const Compiler = struct { flags.apply(option); } if (is_last_of_parent) flags.markLast(); - try writer.writeIntLittle(u16, flags.value); + try writer.writeInt(u16, flags.value, .little); var result = evaluateNumberExpression(menu_item.result, self.source, self.input_code_pages); - try writer.writeIntLittle(u16, result.asWord()); + try writer.writeInt(u16, result.asWord(), .little); var text = try self.parseQuotedStringAsWideString(menu_item.text); defer self.allocator.free(text); @@ -2212,7 +2213,7 @@ pub const Compiler = struct { flags.apply(option); } if (is_last_of_parent) flags.markLast(); - try writer.writeIntLittle(u16, flags.value); + try writer.writeInt(u16, flags.value, .little); var text = try self.parseQuotedStringAsWideString(popup.text); defer self.allocator.free(text); @@ -2228,30 +2229,30 @@ pub const Compiler = struct { if (menu_item.type) |flags| { const value = evaluateNumberExpression(flags, self.source, self.input_code_pages); - try writer.writeIntLittle(u32, value.value); + try writer.writeInt(u32, value.value, .little); } else { - try writer.writeIntLittle(u32, 0); + try writer.writeInt(u32, 0, .little); } if (menu_item.state) |state| { const value = evaluateNumberExpression(state, self.source, self.input_code_pages); - try writer.writeIntLittle(u32, value.value); + try writer.writeInt(u32, value.value, .little); } else { - try writer.writeIntLittle(u32, 0); + try writer.writeInt(u32, 0, .little); } if (menu_item.id) |id| { const value = evaluateNumberExpression(id, self.source, self.input_code_pages); - try writer.writeIntLittle(u32, value.value); + try writer.writeInt(u32, value.value, .little); } else { - try writer.writeIntLittle(u32, 0); + try writer.writeInt(u32, 0, .little); } var flags: u16 = 0; if (is_last_of_parent) flags |= comptime @as(u16, @intCast(res.MF.END)); // This constant doesn't seem to have a named #define, it's different than MF_POPUP if (node_type == .popup_ex) flags |= 0x01; - try writer.writeIntLittle(u16, flags); + try writer.writeInt(u16, flags, .little); var text = try self.parseQuotedStringAsWideString(menu_item.text); defer self.allocator.free(text); @@ -2266,9 +2267,9 @@ pub const Compiler = struct { if (node_type == .popup_ex) { if (menu_item.help_id) |help_id_node| { const help_id = evaluateNumberExpression(help_id_node, self.source, self.input_code_pages); - try writer.writeIntLittle(u32, help_id.value); + try writer.writeInt(u32, help_id.value, .little); } else { - try writer.writeIntLittle(u32, 0); + try writer.writeInt(u32, 0, .little); } for (menu_item.items, 0..) |item, i| { @@ -2289,15 +2290,15 @@ pub const Compiler = struct { var limited_writer = limitedWriter(data_buffer.writer(), std.math.maxInt(u16)); const data_writer = limited_writer.writer(); - try data_writer.writeIntLittle(u16, 0); // placeholder size - try data_writer.writeIntLittle(u16, res.FixedFileInfo.byte_len); - try data_writer.writeIntLittle(u16, res.VersionNode.type_binary); + try data_writer.writeInt(u16, 0, .little); // placeholder size + try data_writer.writeInt(u16, res.FixedFileInfo.byte_len, .little); + try data_writer.writeInt(u16, res.VersionNode.type_binary, .little); const key_bytes = std.mem.sliceAsBytes(res.FixedFileInfo.key[0 .. res.FixedFileInfo.key.len + 1]); try data_writer.writeAll(key_bytes); // The number of bytes written up to this point is always the same, since the name // of the node is a constant (FixedFileInfo.key). The total number of bytes // written so far is 38, so we need 2 padding bytes to get back to DWORD alignment - try data_writer.writeIntLittle(u16, 0); + try data_writer.writeInt(u16, 0, .little); var fixed_file_info = res.FixedFileInfo{}; for (node.fixed_info) |fixed_info| { @@ -2392,7 +2393,7 @@ pub const Compiler = struct { // limited the writer to maxInt(u16) const data_size: u16 = @intCast(data_buffer.items.len); // And now that we know the full size of this node (including its children), set its size - std.mem.writeIntLittle(u16, data_buffer.items[0..2], data_size); + std.mem.writeInt(u16, data_buffer.items[0..2], data_size, .little); var header = try self.resourceHeader(node.id, node.versioninfo, .{ .data_size = data_size, @@ -2415,12 +2416,12 @@ pub const Compiler = struct { try writeDataPadding(writer, @as(u16, @intCast(buf.items.len))); const node_and_children_size_offset = buf.items.len; - try writer.writeIntLittle(u16, 0); // placeholder for size + try writer.writeInt(u16, 0, .little); // placeholder for size const data_size_offset = buf.items.len; - try writer.writeIntLittle(u16, 0); // placeholder for data size + try writer.writeInt(u16, 0, .little); // placeholder for data size const data_type_offset = buf.items.len; // Data type is string unless the node contains values that are numbers. - try writer.writeIntLittle(u16, res.VersionNode.type_string); + try writer.writeInt(u16, res.VersionNode.type_string, .little); switch (node.id) { inline .block, .block_value => |node_type| { @@ -2482,17 +2483,17 @@ pub const Compiler = struct { const is_empty = parsed_to_first_null.len == 0; const is_only = block_or_value.values.len == 1; if ((!is_empty or !is_only) and (is_last or value_value_node.trailing_comma)) { - try writer.writeIntLittle(u16, 0); + try writer.writeInt(u16, 0, .little); values_size += if (has_number_value) 2 else 1; } } } var data_size_slice = buf.items[data_size_offset..]; - std.mem.writeIntLittle(u16, data_size_slice[0..@sizeOf(u16)], @as(u16, @intCast(values_size))); + std.mem.writeInt(u16, data_size_slice[0..@sizeOf(u16)], @as(u16, @intCast(values_size)), .little); if (has_number_value) { const data_type_slice = buf.items[data_type_offset..]; - std.mem.writeIntLittle(u16, data_type_slice[0..@sizeOf(u16)], res.VersionNode.type_binary); + std.mem.writeInt(u16, data_type_slice[0..@sizeOf(u16)], res.VersionNode.type_binary, .little); } if (node_type == .block) { @@ -2507,7 +2508,7 @@ pub const Compiler = struct { const node_and_children_size = buf.items.len - node_and_children_size_offset; const node_and_children_size_slice = buf.items[node_and_children_size_offset..]; - std.mem.writeIntLittle(u16, node_and_children_size_slice[0..@sizeOf(u16)], @as(u16, @intCast(node_and_children_size))); + std.mem.writeInt(u16, node_and_children_size_slice[0..@sizeOf(u16)], @as(u16, @intCast(node_and_children_size)), .little); } pub fn writeStringTable(self: *Compiler, node: *Node.StringTable) !void { @@ -2715,17 +2716,17 @@ pub const Compiler = struct { } fn writeSizeInfo(self: ResourceHeader, writer: anytype, size_info: SizeInfo) !void { - try writer.writeIntLittle(DWORD, self.data_size); // DataSize - try writer.writeIntLittle(DWORD, size_info.bytes); // HeaderSize + try writer.writeInt(DWORD, self.data_size, .little); // DataSize + try writer.writeInt(DWORD, size_info.bytes, .little); // HeaderSize try self.type_value.write(writer); // TYPE try self.name_value.write(writer); // NAME try writer.writeByteNTimes(0, size_info.padding_after_name); - try writer.writeIntLittle(DWORD, self.data_version); // DataVersion - try writer.writeIntLittle(WORD, self.memory_flags.value); // MemoryFlags - try writer.writeIntLittle(WORD, self.language.asInt()); // LanguageId - try writer.writeIntLittle(DWORD, self.version); // Version - try writer.writeIntLittle(DWORD, self.characteristics); // Characteristics + try writer.writeInt(DWORD, self.data_version, .little); // DataVersion + try writer.writeInt(WORD, self.memory_flags.value, .little); // MemoryFlags + try writer.writeInt(WORD, self.language.asInt(), .little); // LanguageId + try writer.writeInt(DWORD, self.version, .little); // Version + try writer.writeInt(DWORD, self.characteristics, .little); // Characteristics } pub fn predefinedResourceType(self: ResourceHeader) ?res.RT { @@ -3055,7 +3056,7 @@ pub const FontDir = struct { defer header.deinit(compiler.allocator); try header.writeAssertNoOverflow(writer); - try writer.writeIntLittle(u16, num_fonts); + try writer.writeInt(u16, num_fonts, .little); for (self.fonts.items) |font| { // The format of the FONTDIR is a strange beast. // Technically, each FONT is seemingly meant to be written as a @@ -3107,7 +3108,7 @@ pub const FontDir = struct { // device name/face name in the FONTDIR is reliable. // First, the ID is written, though - try writer.writeIntLittle(u16, font.id); + try writer.writeInt(u16, font.id, .little); try writer.writeAll(&font.header_bytes); try writer.writeByteNTimes(0, 2); } @@ -3244,7 +3245,7 @@ pub const StringTable = struct { var string_i: u8 = 0; while (true) : (i += 1) { if (!self.set_indexes.isSet(i)) { - try data_writer.writeIntLittle(u16, 0); + try data_writer.writeInt(u16, 0, .little); if (i == 15) break else continue; } @@ -3275,10 +3276,10 @@ pub const StringTable = struct { // If the option is set, then a NUL terminator is added unconditionally. // We already trimmed any trailing NULs, so we know it will be a new addition to the string. if (compiler.null_terminate_string_table_strings) string_len_in_utf16_code_units += 1; - try data_writer.writeIntLittle(u16, string_len_in_utf16_code_units); + try data_writer.writeInt(u16, string_len_in_utf16_code_units, .little); try data_writer.writeAll(std.mem.sliceAsBytes(trimmed_string)); if (compiler.null_terminate_string_table_strings) { - try data_writer.writeIntLittle(u16, 0); + try data_writer.writeInt(u16, 0, .little); } if (i == 15) break; diff --git a/src/errors.zig b/src/errors.zig index 906b406..79907de 100644 --- a/src/errors.zig +++ b/src/errors.zig @@ -9,6 +9,8 @@ const bmp = @import("bmp.zig"); const parse = @import("parse.zig"); const lang = @import("lang.zig"); const CodePage = @import("code_pages.zig").CodePage; +const builtin = @import("builtin"); +const native_endian = builtin.cpu.arch.endian(); pub const Diagnostics = struct { errors: std.ArrayListUnmanaged(ErrorDetails) = .{}, @@ -655,24 +657,24 @@ pub const ErrorDetails = struct { }, .bmp_ignored_palette_bytes => { const bytes = strings[self.extra.number]; - const ignored_bytes = std.mem.readIntNative(u64, bytes[0..8]); + const ignored_bytes = std.mem.readInt(u64, bytes[0..8], native_endian); try writer.print("bitmap has {d} extra bytes preceding the pixel data which will be ignored", .{ignored_bytes}); }, .bmp_missing_palette_bytes => { const bytes = strings[self.extra.number]; - const missing_bytes = std.mem.readIntNative(u64, bytes[0..8]); + const missing_bytes = std.mem.readInt(u64, bytes[0..8], native_endian); try writer.print("bitmap has {d} missing color palette bytes which will be padded with zeroes", .{missing_bytes}); }, .rc_would_miscompile_bmp_palette_padding => { const bytes = strings[self.extra.number]; - const miscompiled_bytes = std.mem.readIntNative(u64, bytes[0..8]); + const miscompiled_bytes = std.mem.readInt(u64, bytes[0..8], native_endian); try writer.print("the missing color palette bytes would be miscompiled by the Win32 RC compiler (the added padding bytes would include {d} bytes of the pixel data)", .{miscompiled_bytes}); }, .bmp_too_many_missing_palette_bytes => switch (self.type) { .err, .warning => { const bytes = strings[self.extra.number]; - const missing_bytes = std.mem.readIntNative(u64, bytes[0..8]); - const max_missing_bytes = std.mem.readIntNative(u64, bytes[8..16]); + const missing_bytes = std.mem.readInt(u64, bytes[0..8], native_endian); + const max_missing_bytes = std.mem.readInt(u64, bytes[8..16], native_endian); try writer.print("bitmap has {} missing color palette bytes which exceeds the maximum of {}", .{ missing_bytes, max_missing_bytes }); }, // TODO: command line option diff --git a/src/fnt.zig b/src/fnt.zig index 023b42d..5bd8a26 100644 --- a/src/fnt.zig +++ b/src/fnt.zig @@ -189,7 +189,7 @@ pub const FontDirEntry = struct { inline for (@typeInfo(FontDirEntry).Struct.fields) |field| { switch (field.type) { u8 => @field(entry, field.name) = try reader.readByte(), - u16, u32 => @field(entry, field.name) = try reader.readIntLittle(field.type), + u16, u32 => @field(entry, field.name) = try reader.readInt(field.type, .little), [60]u8 => @field(entry, field.name) = try reader.readBytesNoEof(60), else => @compileError("unknown field in FontDirEntry"), } @@ -201,7 +201,7 @@ pub const FontDirEntry = struct { inline for (@typeInfo(FontDirEntry).Struct.fields) |field| { switch (field.type) { u8 => try writer.writeByte(@field(entry, field.name)), - u16, u32 => try writer.writeIntLittle(field.type, @field(entry, field.name)), + u16, u32 => try writer.writeInt(field.type, @field(entry, field.name), .little), [60]u8 => try writer.writeAll(&@field(entry, field.name)), else => @compileError("unknown field in FontDirEntry"), } diff --git a/src/ico.zig b/src/ico.zig index 205f5a0..310db6e 100644 --- a/src/ico.zig +++ b/src/ico.zig @@ -5,6 +5,8 @@ //! https://learn.microsoft.com/en-us/windows/win32/menurc/localheader const std = @import("std"); +const builtin = @import("builtin"); +const native_endian = builtin.cpu.arch.endian(); pub const ReadError = std.mem.Allocator.Error || error{ InvalidHeader, InvalidImageType, ImpossibleDataSize, UnexpectedEOF, ReadError }; @@ -37,17 +39,17 @@ pub fn read(allocator: std.mem.Allocator, reader: anytype, max_size: u64) ReadEr // to do this. Maybe it makes more sense to handle the translation // at the call site instead of having a helper function here. pub fn readAnyError(allocator: std.mem.Allocator, reader: anytype, max_size: u64) !IconDir { - const reserved = try reader.readIntLittle(u16); + const reserved = try reader.readInt(u16, .little); if (reserved != 0) { return error.InvalidHeader; } - const image_type = reader.readEnum(ImageType, .Little) catch |err| switch (err) { + const image_type = reader.readEnum(ImageType, .little) catch |err| switch (err) { error.InvalidValue => return error.InvalidImageType, else => |e| return e, }; - const num_images = try reader.readIntLittle(u16); + const num_images = try reader.readInt(u16, .little); // To avoid over-allocation in the case of a file that says it has way more // entries than it actually does, we use an ArrayList with a conservatively @@ -66,19 +68,19 @@ pub fn readAnyError(allocator: std.mem.Allocator, reader: anytype, max_size: u64 switch (image_type) { .icon => { entry.type_specific_data = .{ .icon = .{ - .color_planes = try reader.readIntLittle(u16), - .bits_per_pixel = try reader.readIntLittle(u16), + .color_planes = try reader.readInt(u16, .little), + .bits_per_pixel = try reader.readInt(u16, .little), } }; }, .cursor => { entry.type_specific_data = .{ .cursor = .{ - .hotspot_x = try reader.readIntLittle(u16), - .hotspot_y = try reader.readIntLittle(u16), + .hotspot_x = try reader.readInt(u16, .little), + .hotspot_y = try reader.readInt(u16, .little), } }; }, } - entry.data_size_in_bytes = try reader.readIntLittle(u32); - entry.data_offset_from_start_of_file = try reader.readIntLittle(u32); + entry.data_size_in_bytes = try reader.readInt(u32, .little); + entry.data_offset_from_start_of_file = try reader.readInt(u32, .little); // Validate that the offset/data size is feasible if (@as(u64, entry.data_offset_from_start_of_file) + entry.data_size_in_bytes > max_size) { return error.ImpossibleDataSize; @@ -133,10 +135,10 @@ pub const IconDir = struct { } pub fn writeResData(self: IconDir, writer: anytype, first_image_id: u16) !void { - try writer.writeIntLittle(u16, 0); - try writer.writeIntLittle(u16, @intFromEnum(self.image_type)); + try writer.writeInt(u16, 0, .little); + try writer.writeInt(u16, @intFromEnum(self.image_type), .little); // We know that entries.len must fit into a u16 - try writer.writeIntLittle(u16, @as(u16, @intCast(self.entries.len))); + try writer.writeInt(u16, @as(u16, @intCast(self.entries.len)), .little); var image_id = first_image_id; for (self.entries) |entry| { @@ -173,23 +175,23 @@ pub const Entry = struct { pub fn writeResData(self: Entry, writer: anytype, id: u16) !void { switch (self.type_specific_data) { .icon => |icon_data| { - try writer.writeIntLittle(u8, @as(u8, @truncate(self.width))); - try writer.writeIntLittle(u8, @as(u8, @truncate(self.height))); - try writer.writeIntLittle(u8, self.num_colors); - try writer.writeIntLittle(u8, self.reserved); - try writer.writeIntLittle(u16, icon_data.color_planes); - try writer.writeIntLittle(u16, icon_data.bits_per_pixel); - try writer.writeIntLittle(u32, self.data_size_in_bytes); + try writer.writeInt(u8, @as(u8, @truncate(self.width)), .little); + try writer.writeInt(u8, @as(u8, @truncate(self.height)), .little); + try writer.writeInt(u8, self.num_colors, .little); + try writer.writeInt(u8, self.reserved, .little); + try writer.writeInt(u16, icon_data.color_planes, .little); + try writer.writeInt(u16, icon_data.bits_per_pixel, .little); + try writer.writeInt(u32, self.data_size_in_bytes, .little); }, .cursor => |cursor_data| { - try writer.writeIntLittle(u16, self.width); - try writer.writeIntLittle(u16, self.height); - try writer.writeIntLittle(u16, cursor_data.hotspot_x); - try writer.writeIntLittle(u16, cursor_data.hotspot_y); - try writer.writeIntLittle(u32, self.data_size_in_bytes + 4); + try writer.writeInt(u16, self.width, .little); + try writer.writeInt(u16, self.height, .little); + try writer.writeInt(u16, cursor_data.hotspot_x, .little); + try writer.writeInt(u16, cursor_data.hotspot_y, .little); + try writer.writeInt(u32, self.data_size_in_bytes + 4, .little); }, } - try writer.writeIntLittle(u16, id); + try writer.writeInt(u16, id, .little); } }; @@ -235,21 +237,21 @@ pub const ImageFormat = enum { png, riff, - const riff_header = std.mem.readIntNative(u32, "RIFF"); - const png_signature = std.mem.readIntNative(u64, "\x89PNG\r\n\x1a\n"); - const ihdr_code = std.mem.readIntNative(u32, "IHDR"); - const acon_form_type = std.mem.readIntNative(u32, "ACON"); + const riff_header = std.mem.readInt(u32, "RIFF", native_endian); + const png_signature = std.mem.readInt(u64, "\x89PNG\r\n\x1a\n", native_endian); + const ihdr_code = std.mem.readInt(u32, "IHDR", native_endian); + const acon_form_type = std.mem.readInt(u32, "ACON", native_endian); pub fn detect(header_bytes: *const [16]u8) ImageFormat { - if (std.mem.readIntNative(u32, header_bytes[0..4]) == riff_header) return .riff; - if (std.mem.readIntNative(u64, header_bytes[0..8]) == png_signature) return .png; + if (std.mem.readInt(u32, header_bytes[0..4], native_endian) == riff_header) return .riff; + if (std.mem.readInt(u64, header_bytes[0..8], native_endian) == png_signature) return .png; return .dib; } pub fn validate(format: ImageFormat, header_bytes: *const [16]u8) bool { return switch (format) { - .png => std.mem.readIntNative(u32, header_bytes[12..16]) == ihdr_code, - .riff => std.mem.readIntNative(u32, header_bytes[8..12]) == acon_form_type, + .png => std.mem.readInt(u32, header_bytes[12..16], native_endian) == ihdr_code, + .riff => std.mem.readInt(u32, header_bytes[8..12], native_endian) == acon_form_type, .dib => true, }; } diff --git a/src/res.zig b/src/res.zig index d331644..7db3f0d 100644 --- a/src/res.zig +++ b/src/res.zig @@ -249,14 +249,14 @@ pub const NameOrOrdinal = union(enum) { try writer.writeAll(std.mem.sliceAsBytes(name[0 .. name.len + 1])); }, .ordinal => |ordinal| { - try writer.writeIntLittle(u16, 0xffff); - try writer.writeIntLittle(u16, ordinal); + try writer.writeInt(u16, 0xffff, .little); + try writer.writeInt(u16, ordinal, .little); }, } } pub fn writeEmpty(writer: anytype) !void { - try writer.writeIntLittle(u16, 0); + try writer.writeInt(u16, 0, .little); } pub fn fromString(allocator: Allocator, bytes: SourceBytes) !NameOrOrdinal { @@ -963,19 +963,19 @@ pub const FixedFileInfo = struct { }; pub fn write(self: FixedFileInfo, writer: anytype) !void { - try writer.writeIntLittle(u32, signature); - try writer.writeIntLittle(u32, version); - try writer.writeIntLittle(u32, self.file_version.mostSignificantCombinedParts()); - try writer.writeIntLittle(u32, self.file_version.leastSignificantCombinedParts()); - try writer.writeIntLittle(u32, self.product_version.mostSignificantCombinedParts()); - try writer.writeIntLittle(u32, self.product_version.leastSignificantCombinedParts()); - try writer.writeIntLittle(u32, self.file_flags_mask); - try writer.writeIntLittle(u32, self.file_flags); - try writer.writeIntLittle(u32, self.file_os); - try writer.writeIntLittle(u32, self.file_type); - try writer.writeIntLittle(u32, self.file_subtype); - try writer.writeIntLittle(u32, self.file_date.mostSignificantCombinedParts()); - try writer.writeIntLittle(u32, self.file_date.leastSignificantCombinedParts()); + try writer.writeInt(u32, signature, .little); + try writer.writeInt(u32, version, .little); + try writer.writeInt(u32, self.file_version.mostSignificantCombinedParts(), .little); + try writer.writeInt(u32, self.file_version.leastSignificantCombinedParts(), .little); + try writer.writeInt(u32, self.product_version.mostSignificantCombinedParts(), .little); + try writer.writeInt(u32, self.product_version.leastSignificantCombinedParts(), .little); + try writer.writeInt(u32, self.file_flags_mask, .little); + try writer.writeInt(u32, self.file_flags, .little); + try writer.writeInt(u32, self.file_os, .little); + try writer.writeInt(u32, self.file_type, .little); + try writer.writeInt(u32, self.file_subtype, .little); + try writer.writeInt(u32, self.file_date.mostSignificantCombinedParts(), .little); + try writer.writeInt(u32, self.file_date.leastSignificantCombinedParts(), .little); } }; diff --git a/test/fuzzy_bitmaps.zig b/test/fuzzy_bitmaps.zig index 7eec793..f266a03 100644 --- a/test/fuzzy_bitmaps.zig +++ b/test/fuzzy_bitmaps.zig @@ -44,28 +44,28 @@ test "BITMAP fuzz" { // write a bitmap header and DIB header try image_writer.writeAll("BM"); - try image_writer.writeIntLittle(u32, reported_data_size); // size of the file (including everything) - try image_writer.writeIntLittle(u16, rand.int(u16)); // reserved - try image_writer.writeIntLittle(u16, rand.int(u16)); // reserved + try image_writer.writeInt(u32, reported_data_size, .little); // size of the file (including everything) + try image_writer.writeInt(u16, rand.int(u16), .little); // reserved + try image_writer.writeInt(u16, rand.int(u16), .little); // reserved // offset of bmp image data // Note: This being larger than the file size can trigger some weird behavior in the // Win32 rc compiler - try image_writer.writeIntLittle(u32, if (rand.boolean()) bmp_file_header_len + 40 else rand.uintLessThanBiased(u32, real_data_size + 100)); + try image_writer.writeInt(u32, if (rand.boolean()) bmp_file_header_len + 40 else rand.uintLessThanBiased(u32, real_data_size + 100), .little); const dib_header_size: u32 = if (rand.boolean()) 40 else rand.int(u32); - try image_writer.writeIntLittle(u32, dib_header_size); - try image_writer.writeIntLittle(i32, rand.int(i32)); // width - try image_writer.writeIntLittle(i32, rand.int(i32)); // height - try image_writer.writeIntLittle(u16, rand.int(u16)); // planes - try image_writer.writeIntLittle(u16, rand.uintLessThanBiased(u16, 34)); // bits_per_pixel - try image_writer.writeIntLittle(u32, rand.uintLessThanBiased(u32, 15)); // compression - try image_writer.writeIntLittle(u32, rand.int(u32)); // image_size - try image_writer.writeIntLittle(i32, rand.int(i32)); // x_pixels_per_meter - try image_writer.writeIntLittle(i32, rand.int(i32)); // y_pixels_per_meter + try image_writer.writeInt(u32, dib_header_size, .little); + try image_writer.writeInt(i32, rand.int(i32), .little); // width + try image_writer.writeInt(i32, rand.int(i32), .little); // height + try image_writer.writeInt(u16, rand.int(u16), .little); // planes + try image_writer.writeInt(u16, rand.uintLessThanBiased(u16, 34), .little); // bits_per_pixel + try image_writer.writeInt(u32, rand.uintLessThanBiased(u32, 15), .little); // compression + try image_writer.writeInt(u32, rand.int(u32), .little); // image_size + try image_writer.writeInt(i32, rand.int(i32), .little); // x_pixels_per_meter + try image_writer.writeInt(i32, rand.int(i32), .little); // y_pixels_per_meter // This being large can trigger `out of memory` or really long .res compile // times in the Win32 rc compiler - try image_writer.writeIntLittle(u32, if (rand.boolean()) rand.uintLessThan(u32, 500) else rand.int(u32)); // num_colors - try image_writer.writeIntLittle(u32, rand.int(u32)); // important colors used + try image_writer.writeInt(u32, if (rand.boolean()) rand.uintLessThan(u32, 500) else rand.int(u32), .little); // num_colors + try image_writer.writeInt(u32, rand.int(u32), .little); // important colors used // and now a bunch of random bytes try image_buffer.ensureUnusedCapacity(random_bytes_len); diff --git a/test/fuzzy_icons.zig b/test/fuzzy_icons.zig index bd90ea5..1b4ae8d 100644 --- a/test/fuzzy_icons.zig +++ b/test/fuzzy_icons.zig @@ -24,26 +24,26 @@ test "ICON fuzz" { icon_buffer.shrinkRetainingCapacity(0); const icon_writer = icon_buffer.writer(); // reserved bytes, very occasionally make it random - try icon_writer.writeIntLittle(u16, if (rand.int(u8) == 0) rand.int(u16) else 0); + try icon_writer.writeInt(u16, if (rand.int(u8) == 0) rand.int(u16) else 0, .little); // icon is 1, cursor is 2, anything else is invalid var res_type = if (rand.int(u8) == 0) rand.int(u16) else 1; // we don't want to test with a cursor value here, though, since // that is a compile error for us but not for the Win32 RC compiler if (res_type == 2) res_type = 0; - try icon_writer.writeIntLittle(u16, res_type); + try icon_writer.writeInt(u16, res_type, .little); // Unfortunately, we can't really make this random (or even > 1) because // the Win32 RC compiler has a bug that can lead to infinite `.res` filesize // (see also below comment about reported data size) - try icon_writer.writeIntLittle(u16, if (rand.int(u8) == 0) @as(u16, 0) else 1); + try icon_writer.writeInt(u16, if (rand.int(u8) == 0) @as(u16, 0) else 1, .little); // we'll write one well-formed-ish resdir - try icon_writer.writeIntLittle(u8, rand.int(u8)); // width - try icon_writer.writeIntLittle(u8, rand.int(u8)); // height - try icon_writer.writeIntLittle(u8, rand.int(u8)); // num_colors + try icon_writer.writeInt(u8, rand.int(u8), .little); // width + try icon_writer.writeInt(u8, rand.int(u8), .little); // height + try icon_writer.writeInt(u8, rand.int(u8), .little); // num_colors // reserved, should be zero but occasionally make it random - try icon_writer.writeIntLittle(u8, if (rand.int(u8) == 0) rand.int(u8) else 0); - try icon_writer.writeIntLittle(u16, rand.int(u16)); // color_planes/hotspot_x - try icon_writer.writeIntLittle(u16, rand.int(u16)); // bits_per_pixel/hotspot_y + try icon_writer.writeInt(u8, if (rand.int(u8) == 0) rand.int(u8) else 0, .little); + try icon_writer.writeInt(u16, rand.int(u16), .little); // color_planes/hotspot_x + try icon_writer.writeInt(u16, rand.int(u16), .little); // bits_per_pixel/hotspot_y const make_png = rand.boolean(); const random_bytes_len = rand.uintLessThanBiased(u32, 1000); @@ -57,14 +57,14 @@ test "ICON fuzz" { @as(u32, @intCast(@max(0, @as(i33, @intCast(real_data_size)) - rand.int(i8)))) else real_data_size; - try icon_writer.writeIntLittle(u32, reported_data_size); + try icon_writer.writeInt(u32, reported_data_size, .little); // Offset to the first icon, 0x16 is correct if there's 1 icon - try icon_writer.writeIntLittle(u32, if (rand.int(u8) == 0) rand.int(u32) else 0x16); + try icon_writer.writeInt(u32, if (rand.int(u8) == 0) rand.int(u32) else 0x16, .little); // half the time write enough of a PNG that the RC compiler treats it as a PNG if (make_png) { try icon_writer.writeAll("\x89PNG\r\n\x1a\n"); - try icon_writer.writeIntBig(u32, rand.int(u32)); // IHDR chunk size + try icon_writer.writeInt(u32, rand.int(u32), .big); // IHDR chunk size try icon_writer.writeAll("IHDR"); }