aboutsummaryrefslogtreecommitdiff
path: root/vendor/libghostty-vt/src/synthetic/Bytes.zig
diff options
context:
space:
mode:
authorCan Celik <ogulcancelik@gmail.com>2026-04-04 19:22:04 +0300
committerCan Celik <ogulcancelik@gmail.com>2026-04-05 01:23:06 +0300
commit41dd733ca7123c9ac4bfc6c781697a660e95b052 (patch)
tree3fc91815ca139ef2e0b281bba0abda4ef15175f4 /vendor/libghostty-vt/src/synthetic/Bytes.zig
parent55c138263e190a1e79d4b997bfb9397306c0ec1f (diff)
feat: finish ghostty pane backend integration
Diffstat (limited to 'vendor/libghostty-vt/src/synthetic/Bytes.zig')
-rw-r--r--vendor/libghostty-vt/src/synthetic/Bytes.zig119
1 files changed, 119 insertions, 0 deletions
diff --git a/vendor/libghostty-vt/src/synthetic/Bytes.zig b/vendor/libghostty-vt/src/synthetic/Bytes.zig
new file mode 100644
index 00000000..7d4c34a3
--- /dev/null
+++ b/vendor/libghostty-vt/src/synthetic/Bytes.zig
@@ -0,0 +1,119 @@
+//! Generates bytes.
+const Bytes = @This();
+
+const std = @import("std");
+const Generator = @import("Generator.zig");
+
+/// Random number generator.
+rand: std.Random,
+
+/// The minimum and maximum length of the generated bytes.
+min_len: usize = 1,
+max_len: usize = std.math.maxInt(usize),
+
+/// The possible bytes that can be generated. If a byte is duplicated
+/// in the alphabet, it will be more likely to be generated. That's a
+/// side effect of the generator, not an intended use case.
+alphabet: ?[]const u8 = null,
+
+/// Generate an alphabet given a function that returns true/false for a
+/// given byte.
+pub fn generateAlphabet(comptime func: fn (u8) bool) []const u8 {
+ @setEvalBranchQuota(3000);
+ var count = 0;
+ for (0..256) |c| {
+ if (func(c)) count += 1;
+ }
+ var alphabet: [count]u8 = undefined;
+ var i = 0;
+ for (0..256) |c| {
+ if (func(c)) {
+ alphabet[i] = c;
+ i += 1;
+ }
+ }
+ const result = alphabet;
+ return &result;
+}
+
+pub fn generator(self: *Bytes) Generator {
+ return .init(self, next);
+}
+
+/// Return a copy of the Bytes, but with a new alphabet.
+pub fn newAlphabet(self: *const Bytes, new_alphabet: ?[]const u8) Bytes {
+ return .{
+ .rand = self.rand,
+ .alphabet = new_alphabet,
+ .min_len = self.min_len,
+ .max_len = self.max_len,
+ };
+}
+
+/// Return a copy of the Bytes, but with a new min_len. The new min
+/// len cannot be more than the previous max_len.
+pub fn atLeast(self: *const Bytes, new_min_len: usize) Bytes {
+ return .{
+ .rand = self.rand,
+ .alphabet = self.alphabet,
+ .min_len = @min(self.max_len, new_min_len),
+ .max_len = self.max_len,
+ };
+}
+
+/// Return a copy of the Bytes, but with a new max_len. The new max_len cannot
+/// be more the previous max_len.
+pub fn atMost(self: *const Bytes, new_max_len: usize) Bytes {
+ return .{
+ .rand = self.rand,
+ .alphabet = self.alphabet,
+ .min_len = @min(self.min_len, @min(self.max_len, new_max_len)),
+ .max_len = @min(self.max_len, new_max_len),
+ };
+}
+
+pub fn next(self: *const Bytes, writer: *std.Io.Writer, max_len: usize) std.Io.Writer.Error!void {
+ _ = try self.atMost(max_len).write(writer);
+}
+
+pub fn format(self: *const Bytes, writer: *std.Io.Writer) std.Io.Writer.Error!void {
+ _ = try self.write(writer);
+}
+
+/// Write some random data and return the number of bytes written.
+pub fn write(self: *const Bytes, writer: *std.Io.Writer) std.Io.Writer.Error!usize {
+ std.debug.assert(self.min_len >= 1);
+ std.debug.assert(self.max_len >= self.min_len);
+
+ const len = self.rand.intRangeAtMostBiased(usize, self.min_len, self.max_len);
+
+ var buf: [8]u8 = undefined;
+
+ var remaining = len;
+ while (remaining > 0) {
+ const data = buf[0..@min(remaining, buf.len)];
+ self.rand.bytes(data);
+ if (self.alphabet) |alphabet| {
+ for (data) |*byte| byte.* = alphabet[byte.* % alphabet.len];
+ }
+ try writer.writeAll(data);
+ remaining -= data.len;
+ }
+
+ return len;
+}
+
+test "bytes" {
+ const testing = std.testing;
+ var prng = std.Random.DefaultPrng.init(0);
+ var buf: [256]u8 = undefined;
+ var writer: std.Io.Writer = .fixed(&buf);
+ var v: Bytes = .{
+ .rand = prng.random(),
+ .min_len = buf.len,
+ .max_len = buf.len,
+ };
+ const gen = v.generator();
+ try gen.next(&writer, buf.len);
+ try testing.expectEqual(buf.len, writer.buffered().len);
+}