| author | |
| committer | |
| log | 431d76c0233271de6a30aa626ccb1553dc241722 |
| tree | 211266569e5d20fbe264fef34c885b957bc32938 |
| parent | c71991c869fc8c997c2714fe1b53caef23449c9c |
| signature |
5 files changed, 127 insertions(+), 34 deletions(-)
lib/std/build/emit_raw.zig+1-3| ... | @@ -48,8 +48,6 @@ const BinaryElfOutput = struct { | ... | @@ -48,8 +48,6 @@ const BinaryElfOutput = struct { |
| 48 | }; | 48 | }; |
| 49 | const elf_hdrs = try std.elf.readAllHeaders(allocator, elf_file); | 49 | const elf_hdrs = try std.elf.readAllHeaders(allocator, elf_file); |
| 50 | 50 | ||
| 51 | var binaryElfOutput = BinaryElfOutput.init(arena_allocator); | ||
| 52 | |||
| 53 | for (elf_hdrs.section_headers) |section, i| { | 51 | for (elf_hdrs.section_headers) |section, i| { |
| 54 | if (sectionValidForOutput(section)) { | 52 | if (sectionValidForOutput(section)) { |
| 55 | const newSection = try allocator.create(BinaryElfSection); | 53 | const newSection = try allocator.create(BinaryElfSection); |
| ... | @@ -164,7 +162,7 @@ fn emitRaw(allocator: *Allocator, elf_path: []const u8, raw_path: []const u8) !v | ... | @@ -164,7 +162,7 @@ fn emitRaw(allocator: *Allocator, elf_path: []const u8, raw_path: []const u8) !v |
| 164 | var out_file = try fs.cwd().createFile(raw_path, .{}); | 162 | var out_file = try fs.cwd().createFile(raw_path, .{}); |
| 165 | defer out_file.close(); | 163 | defer out_file.close(); |
| 166 | 164 | ||
| 167 | const binary_elf_output = try BinaryElfOutput.parse(allocator, elf_file); | 165 | var binary_elf_output = try BinaryElfOutput.parse(allocator, elf_file); |
| 168 | defer binary_elf_output.deinit(); | 166 | defer binary_elf_output.deinit(); |
| 169 | 167 | ||
| 170 | for (binary_elf_output.sections.toSlice()) |section| { | 168 | for (binary_elf_output.sections.toSlice()) |section| { |
lib/std/elf.zig+12-12| ... | @@ -1,5 +1,5 @@ | ... | @@ -1,5 +1,5 @@ |
| 1 | const builtin = @import("builtin"); | ||
| 2 | const std = @import("std.zig"); | 1 | const std = @import("std.zig"); |
| 2 | const builtin = std.builtin; | ||
| 3 | const io = std.io; | 3 | const io = std.io; |
| 4 | const os = std.os; | 4 | const os = std.os; |
| 5 | const math = std.math; | 5 | const math = std.math; |
| ... | @@ -352,7 +352,7 @@ pub fn readHeader(file: File) !Header { | ... | @@ -352,7 +352,7 @@ pub fn readHeader(file: File) !Header { |
| 352 | if (!mem.eql(u8, hdr32.e_ident[0..4], "\x7fELF")) return error.InvalidElfMagic; | 352 | if (!mem.eql(u8, hdr32.e_ident[0..4], "\x7fELF")) return error.InvalidElfMagic; |
| 353 | if (hdr32.e_ident[EI_VERSION] != 1) return error.InvalidElfVersion; | 353 | if (hdr32.e_ident[EI_VERSION] != 1) return error.InvalidElfVersion; |
| 354 | 354 | ||
| 355 | const endian = switch (hdr32.e_ident[EI_DATA]) { | 355 | const endian: std.builtin.Endian = switch (hdr32.e_ident[EI_DATA]) { |
| 356 | ELFDATA2LSB => .Little, | 356 | ELFDATA2LSB => .Little, |
| 357 | ELFDATA2MSB => .Big, | 357 | ELFDATA2MSB => .Big, |
| 358 | else => return error.InvalidElfEndian, | 358 | else => return error.InvalidElfEndian, |
| ... | @@ -406,8 +406,8 @@ pub fn readAllHeaders(allocator: *mem.Allocator, file: File) !AllHeaders { | ... | @@ -406,8 +406,8 @@ pub fn readAllHeaders(allocator: *mem.Allocator, file: File) !AllHeaders { |
| 406 | // Treat section headers and program headers as byte buffers. For 32-bit ELF and | 406 | // Treat section headers and program headers as byte buffers. For 32-bit ELF and |
| 407 | // non-matching endian files, we post-process to correct integer endianness and offsets. | 407 | // non-matching endian files, we post-process to correct integer endianness and offsets. |
| 408 | 408 | ||
| 409 | const shdr_buf = std.mem.sliceToBytes(hdrs.section_headers)[0 .. hdrs.header.shentsize * hdrs.header.shnum]; | 409 | const shdr_buf = std.mem.sliceAsBytes(hdrs.section_headers)[0 .. hdrs.header.shentsize * hdrs.header.shnum]; |
| 410 | const phdr_buf = std.mem.sliceToBytes(hdrs.program_headers)[0 .. hdrs.header.phentsize * hdrs.header.phnum]; | 410 | const phdr_buf = std.mem.sliceAsBytes(hdrs.program_headers)[0 .. hdrs.header.phentsize * hdrs.header.phnum]; |
| 411 | 411 | ||
| 412 | try preadNoEof(file, shdr_buf, hdrs.header.shoff); | 412 | try preadNoEof(file, shdr_buf, hdrs.header.shoff); |
| 413 | try preadNoEof(file, phdr_buf, hdrs.header.phoff); | 413 | try preadNoEof(file, phdr_buf, hdrs.header.phoff); |
| ... | @@ -430,14 +430,14 @@ pub fn readAllHeaders(allocator: *mem.Allocator, file: File) !AllHeaders { | ... | @@ -430,14 +430,14 @@ pub fn readAllHeaders(allocator: *mem.Allocator, file: File) !AllHeaders { |
| 430 | } | 430 | } |
| 431 | for (hdrs.program_headers) |*phdr, i| { | 431 | for (hdrs.program_headers) |*phdr, i| { |
| 432 | phdr.* = .{ | 432 | phdr.* = .{ |
| 433 | .p_type = int(is_64, need_bswap, phdrs32[i].p_type, shdr.p_type), | 433 | .p_type = int(is_64, need_bswap, phdrs32[i].p_type, phdr.p_type), |
| 434 | .p_offset = int(is_64, need_bswap, phdrs32[i].p_offset, shdr.p_offset), | 434 | .p_offset = int(is_64, need_bswap, phdrs32[i].p_offset, phdr.p_offset), |
| 435 | .p_vaddr = int(is_64, need_bswap, phdrs32[i].p_vaddr, shdr.p_vaddr), | 435 | .p_vaddr = int(is_64, need_bswap, phdrs32[i].p_vaddr, phdr.p_vaddr), |
| 436 | .p_paddr = int(is_64, need_bswap, phdrs32[i].p_paddr, shdr.p_paddr), | 436 | .p_paddr = int(is_64, need_bswap, phdrs32[i].p_paddr, phdr.p_paddr), |
| 437 | .p_filesz = int(is_64, need_bswap, phdrs32[i].p_filesz, shdr.p_filesz), | 437 | .p_filesz = int(is_64, need_bswap, phdrs32[i].p_filesz, phdr.p_filesz), |
| 438 | .p_memsz = int(is_64, need_bswap, phdrs32[i].p_memsz, shdr.p_memsz), | 438 | .p_memsz = int(is_64, need_bswap, phdrs32[i].p_memsz, phdr.p_memsz), |
| 439 | .p_flags = int(is_64, need_bswap, phdrs32[i].p_flags, shdr.p_flags), | 439 | .p_flags = int(is_64, need_bswap, phdrs32[i].p_flags, phdr.p_flags), |
| 440 | .p_align = int(is_64, need_bswap, phdrs32[i].p_align, shdr.p_align), | 440 | .p_align = int(is_64, need_bswap, phdrs32[i].p_align, phdr.p_align), |
| 441 | }; | 441 | }; |
| 442 | } | 442 | } |
| 443 | return hdrs; | 443 | return hdrs; |
lib/std/io.zig+2| ... | @@ -126,6 +126,8 @@ pub const deserializer = @import("io/serialization.zig").deserializer; | ... | @@ -126,6 +126,8 @@ pub const deserializer = @import("io/serialization.zig").deserializer; |
| 126 | 126 | ||
| 127 | pub const BufferedAtomicFile = @import("io/buffered_atomic_file.zig").BufferedAtomicFile; | 127 | pub const BufferedAtomicFile = @import("io/buffered_atomic_file.zig").BufferedAtomicFile; |
| 128 | 128 | ||
| 129 | pub const StreamSource = @import("io/stream_source.zig").StreamSource; | ||
| 130 | |||
| 129 | /// Deprecated; use `std.fs.Dir.writeFile`. | 131 | /// Deprecated; use `std.fs.Dir.writeFile`. |
| 130 | pub fn writeFile(path: []const u8, data: []const u8) !void { | 132 | pub fn writeFile(path: []const u8, data: []const u8) !void { |
| 131 | return fs.cwd().writeFile(path, data); | 133 | return fs.cwd().writeFile(path, data); |
lib/std/io/fixed_buffer_stream.zig+22-19| ... | @@ -12,9 +12,9 @@ pub fn FixedBufferStream(comptime Buffer: type) type { | ... | @@ -12,9 +12,9 @@ pub fn FixedBufferStream(comptime Buffer: type) type { |
| 12 | buffer: Buffer, | 12 | buffer: Buffer, |
| 13 | pos: usize, | 13 | pos: usize, |
| 14 | 14 | ||
| 15 | pub const ReadError = error{EndOfStream}; | 15 | pub const ReadError = error{}; |
| 16 | pub const WriteError = error{OutOfMemory}; | 16 | pub const WriteError = error{NoSpaceLeft}; |
| 17 | pub const SeekError = error{EndOfStream}; | 17 | pub const SeekError = error{}; |
| 18 | pub const GetSeekPosError = error{}; | 18 | pub const GetSeekPosError = error{}; |
| 19 | 19 | ||
| 20 | pub const InStream = io.InStream(*Self, ReadError, read); | 20 | pub const InStream = io.InStream(*Self, ReadError, read); |
| ... | @@ -51,16 +51,16 @@ pub fn FixedBufferStream(comptime Buffer: type) type { | ... | @@ -51,16 +51,16 @@ pub fn FixedBufferStream(comptime Buffer: type) type { |
| 51 | mem.copy(u8, dest[0..size], self.buffer[self.pos..end]); | 51 | mem.copy(u8, dest[0..size], self.buffer[self.pos..end]); |
| 52 | self.pos = end; | 52 | self.pos = end; |
| 53 | 53 | ||
| 54 | if (size == 0) return error.EndOfStream; | ||
| 55 | return size; | 54 | return size; |
| 56 | } | 55 | } |
| 57 | 56 | ||
| 58 | /// If the returned number of bytes written is less than requested, the | 57 | /// If the returned number of bytes written is less than requested, the |
| 59 | /// buffer is full. Returns `error.OutOfMemory` when no bytes would be written. | 58 | /// buffer is full. Returns `error.NoSpaceLeft` when no bytes would be written. |
| 59 | /// Note: `error.NoSpaceLeft` matches the corresponding error from | ||
| 60 | /// `std.fs.File.WriteError`. | ||
| 60 | pub fn write(self: *Self, bytes: []const u8) WriteError!usize { | 61 | pub fn write(self: *Self, bytes: []const u8) WriteError!usize { |
| 61 | if (bytes.len == 0) return 0; | 62 | if (bytes.len == 0) return 0; |
| 62 | 63 | if (self.pos >= self.buffer.len) return error.NoSpaceLeft; | |
| 63 | assert(self.pos <= self.buffer.len); | ||
| 64 | 64 | ||
| 65 | const n = if (self.pos + bytes.len <= self.buffer.len) | 65 | const n = if (self.pos + bytes.len <= self.buffer.len) |
| 66 | bytes.len | 66 | bytes.len |
| ... | @@ -70,26 +70,27 @@ pub fn FixedBufferStream(comptime Buffer: type) type { | ... | @@ -70,26 +70,27 @@ pub fn FixedBufferStream(comptime Buffer: type) type { |
| 70 | mem.copy(u8, self.buffer[self.pos .. self.pos + n], bytes[0..n]); | 70 | mem.copy(u8, self.buffer[self.pos .. self.pos + n], bytes[0..n]); |
| 71 | self.pos += n; | 71 | self.pos += n; |
| 72 | 72 | ||
| 73 | if (n == 0) return error.OutOfMemory; | 73 | if (n == 0) return error.NoSpaceLeft; |
| 74 | 74 | ||
| 75 | return n; | 75 | return n; |
| 76 | } | 76 | } |
| 77 | 77 | ||
| 78 | pub fn seekTo(self: *Self, pos: u64) SeekError!void { | 78 | pub fn seekTo(self: *Self, pos: u64) SeekError!void { |
| 79 | const usize_pos = std.math.cast(usize, pos) catch return error.EndOfStream; | 79 | const usize_pos = std.math.cast(usize, pos) catch std.math.maxInt(usize); |
| 80 | if (usize_pos > self.buffer.len) return error.EndOfStream; | ||
| 81 | self.pos = usize_pos; | 80 | self.pos = usize_pos; |
| 82 | } | 81 | } |
| 83 | 82 | ||
| 84 | pub fn seekBy(self: *Self, amt: i64) SeekError!void { | 83 | pub fn seekBy(self: *Self, amt: i64) SeekError!void { |
| 85 | if (amt < 0) { | 84 | if (amt < 0) { |
| 86 | const abs_amt = std.math.cast(usize, -amt) catch return error.EndOfStream; | 85 | const abs_amt = std.math.cast(usize, -amt) catch std.math.maxInt(usize); |
| 87 | if (abs_amt > self.pos) return error.EndOfStream; | 86 | if (abs_amt > self.pos) { |
| 88 | self.pos -= abs_amt; | 87 | self.pos = 0; |
| 88 | } else { | ||
| 89 | self.pos -= abs_amt; | ||
| 90 | } | ||
| 89 | } else { | 91 | } else { |
| 90 | const usize_amt = std.math.cast(usize, amt) catch return error.EndOfStream; | 92 | const usize_amt = std.math.cast(usize, amt) catch std.math.maxInt(usize); |
| 91 | if (self.pos + usize_amt > self.buffer.len) return error.EndOfStream; | 93 | self.pos = std.math.add(usize, self.pos, usize_amt) catch std.math.maxInt(usize); |
| 92 | self.pos += usize_amt; | ||
| 93 | } | 94 | } |
| 94 | } | 95 | } |
| 95 | 96 | ||
| ... | @@ -101,6 +102,7 @@ pub fn FixedBufferStream(comptime Buffer: type) type { | ... | @@ -101,6 +102,7 @@ pub fn FixedBufferStream(comptime Buffer: type) type { |
| 101 | return self.pos; | 102 | return self.pos; |
| 102 | } | 103 | } |
| 103 | 104 | ||
| 105 | /// Asserts that the seek pos is within the buffer range. | ||
| 104 | pub fn getWritten(self: Self) []const u8 { | 106 | pub fn getWritten(self: Self) []const u8 { |
| 105 | return self.buffer[0..self.pos]; | 107 | return self.buffer[0..self.pos]; |
| 106 | } | 108 | } |
| ... | @@ -140,13 +142,13 @@ test "FixedBufferStream output 2" { | ... | @@ -140,13 +142,13 @@ test "FixedBufferStream output 2" { |
| 140 | try fbs.outStream().writeAll("world"); | 142 | try fbs.outStream().writeAll("world"); |
| 141 | testing.expect(mem.eql(u8, fbs.getWritten(), "Helloworld")); | 143 | testing.expect(mem.eql(u8, fbs.getWritten(), "Helloworld")); |
| 142 | 144 | ||
| 143 | testing.expectError(error.OutOfMemory, fbs.outStream().writeAll("!")); | 145 | testing.expectError(error.NoSpaceLeft, fbs.outStream().writeAll("!")); |
| 144 | testing.expect(mem.eql(u8, fbs.getWritten(), "Helloworld")); | 146 | testing.expect(mem.eql(u8, fbs.getWritten(), "Helloworld")); |
| 145 | 147 | ||
| 146 | fbs.reset(); | 148 | fbs.reset(); |
| 147 | testing.expect(fbs.getWritten().len == 0); | 149 | testing.expect(fbs.getWritten().len == 0); |
| 148 | 150 | ||
| 149 | testing.expectError(error.OutOfMemory, fbs.outStream().writeAll("Hello world!")); | 151 | testing.expectError(error.NoSpaceLeft, fbs.outStream().writeAll("Hello world!")); |
| 150 | testing.expect(mem.eql(u8, fbs.getWritten(), "Hello worl")); | 152 | testing.expect(mem.eql(u8, fbs.getWritten(), "Hello worl")); |
| 151 | } | 153 | } |
| 152 | 154 | ||
| ... | @@ -164,5 +166,6 @@ test "FixedBufferStream input" { | ... | @@ -164,5 +166,6 @@ test "FixedBufferStream input" { |
| 164 | testing.expect(read == 3); | 166 | testing.expect(read == 3); |
| 165 | testing.expect(mem.eql(u8, dest[0..3], bytes[4..7])); | 167 | testing.expect(mem.eql(u8, dest[0..3], bytes[4..7])); |
| 166 | 168 | ||
| 167 | testing.expectError(error.EndOfStream, fbs.inStream().read(dest[0..4])); | 169 | read = try fbs.inStream().read(dest[0..4]); |
| 170 | testing.expect(read == 0); | ||
| 168 | } | 171 | } |
lib/std/io/stream_source.zig created+90| ... | @@ -0,0 +1,90 @@ | ||
| 1 | const std = @import("../std.zig"); | ||
| 2 | const io = std.io; | ||
| 3 | const testing = std.testing; | ||
| 4 | |||
| 5 | /// Provides `io.InStream`, `io.OutStream`, and `io.SeekableStream` for in-memory buffers as | ||
| 6 | /// well as files. | ||
| 7 | /// For memory sources, if the supplied byte buffer is const, then `io.OutStream` is not available. | ||
| 8 | /// The error set of the stream functions is the error set of the corresponding file functions. | ||
| 9 | pub const StreamSource = union(enum) { | ||
| 10 | buffer: io.FixedBufferStream([]u8), | ||
| 11 | const_buffer: io.FixedBufferStream([]const u8), | ||
| 12 | file: std.fs.File, | ||
| 13 | |||
| 14 | pub const ReadError = std.fs.File.ReadError; | ||
| 15 | pub const WriteError = std.fs.File.WriteError; | ||
| 16 | pub const SeekError = std.fs.File.SeekError; | ||
| 17 | pub const GetSeekPosError = std.fs.File.GetPosError; | ||
| 18 | |||
| 19 | pub const InStream = io.InStream(*StreamSource, ReadError, read); | ||
| 20 | pub const OutStream = io.OutStream(*StreamSource, WriteError, write); | ||
| 21 | pub const SeekableStream = io.SeekableStream( | ||
| 22 | *StreamSource, | ||
| 23 | SeekError, | ||
| 24 | GetSeekPosError, | ||
| 25 | seekTo, | ||
| 26 | seekBy, | ||
| 27 | getPos, | ||
| 28 | getEndPos, | ||
| 29 | ); | ||
| 30 | |||
| 31 | pub fn read(self: *StreamSource, dest: []u8) ReadError!usize { | ||
| 32 | switch (self.*) { | ||
| 33 | .buffer => |*x| return x.read(dest), | ||
| 34 | .const_buffer => |*x| return x.read(dest), | ||
| 35 | .file => |x| return x.read(dest), | ||
| 36 | } | ||
| 37 | } | ||
| 38 | |||
| 39 | pub fn write(self: *StreamSource, bytes: []const u8) WriteError!usize { | ||
| 40 | switch (self.*) { | ||
| 41 | .buffer => |*x| return x.write(bytes), | ||
| 42 | .const_buffer => |*x| return x.write(bytes), | ||
| 43 | .file => |x| return x.write(bytes), | ||
| 44 | } | ||
| 45 | } | ||
| 46 | |||
| 47 | pub fn seekTo(self: *StreamSource, pos: u64) SeekError!void { | ||
| 48 | switch (self.*) { | ||
| 49 | .buffer => |*x| return x.seekTo(pos), | ||
| 50 | .const_buffer => |*x| return x.seekTo(pos), | ||
| 51 | .file => |x| return x.seekTo(pos), | ||
| 52 | } | ||
| 53 | } | ||
| 54 | |||
| 55 | pub fn seekBy(self: *StreamSource, amt: i64) SeekError!void { | ||
| 56 | switch (self.*) { | ||
| 57 | .buffer => |*x| return x.seekBy(amt), | ||
| 58 | .const_buffer => |*x| return x.seekBy(amt), | ||
| 59 | .file => |x| return x.seekBy(amt), | ||
| 60 | } | ||
| 61 | } | ||
| 62 | |||
| 63 | pub fn getEndPos(self: *StreamSource) GetSeekPosError!u64 { | ||
| 64 | switch (self.*) { | ||
| 65 | .buffer => |*x| return x.getEndPos(), | ||
| 66 | .const_buffer => |*x| return x.getEndPos(), | ||
| 67 | .file => |x| return x.getEndPos(), | ||
| 68 | } | ||
| 69 | } | ||
| 70 | |||
| 71 | pub fn getPos(self: *StreamSource) GetSeekPosError!u64 { | ||
| 72 | switch (self.*) { | ||
| 73 | .buffer => |*x| return x.getPos(), | ||
| 74 | .const_buffer => |*x| return x.getPos(), | ||
| 75 | .file => |x| return x.getPos(), | ||
| 76 | } | ||
| 77 | } | ||
| 78 | |||
| 79 | pub fn inStream(self: *StreamSource) InStream { | ||
| 80 | return .{ .context = self }; | ||
| 81 | } | ||
| 82 | |||
| 83 | pub fn outStream(self: *StreamSource) OutStream { | ||
| 84 | return .{ .context = self }; | ||
| 85 | } | ||
| 86 | |||
| 87 | pub fn seekableStream(self: *StreamSource) SeekableStream { | ||
| 88 | return .{ .context = self }; | ||
| 89 | } | ||
| 90 | }; | ||