@@ -133,9 +133,7 @@ pub fn main() !u8 {
133
133
134
134
try output_file .file .setEndPos (size_limit );
135
135
136
- var stream = BinaryStream {
137
- .capacity = size_limit ,
138
- };
136
+ var stream : BinaryStream = .init_file (output_file .file , size_limit );
139
137
140
138
try root_content .render (& stream );
141
139
@@ -338,7 +336,7 @@ const Environment = struct {
338
336
///
339
337
///
340
338
pub const Content = struct {
341
- pub const RenderError = FileName .OpenError || FileHandle .ReadError || error { WriteError } ;
339
+ pub const RenderError = FileName .OpenError || FileHandle .ReadError || BinaryStream . WriteError ;
342
340
pub const GuessError = FileName .GetSizeError ;
343
341
344
342
obj : * anyopaque ,
@@ -509,26 +507,117 @@ pub const FileHandle = struct {
509
507
};
510
508
511
509
pub const BinaryStream = struct {
512
- pub const WriteError = error {IoError };
510
+ pub const WriteError = error { Overflow , IoError };
513
511
pub const Writer = std .io .Writer (* BinaryStream , WriteError , write_some );
514
512
513
+ backing : Backing ,
514
+
515
+ virtual_offset : u64 = 0 ,
516
+
515
517
/// 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
+ }
517
598
518
599
pub fn writer (bs : * BinaryStream ) Writer {
519
600
return .{ .context = bs };
520
601
}
521
602
522
603
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 ));
525
607
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 ;
529
610
530
- return data . len ;
611
+ return written_len ;
531
612
}
613
+
614
+ pub const Backing = union (enum ) {
615
+ file : struct {
616
+ file : std.fs.File ,
617
+ base : u64 ,
618
+ },
619
+ buffer : [* ]u8 ,
620
+ };
532
621
};
533
622
534
623
test {
0 commit comments