1- /// Generates bytes.
1+ //! Generates bytes.
22const Bytes = @This ();
33
44const std = @import ("std" );
@@ -7,9 +7,7 @@ const Generator = @import("Generator.zig");
77/// Random number generator.
88rand : std.Random ,
99
10- /// The minimum and maximum length of the generated bytes. The maximum
11- /// length will be capped to the length of the buffer passed in if the
12- /// buffer length is smaller.
10+ /// The minimum and maximum length of the generated bytes.
1311min_len : usize = 1 ,
1412max_len : usize = std .math .maxInt (usize ),
1513
@@ -18,23 +16,79 @@ max_len: usize = std.math.maxInt(usize),
1816/// side effect of the generator, not an intended use case.
1917alphabet : ? []const u8 = null ,
2018
21- /// Predefined alphabets.
22- pub const Alphabet = struct {
23- pub const ascii = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*()_+-=[]{}|;':\\ \" ,./<>?`~" ;
24- };
19+ /// Generate an alphabet given a function that returns true/false for a
20+ /// given byte.
21+ pub fn generateAlphabet (comptime func : fn (u8 ) bool ) []const u8 {
22+ @setEvalBranchQuota (3000 );
23+ var count = 0 ;
24+ for (0.. 256) | c | {
25+ if (func (c )) count += 1 ;
26+ }
27+ var alphabet : [count ]u8 = undefined ;
28+ var i = 0 ;
29+ for (0.. 256) | c | {
30+ if (func (c )) {
31+ alphabet [i ] = c ;
32+ i += 1 ;
33+ }
34+ }
35+ const result = alphabet ;
36+ return & result ;
37+ }
2538
2639pub fn generator (self : * Bytes ) Generator {
2740 return .init (self , next );
2841}
2942
30- pub fn next (self : * Bytes , writer : * std.Io.Writer , max_len : usize ) Generator.Error ! void {
31- std .debug .assert (max_len >= 1 );
32- const len = @min (
33- self .rand .intRangeAtMostBiased (usize , self .min_len , self .max_len ),
34- max_len ,
35- );
43+ /// Return a copy of the Bytes, but with a new alphabet.
44+ pub fn newAlphabet (self : * const Bytes , new_alphabet : ? []const u8 ) Bytes {
45+ return .{
46+ .rand = self .rand ,
47+ .alphabet = new_alphabet ,
48+ .min_len = self .min_len ,
49+ .max_len = self .max_len ,
50+ };
51+ }
52+
53+ /// Return a copy of the Bytes, but with a new min_len. The new min
54+ /// len cannot be more than the previous max_len.
55+ pub fn atLeast (self : * const Bytes , new_min_len : usize ) Bytes {
56+ return .{
57+ .rand = self .rand ,
58+ .alphabet = self .alphabet ,
59+ .min_len = @min (self .max_len , new_min_len ),
60+ .max_len = self .max_len ,
61+ };
62+ }
63+
64+ /// Return a copy of the Bytes, but with a new max_len. The new max_len cannot
65+ /// be more the previous max_len.
66+ pub fn atMost (self : * const Bytes , new_max_len : usize ) Bytes {
67+ return .{
68+ .rand = self .rand ,
69+ .alphabet = self .alphabet ,
70+ .min_len = @min (self .min_len , @min (self .max_len , new_max_len )),
71+ .max_len = @min (self .max_len , new_max_len ),
72+ };
73+ }
74+
75+ pub fn next (self : * const Bytes , writer : * std.Io.Writer , max_len : usize ) std.Io.Writer.Error ! void {
76+ _ = try self .atMost (max_len ).write (writer );
77+ }
78+
79+ pub fn format (self : * const Bytes , writer : * std.Io.Writer ) std.Io.Writer.Error ! void {
80+ _ = try self .write (writer );
81+ }
82+
83+ /// Write some random data and return the number of bytes written.
84+ pub fn write (self : * const Bytes , writer : * std.Io.Writer ) std.Io.Writer.Error ! usize {
85+ std .debug .assert (self .min_len >= 1 );
86+ std .debug .assert (self .max_len >= self .min_len );
87+
88+ const len = self .rand .intRangeAtMostBiased (usize , self .min_len , self .max_len );
3689
3790 var buf : [8 ]u8 = undefined ;
91+
3892 var remaining = len ;
3993 while (remaining > 0 ) {
4094 const data = buf [0.. @min (remaining , buf .len )];
@@ -45,16 +99,20 @@ pub fn next(self: *Bytes, writer: *std.Io.Writer, max_len: usize) Generator.Erro
4599 try writer .writeAll (data );
46100 remaining -= data .len ;
47101 }
102+
103+ return len ;
48104}
49105
50106test "bytes" {
51107 const testing = std .testing ;
52108 var prng = std .Random .DefaultPrng .init (0 );
53109 var buf : [256 ]u8 = undefined ;
54110 var writer : std.Io.Writer = .fixed (& buf );
55- var v : Bytes = .{ .rand = prng .random () };
56- v .min_len = buf .len ;
57- v .max_len = buf .len ;
111+ var v : Bytes = .{
112+ .rand = prng .random (),
113+ .min_len = buf .len ,
114+ .max_len = buf .len ,
115+ };
58116 const gen = v .generator ();
59117 try gen .next (& writer , buf .len );
60118 try testing .expectEqual (buf .len , writer .buffered ().len );
0 commit comments