Skip to content

Commit 1f99f5e

Browse files
author
Felix "xq" Queißner
committed
Implements basic writing to files
1 parent 0db84d3 commit 1f99f5e

File tree

4 files changed

+108
-16
lines changed

4 files changed

+108
-16
lines changed

.gitignore

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
.zig-cache/
22
zig-out/
3-
.vscode/
3+
.vscode/
4+
.dim-out/

justfile

+4-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11

22
zig:="zig-0.14.0"
33

4+
out:=".dim-out"
5+
46
default: install test
57

68
install:
@@ -23,8 +25,8 @@ behaviour-tests: \
2325
(behaviour-test "tests/part/mbr/basic-single-part-unsized.dis")
2426

2527
behaviour-test script: install
26-
./zig-out/bin/dim --output .zig-cache/disk.img --script "{{script}}" --size 30M
27-
28+
@mkdir -p {{ join(out, parent_directory(script)) }}
29+
./zig-out/bin/dim --output {{ join(out, without_extension(script) + ".img") }} --script "{{script}}" --size 30M
2830

2931
fuzz:
3032
{{zig}} build install test --fuzz --port 35991

src/components/FillData.zig

+1-1
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,6 @@ pub fn parse(ctx: dim.Context) !dim.Content {
2222
fn render(self: *FillData, stream: *dim.BinaryStream) dim.Content.RenderError!void {
2323
try stream.writer().writeByteNTimes(
2424
self.fill_value,
25-
stream.capacity,
25+
stream.length,
2626
);
2727
}

src/dim.zig

+101-12
Original file line numberDiff line numberDiff line change
@@ -133,9 +133,7 @@ pub fn main() !u8 {
133133

134134
try output_file.file.setEndPos(size_limit);
135135

136-
var stream = BinaryStream{
137-
.capacity = size_limit,
138-
};
136+
var stream: BinaryStream = .init_file(output_file.file, size_limit);
139137

140138
try root_content.render(&stream);
141139

@@ -338,7 +336,7 @@ const Environment = struct {
338336
///
339337
///
340338
pub const Content = struct {
341-
pub const RenderError = FileName.OpenError || FileHandle.ReadError || error{WriteError};
339+
pub const RenderError = FileName.OpenError || FileHandle.ReadError || BinaryStream.WriteError;
342340
pub const GuessError = FileName.GetSizeError;
343341

344342
obj: *anyopaque,
@@ -509,26 +507,117 @@ pub const FileHandle = struct {
509507
};
510508

511509
pub const BinaryStream = struct {
512-
pub const WriteError = error{IoError};
510+
pub const WriteError = error{ Overflow, IoError };
513511
pub const Writer = std.io.Writer(*BinaryStream, WriteError, write_some);
514512

513+
backing: Backing,
514+
515+
virtual_offset: u64 = 0,
516+
515517
/// Max number of bytes that can be written
516-
capacity: u64,
518+
length: u64,
519+
520+
/// Constructs a BinaryStream from a slice.
521+
pub fn init_buffer(data: []u8) BinaryStream {
522+
return .{
523+
.backing = .{ .buffer = data.ptr },
524+
.length = data.len,
525+
};
526+
}
527+
528+
/// Constructs a BinaryStream from a file.
529+
pub fn init_file(file: std.fs.File, max_len: u64) BinaryStream {
530+
return .{
531+
.backing = .{
532+
.file = .{
533+
.file = file,
534+
.base = 0,
535+
},
536+
},
537+
.length = max_len,
538+
};
539+
}
540+
541+
/// Returns a view into the stream.
542+
pub fn slice(bs: BinaryStream, offset: u64, length: ?u64) error{OutOfBounds}!BinaryStream {
543+
if (offset > bs.length)
544+
return error.OutOfBounds;
545+
const true_length = length or bs.length - offset;
546+
if (true_length > bs.length)
547+
return error.OutOfBounds;
548+
549+
return .{
550+
.length = true_length,
551+
.backing = switch (bs.backing) {
552+
.buffer => |old| .{ .buffer = old + offset },
553+
.file => |old| .{
554+
.file = old.file,
555+
.base = old.base + offset,
556+
},
557+
},
558+
};
559+
}
560+
561+
pub fn write(bs: *BinaryStream, offset: u64, data: []const u8) WriteError!void {
562+
const end_pos = offset + data.len;
563+
if (end_pos > bs.length)
564+
return error.Overflow;
565+
566+
switch (bs.backing) {
567+
.buffer => |ptr| @memcpy(ptr[@intCast(offset)..][0..data.len], data),
568+
.file => |state| {
569+
state.file.seekTo(state.base + offset) catch return error.IoError;
570+
state.file.writeAll(data) catch |err| switch (err) {
571+
error.DiskQuota, error.NoSpaceLeft, error.FileTooBig => return error.Overflow,
572+
573+
error.InputOutput,
574+
error.DeviceBusy,
575+
error.InvalidArgument,
576+
error.AccessDenied,
577+
error.BrokenPipe,
578+
error.SystemResources,
579+
error.OperationAborted,
580+
error.NotOpenForWriting,
581+
error.LockViolation,
582+
error.WouldBlock,
583+
error.ConnectionResetByPeer,
584+
error.ProcessNotFound,
585+
error.NoDevice,
586+
error.Unexpected,
587+
=> return error.IoError,
588+
};
589+
},
590+
}
591+
}
592+
593+
pub fn seek_to(bs: *BinaryStream, offset: u64) error{OutOfBounds}!void {
594+
if (offset > bs.length)
595+
return error.OutOfBounds;
596+
bs.virtual_offset = offset;
597+
}
517598

518599
pub fn writer(bs: *BinaryStream) Writer {
519600
return .{ .context = bs };
520601
}
521602

522603
fn write_some(stream: *BinaryStream, data: []const u8) WriteError!usize {
523-
_ = stream;
524-
// TODO: Implement write_some!
604+
const remaining_len = stream.length - stream.virtual_offset;
605+
606+
const written_len: usize = @intCast(@min(remaining_len, data.len));
525607

526-
// std.debug.print("dummy write of '{}'\n", .{
527-
// std.fmt.fmtSliceHexUpper(data),
528-
// });
608+
try stream.write(stream.virtual_offset, data[0..written_len]);
609+
stream.virtual_offset += written_len;
529610

530-
return data.len;
611+
return written_len;
531612
}
613+
614+
pub const Backing = union(enum) {
615+
file: struct {
616+
file: std.fs.File,
617+
base: u64,
618+
},
619+
buffer: [*]u8,
620+
};
532621
};
533622

534623
test {

0 commit comments

Comments
 (0)