summaryrefslogtreecommitdiff
path: root/src/detached/wire.zig
diff options
context:
space:
mode:
Diffstat (limited to 'src/detached/wire.zig')
-rw-r--r--src/detached/wire.zig20
1 files changed, 16 insertions, 4 deletions
diff --git a/src/detached/wire.zig b/src/detached/wire.zig
index 5d52e2df..416330e8 100644
--- a/src/detached/wire.zig
+++ b/src/detached/wire.zig
@@ -2,8 +2,9 @@
//! Native struct layout never reaches the wire.
const std = @import("std");
const pardes = @import("../pardes.zig");
+const limits = @import("../memory.zig").limits;
-pub const version: u16 = 4;
+pub const version: u16 = 5;
pub const Error = error{ Truncated, Overlong, BadTag, BadValue, Trailing, NoSpace };
@@ -184,9 +185,12 @@ pub const Frame = struct {
layer.rows = try r.getU16();
layer.context_rows = try r.getU16();
if (layer.pane >= pardes.MAX_PANES or layer.cols == 0 or layer.cols > f.cols or
- layer.rows == 0 or layer.rows > 2 * max_rows or layer.context_rows > layer.rows or
+ layer.rows == 0 or layer.rows > 2 * max_rows or layer.context_rows > layer.rows or layer.context_rows > limits.wrap_rows or
layer.viewport.x > f.cols or layer.viewport.w > f.cols - layer.viewport.x or
layer.viewport.y > f.rows or layer.viewport.h > f.rows - layer.viewport.y) return error.BadValue;
+ for (0..layer.context_rows) |row| {
+ if (try r.getBool()) layer.context_separators.set(row);
+ }
const cursor = try getCursor(&r, layer.cols, layer.rows);
layer.cursor = if (cursor) |c| .{ .x = c.x, .y = c.y, .bar = c.bar } else null;
layer.cells = try gpa.alloc(pardes.Cell, @as(usize, layer.cols) * layer.rows);
@@ -640,7 +644,7 @@ pub fn encodeFramePointer(
pub fn layersBound(layers: []const pardes.BodyLayer) usize {
var n: usize = 2;
for (layers) |layer| if (layer.rows != 0) {
- n += 26 + layer.cells.len * cell_max;
+ n += 26 + layer.context_rows + layer.cells.len * cell_max;
};
return n;
}
@@ -675,6 +679,7 @@ pub fn encodeFrameLayers(out: []u8, cols: u16, rows: u16, cursor: ?Cursor, point
try w.putU16(count);
for (layers) |layer| {
if (layer.rows == 0) continue;
+ if (layer.context_rows > limits.wrap_rows or layer.context_rows > layer.rows) return error.BadValue;
try w.putU16(layer.pane);
try w.putU32(layer.serial);
try w.putU16(layer.viewport.x);
@@ -684,6 +689,7 @@ pub fn encodeFrameLayers(out: []u8, cols: u16, rows: u16, cursor: ?Cursor, point
try w.putU16(layer.cols);
try w.putU16(layer.rows);
try w.putU16(layer.context_rows);
+ for (0..layer.context_rows) |row| try w.putBool(layer.context_separators.isSet(row));
try putCursor(&w, if (layer.cursor) |c| .{ .x = c.x, .y = c.y, .bar = c.bar } else null, layer.cols, layer.rows);
for (layer.cells) |*cell| try putCell(&w, cell);
}
@@ -1727,7 +1733,8 @@ test "detached wire carries compact body rows and exact pointer metrics" {
var cells: [8]pardes.Cell = @splat(.{});
var logical: [12]pardes.Cell = @splat(.{});
logical[10] = .{ .text = "z".* ++ @as([6]u8, @splat(0)), .len = 1, .default = false };
- const layer: pardes.BodyLayer = .{ .pane = 0, .serial = 42, .viewport = .{ .x = 0, .y = 0, .w = 2, .h = 4 }, .cols = 2, .rows = 6, .context_rows = 2, .cells = &logical, .cursor = .{ .x = 0, .y = 5, .bar = true } };
+ var layer: pardes.BodyLayer = .{ .pane = 0, .serial = 42, .viewport = .{ .x = 0, .y = 0, .w = 2, .h = 4 }, .cols = 2, .rows = 6, .context_rows = 2, .cells = &logical, .cursor = .{ .x = 0, .y = 5, .bar = true } };
+ layer.context_separators.set(0);
const out = try gpa.alloc(u8, frameBound(2, 4) + layersBound(&.{layer}));
defer gpa.free(out);
const encoded = try encodeFrameLayers(out, 2, 4, null, .link, &cells, &cells, &.{layer});
@@ -1738,6 +1745,10 @@ test "detached wire carries compact body rows and exact pointer metrics" {
try frame.apply(&cells);
try frame.applyLayers(gpa, &decoded);
try std.testing.expectEqual(@as(u16, 6), decoded[0].rows);
+ try std.testing.expect(decoded[0].context_separators.isSet(0));
+ try std.testing.expect(!decoded[0].context_separators.isSet(1));
+ try std.testing.expect(decoded[0].hasContextBorderAfter(0));
+ try std.testing.expect(decoded[0].hasContextBorderAfter(1));
try std.testing.expectEqualStrings("z", decoded[0].cells[10].grapheme());
try std.testing.expectEqual(@as(u16, 5), decoded[0].cursor.?.y);
const pointer = layer.hitAt(4, 27, 8, 16, 6, 8).?;
@@ -1754,6 +1765,7 @@ test "detached wire carries compact body rows and exact pointer metrics" {
for (decoded) |item| {
try std.testing.expectEqual(@as(u16, 0), item.rows);
try std.testing.expectEqual(@as(usize, 0), item.cells.len);
+ try std.testing.expectEqual(@as(usize, 0), item.context_separators.count());
}
const no_layers = try encodeFramePointer(out, 2, 4, null, .arrow, &cells, &cells);
const cleared_packet = (try framed(no_layers)).?;