| 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 | 48 | }; |
| 49 | 49 | const elf_hdrs = try std.elf.readAllHeaders(allocator, elf_file); |
| 50 | 50 | |
| 51 | var binaryElfOutput = BinaryElfOutput.init(arena_allocator); | |
| 52 | ||
| 53 | 51 | for (elf_hdrs.section_headers) |section, i| { |
| 54 | 52 | if (sectionValidForOutput(section)) { |
| 55 | 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 | 162 | var out_file = try fs.cwd().createFile(raw_path, .{}); |
| 165 | 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 | 166 | defer binary_elf_output.deinit(); |
| 169 | 167 | |
| 170 | 168 | for (binary_elf_output.sections.toSlice()) |section| { |
lib/std/elf.zig+12-12| ... | ... | @@ -1,5 +1,5 @@ |
| 1 | const builtin = @import("builtin"); | |
| 2 | 1 | const std = @import("std.zig"); |
| 2 | const builtin = std.builtin; | |
| 3 | 3 | const io = std.io; |
| 4 | 4 | const os = std.os; |
| 5 | 5 | const math = std.math; |
| ... | ... | @@ -352,7 +352,7 @@ pub fn readHeader(file: File) !Header { |
| 352 | 352 | if (!mem.eql(u8, hdr32.e_ident[0..4], "\x7fELF")) return error.InvalidElfMagic; |
| 353 | 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 | 356 | ELFDATA2LSB => .Little, |
| 357 | 357 | ELFDATA2MSB => .Big, |
| 358 | 358 | else => return error.InvalidElfEndian, |
| ... | ... | @@ -406,8 +406,8 @@ pub fn readAllHeaders(allocator: *mem.Allocator, file: File) !AllHeaders { |
| 406 | 406 | // Treat section headers and program headers as byte buffers. For 32-bit ELF and |
| 407 | 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]; | |
| 410 | const phdr_buf = std.mem.sliceToBytes(hdrs.program_headers)[0 .. hdrs.header.phentsize * hdrs.header.phnum]; | |
| 409 | const shdr_buf = std.mem.sliceAsBytes(hdrs.section_headers)[0 .. hdrs.header.shentsize * hdrs.header.shnum]; | |
| 410 | const phdr_buf = std.mem.sliceAsBytes(hdrs.program_headers)[0 .. hdrs.header.phentsize * hdrs.header.phnum]; | |
| 411 | 411 | |
| 412 | 412 | try preadNoEof(file, shdr_buf, hdrs.header.shoff); |
| 413 | 413 | try preadNoEof(file, phdr_buf, hdrs.header.phoff); |
| ... | ... | @@ -430,14 +430,14 @@ pub fn readAllHeaders(allocator: *mem.Allocator, file: File) !AllHeaders { |
| 430 | 430 | } |
| 431 | 431 | for (hdrs.program_headers) |*phdr, i| { |
| 432 | 432 | phdr.* = .{ |
| 433 | .p_type = int(is_64, need_bswap, phdrs32[i].p_type, shdr.p_type), | |
| 434 | .p_offset = int(is_64, need_bswap, phdrs32[i].p_offset, shdr.p_offset), | |
| 435 | .p_vaddr = int(is_64, need_bswap, phdrs32[i].p_vaddr, shdr.p_vaddr), | |
| 436 | .p_paddr = int(is_64, need_bswap, phdrs32[i].p_paddr, shdr.p_paddr), | |
| 437 | .p_filesz = int(is_64, need_bswap, phdrs32[i].p_filesz, shdr.p_filesz), | |
| 438 | .p_memsz = int(is_64, need_bswap, phdrs32[i].p_memsz, shdr.p_memsz), | |
| 439 | .p_flags = int(is_64, need_bswap, phdrs32[i].p_flags, shdr.p_flags), | |
| 440 | .p_align = int(is_64, need_bswap, phdrs32[i].p_align, shdr.p_align), | |
| 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, phdr.p_offset), | |
| 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, phdr.p_paddr), | |
| 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, phdr.p_memsz), | |
| 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, phdr.p_align), | |
| 441 | 441 | }; |
| 442 | 442 | } |
| 443 | 443 | return hdrs; |
lib/std/io.zig+2| ... | ... | @@ -126,6 +126,8 @@ pub const deserializer = @import("io/serialization.zig").deserializer; |
| 126 | 126 | |
| 127 | 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 | 131 | /// Deprecated; use `std.fs.Dir.writeFile`. |
| 130 | 132 | pub fn writeFile(path: []const u8, data: []const u8) !void { |
| 131 | 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 | 12 | buffer: Buffer, |
| 13 | 13 | pos: usize, |
| 14 | 14 | |
| 15 | pub const ReadError = error{EndOfStream}; | |
| 16 | pub const WriteError = error{OutOfMemory}; | |
| 17 | pub const SeekError = error{EndOfStream}; | |
| 15 | pub const ReadError = error{}; | |
| 16 | pub const WriteError = error{NoSpaceLeft}; | |
| 17 | pub const SeekError = error{}; | |
| 18 | 18 | pub const GetSeekPosError = error{}; |
| 19 | 19 | |
| 20 | 20 | pub const InStream = io.InStream(*Self, ReadError, read); |
| ... | ... | @@ -51,16 +51,16 @@ pub fn FixedBufferStream(comptime Buffer: type) type { |
| 51 | 51 | mem.copy(u8, dest[0..size], self.buffer[self.pos..end]); |
| 52 | 52 | self.pos = end; |
| 53 | 53 | |
| 54 | if (size == 0) return error.EndOfStream; | |
| 55 | 54 | return size; |
| 56 | 55 | } |
| 57 | 56 | |
| 58 | 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 | 61 | pub fn write(self: *Self, bytes: []const u8) WriteError!usize { |
| 61 | 62 | if (bytes.len == 0) return 0; |
| 62 | ||
| 63 | assert(self.pos <= self.buffer.len); | |
| 63 | if (self.pos >= self.buffer.len) return error.NoSpaceLeft; | |
| 64 | 64 | |
| 65 | 65 | const n = if (self.pos + bytes.len <= self.buffer.len) |
| 66 | 66 | bytes.len |
| ... | ... | @@ -70,26 +70,27 @@ pub fn FixedBufferStream(comptime Buffer: type) type { |
| 70 | 70 | mem.copy(u8, self.buffer[self.pos .. self.pos + n], bytes[0..n]); |
| 71 | 71 | self.pos += n; |
| 72 | 72 | |
| 73 | if (n == 0) return error.OutOfMemory; | |
| 73 | if (n == 0) return error.NoSpaceLeft; | |
| 74 | 74 | |
| 75 | 75 | return n; |
| 76 | 76 | } |
| 77 | 77 | |
| 78 | 78 | pub fn seekTo(self: *Self, pos: u64) SeekError!void { |
| 79 | const usize_pos = std.math.cast(usize, pos) catch return error.EndOfStream; | |
| 80 | if (usize_pos > self.buffer.len) return error.EndOfStream; | |
| 79 | const usize_pos = std.math.cast(usize, pos) catch std.math.maxInt(usize); | |
| 81 | 80 | self.pos = usize_pos; |
| 82 | 81 | } |
| 83 | 82 | |
| 84 | 83 | pub fn seekBy(self: *Self, amt: i64) SeekError!void { |
| 85 | 84 | if (amt < 0) { |
| 86 | const abs_amt = std.math.cast(usize, -amt) catch return error.EndOfStream; | |
| 87 | if (abs_amt > self.pos) return error.EndOfStream; | |
| 88 | self.pos -= abs_amt; | |
| 85 | const abs_amt = std.math.cast(usize, -amt) catch std.math.maxInt(usize); | |
| 86 | if (abs_amt > self.pos) { | |
| 87 | self.pos = 0; | |
| 88 | } else { | |
| 89 | self.pos -= abs_amt; | |
| 90 | } | |
| 89 | 91 | } else { |
| 90 | const usize_amt = std.math.cast(usize, amt) catch return error.EndOfStream; | |
| 91 | if (self.pos + usize_amt > self.buffer.len) return error.EndOfStream; | |
| 92 | self.pos += usize_amt; | |
| 92 | const usize_amt = std.math.cast(usize, amt) catch std.math.maxInt(usize); | |
| 93 | self.pos = std.math.add(usize, self.pos, usize_amt) catch std.math.maxInt(usize); | |
| 93 | 94 | } |
| 94 | 95 | } |
| 95 | 96 | |
| ... | ... | @@ -101,6 +102,7 @@ pub fn FixedBufferStream(comptime Buffer: type) type { |
| 101 | 102 | return self.pos; |
| 102 | 103 | } |
| 103 | 104 | |
| 105 | /// Asserts that the seek pos is within the buffer range. | |
| 104 | 106 | pub fn getWritten(self: Self) []const u8 { |
| 105 | 107 | return self.buffer[0..self.pos]; |
| 106 | 108 | } |
| ... | ... | @@ -140,13 +142,13 @@ test "FixedBufferStream output 2" { |
| 140 | 142 | try fbs.outStream().writeAll("world"); |
| 141 | 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 | 146 | testing.expect(mem.eql(u8, fbs.getWritten(), "Helloworld")); |
| 145 | 147 | |
| 146 | 148 | fbs.reset(); |
| 147 | 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 | 152 | testing.expect(mem.eql(u8, fbs.getWritten(), "Hello worl")); |
| 151 | 153 | } |
| 152 | 154 | |
| ... | ... | @@ -164,5 +166,6 @@ test "FixedBufferStream input" { |
| 164 | 166 | testing.expect(read == 3); |
| 165 | 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 | }; |