authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-03-11 15:40:34-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-03-11 15:40:34-04:00
log431d76c0233271de6a30aa626ccb1553dc241722
tree211266569e5d20fbe264fef34c885b957bc32938
parentc71991c869fc8c997c2714fe1b53caef23449c9c
signaturelock-open Commit is signed but in an unrecognized format.

add std.io.StreamSource and fixes to emitRaw


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);
5050
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();
166164
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();
169167
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 @@
1const builtin = @import("builtin");
2const std = @import("std.zig");1const std = @import("std.zig");
2const builtin = std.builtin;
3const io = std.io;3const io = std.io;
4const os = std.os;4const os = std.os;
5const math = std.math;5const 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;
354354
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 and406 // 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.
408408
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];
411411
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;
126126
127pub const BufferedAtomicFile = @import("io/buffered_atomic_file.zig").BufferedAtomicFile;127pub const BufferedAtomicFile = @import("io/buffered_atomic_file.zig").BufferedAtomicFile;
128128
129pub const StreamSource = @import("io/stream_source.zig").StreamSource;
130
129/// Deprecated; use `std.fs.Dir.writeFile`.131/// Deprecated; use `std.fs.Dir.writeFile`.
130pub fn writeFile(path: []const u8, data: []const u8) !void {132pub 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,
1414
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{};
1919
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;
5353
54 if (size == 0) return error.EndOfStream;
55 return size;54 return size;
56 }55 }
5756
58 /// If the returned number of bytes written is less than requested, the57 /// 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;
6263 if (self.pos >= self.buffer.len) return error.NoSpaceLeft;
63 assert(self.pos <= self.buffer.len);
6464
65 const n = if (self.pos + bytes.len <= self.buffer.len)65 const n = if (self.pos + bytes.len <= self.buffer.len)
66 bytes.len66 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;
7272
73 if (n == 0) return error.OutOfMemory;73 if (n == 0) return error.NoSpaceLeft;
7474
75 return n;75 return n;
76 }76 }
7777
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 }
8382
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 }
9596
...@@ -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 }
103104
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"));
142144
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"));
145147
146 fbs.reset();148 fbs.reset();
147 testing.expect(fbs.getWritten().len == 0);149 testing.expect(fbs.getWritten().len == 0);
148150
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}
152154
...@@ -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]));
166168
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 @@
1const std = @import("../std.zig");
2const io = std.io;
3const 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.
9pub 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};