@@ -464,34 +464,54 @@ pub fn writeVecAll(w: *Writer, data: [][]const u8) Error!void {
464
464
465
465
/// The `data` parameter is mutable because this function needs to mutate the
466
466
/// fields in order to handle partial writes from `VTable.writeSplat`.
467
+ /// `data` will be restored to its original state before returning.
467
468
pub fn writeSplatAll (w : * Writer , data : [][]const u8 , splat : usize ) Error ! void {
468
469
var index : usize = 0 ;
469
470
var truncate : usize = 0 ;
470
- var remaining_splat = splat ;
471
471
while (index + 1 < data .len ) {
472
472
{
473
473
const untruncated = data [index ];
474
474
data [index ] = untruncated [truncate .. ];
475
475
defer data [index ] = untruncated ;
476
- truncate += try w .writeSplat (data [index .. ], remaining_splat );
476
+ truncate += try w .writeSplat (data [index .. ], splat );
477
477
}
478
- while (truncate >= data [index ].len ) {
479
- if (index + 1 < data .len ) {
480
- truncate -= data [index ].len ;
481
- index += 1 ;
482
- } else {
483
- const last = data [data .len - 1 ];
484
- remaining_splat -= @divExact (truncate , last .len );
485
- while (remaining_splat > 0 ) {
486
- const n = try w .writeSplat (data [data .len - 1 .. ][0.. 1], remaining_splat );
487
- remaining_splat -= @divExact (n , last .len );
488
- }
489
- return ;
490
- }
478
+ while (truncate >= data [index ].len and index + 1 < data .len ) {
479
+ truncate -= data [index ].len ;
480
+ index += 1 ;
481
+ }
482
+ }
483
+
484
+ // Deal with any left over splats
485
+ if (data .len != 0 and truncate < data [index ].len * splat ) {
486
+ std .debug .assert (index == data .len - 1 );
487
+ var remaining_splat = splat ;
488
+ while (true ) {
489
+ remaining_splat -= truncate / data [index ].len ;
490
+ truncate %= data [index ].len ;
491
+ if (remaining_splat == 0 ) break ;
492
+ truncate += try w .writeSplat (&.{ data [index ][truncate .. ], data [index ] }, remaining_splat - 1 );
491
493
}
492
494
}
493
495
}
494
496
497
+ test writeSplatAll {
498
+ var aw : Writer.Allocating = .init (testing .allocator );
499
+ defer aw .deinit ();
500
+
501
+ var buffers = [_ ][]const u8 { "ba" , "na" };
502
+ try aw .writer .writeSplatAll (& buffers , 2 );
503
+ try testing .expectEqualStrings ("banana" , aw .writer .buffered ());
504
+ }
505
+
506
+ test "writeSplatAll works with a single buffer" {
507
+ var aw : Writer.Allocating = .init (testing .allocator );
508
+ defer aw .deinit ();
509
+
510
+ var message : [1 ][]const u8 = .{"hello" };
511
+ try aw .writer .writeSplatAll (& message , 3 );
512
+ try testing .expectEqualStrings ("hellohellohello" , aw .writer .buffered ());
513
+ }
514
+
495
515
pub fn write (w : * Writer , bytes : []const u8 ) Error ! usize {
496
516
if (w .end + bytes .len <= w .buffer .len ) {
497
517
@branchHint (.likely );
@@ -763,6 +783,14 @@ pub fn splatByteAll(w: *Writer, byte: u8, n: usize) Error!void {
763
783
while (remaining > 0 ) remaining -= try w .splatByte (byte , remaining );
764
784
}
765
785
786
+ test splatByteAll {
787
+ var aw : Writer.Allocating = .init (testing .allocator );
788
+ defer aw .deinit ();
789
+
790
+ try aw .writer .splatByteAll ('7' , 45 );
791
+ try testing .expectEqualStrings ("7" ** 45 , aw .writer .buffered ());
792
+ }
793
+
766
794
/// Writes the same byte many times, allowing short writes.
767
795
///
768
796
/// Does maximum of one underlying `VTable.drain`.
@@ -778,13 +806,21 @@ pub fn splatBytesAll(w: *Writer, bytes: []const u8, splat: usize) Error!void {
778
806
while (remaining_bytes > 0 ) {
779
807
const leftover = remaining_bytes % bytes .len ;
780
808
const buffers : [2 ][]const u8 = .{ bytes [bytes .len - leftover .. ], bytes };
781
- remaining_bytes -= try w .splatBytes (& buffers , splat );
809
+ remaining_bytes -= try w .writeSplat (& buffers , splat );
782
810
}
783
811
}
784
812
813
+ test splatBytesAll {
814
+ var aw : Writer.Allocating = .init (testing .allocator );
815
+ defer aw .deinit ();
816
+
817
+ try aw .writer .splatBytesAll ("hello" , 3 );
818
+ try testing .expectEqualStrings ("hellohellohello" , aw .writer .buffered ());
819
+ }
820
+
785
821
/// Writes the same slice many times, allowing short writes.
786
822
///
787
- /// Does maximum of one underlying `VTable.writeSplat `.
823
+ /// Does maximum of one underlying `VTable.drain `.
788
824
pub fn splatBytes (w : * Writer , bytes : []const u8 , n : usize ) Error ! usize {
789
825
return writeSplat (w , &.{bytes }, n );
790
826
}
0 commit comments