diff options
Diffstat (limited to 'dump.zig')
| -rw-r--r-- | dump.zig | 218 |
1 files changed, 0 insertions, 218 deletions
diff --git a/dump.zig b/dump.zig deleted file mode 100644 index 9c1dceec..00000000 --- a/dump.zig +++ /dev/null @@ -1,218 +0,0 @@ -const std = @import("std"); -const builtin = @import("builtin"); - -pub const default_path = "/tmp/pardes-dump.zon"; -pub const magic = "pardes-dump"; -pub const version: u32 = 1; -pub const max_panes: usize = 16; -pub const max_cols: usize = 6; - -pub const Size = struct { - cols: u16, - rows: u16, -}; - -pub const Cursor = struct { - col: u16 = 0, - row: u16 = 0, -}; - -pub const PaneKind = enum { - terminal, - file, - image, -}; - -pub const Terminal = struct { - cwd: []const u8 = "", - stream: []const u8 = "", - stream_b64: []const u8 = "", - cursor: Cursor = .{}, -}; - -pub const File = struct { - path: []const u8 = "", - content: []const u8 = "", - content_b64: []const u8 = "", -}; - -pub const Image = struct { - path: []const u8 = "", - bytes_b64: []const u8 = "", -}; - -pub const Pane = struct { - kind: PaneKind, - tag: []const u8, - body: []const u8, - scroll: usize = 0, - cols: u16 = 0, - rows: u16 = 0, - vweight: f32 = 1, - terminal: ?Terminal = null, - file: ?File = null, - image: ?Image = null, -}; - -pub const Column = struct { - weight: f32 = 1, - panes: []const usize = &.{}, -}; - -pub const State = struct { - magic: []const u8 = magic, - version: u32 = version, - screen: Size, - active: usize = 0, - topbar: []const u8 = "", - theme: []const u8 = "dark", - columns: []const Column = &.{}, - panes: []const Pane = &.{}, -}; - -pub fn validate(state: State) !void { - if (!std.mem.eql(u8, state.magic, magic)) return error.BadDumpMagic; - if (state.version != version) return error.BadDumpVersion; - if (state.panes.len == 0 or state.panes.len > max_panes) return error.BadDumpPanes; - if (state.columns.len == 0 or state.columns.len > max_cols) return error.BadDumpColumns; - if (state.active >= state.panes.len) return error.BadDumpActive; - for (state.columns) |col| { - if (col.panes.len == 0 or col.panes.len > max_panes) return error.BadDumpColumns; - for (col.panes) |pane| { - if (pane >= state.panes.len) return error.BadDumpPaneRef; - } - } - for (state.panes) |pane| { - switch (pane.kind) { - .terminal => if (pane.terminal == null) return error.BadDumpPaneKind, - .file => if (pane.file == null) return error.BadDumpPaneKind, - .image => if (pane.image == null) return error.BadDumpPaneKind, - } - } -} - -pub fn writeFile(io: std.Io, gpa: std.mem.Allocator, path: []const u8, state: State) !void { - try validate(state); - var out: std.Io.Writer.Allocating = .init(gpa); - defer out.deinit(); - try std.zon.stringify.serialize(state, .{ .whitespace = true }, &out.writer); - - var file = try std.Io.Dir.createFileAbsolute(io, path, .{}); - defer file.close(io); - try file.writeStreamingAll(io, out.written()); -} - -pub fn readFile(io: std.Io, gpa: std.mem.Allocator, path: []const u8) !State { - const bytes = try std.Io.Dir.cwd().readFileAlloc(io, path, gpa, .limited(64 * 1024 * 1024)); - defer gpa.free(bytes); - return readZon(gpa, bytes, path); -} - -pub fn readZon(gpa: std.mem.Allocator, bytes: []const u8, label: []const u8) !State { - const source = try gpa.dupeZ(u8, bytes); - defer gpa.free(source); - return readZonZ(gpa, source, label); -} - -pub fn readZonZ(gpa: std.mem.Allocator, source: [:0]const u8, label: []const u8) !State { - if (builtin.os.tag == .emscripten) { - const state = std.zon.parse.fromSliceAlloc(State, gpa, source, null, .{}) catch |err| { - std.log.err("parse dump {s}: {s}", .{ label, @errorName(err) }); - return err; - }; - errdefer std.zon.parse.free(gpa, state); - try validate(state); - return state; - } - - var diag: std.zon.parse.Diagnostics = .{}; - defer diag.deinit(gpa); - const state = std.zon.parse.fromSliceAlloc(State, gpa, source, &diag, .{}) catch |err| { - std.log.err("parse dump {s}: {f}", .{ label, diag }); - return err; - }; - errdefer std.zon.parse.free(gpa, state); - try validate(state); - return state; -} - -pub fn free(gpa: std.mem.Allocator, state: State) void { - std.zon.parse.free(gpa, state); -} - -pub fn encodeBytes(alloc: std.mem.Allocator, bytes: []const u8) ![]const u8 { - const enc = std.base64.standard.Encoder; - const out = try alloc.alloc(u8, enc.calcSize(bytes.len)); - return enc.encode(out, bytes); -} - -pub fn decodeBytes(alloc: std.mem.Allocator, b64: []const u8) ![]u8 { - const dec = std.base64.standard.Decoder; - const n = try dec.calcSizeForSlice(b64); - const out = try alloc.alloc(u8, n); - errdefer alloc.free(out); - try dec.decode(out, b64); - return out; -} - -test "dump zon roundtrip" { - const gpa = std.testing.allocator; - const tty_b64 = try encodeBytes(gpa, "old\nhello\nworld"); - defer gpa.free(tty_b64); - const file_b64 = try encodeBytes(gpa, "alpha\nbeta\n"); - defer gpa.free(file_b64); - const panes = [_]Pane{ - .{ - .kind = .terminal, - .tag = "nm /tmp Del", - .body = "hello\nworld", - .scroll = 1, - .cols = 40, - .rows = 10, - .terminal = .{ .cwd = "/tmp", .stream = "old\nhello\nworld", .stream_b64 = tty_b64, .cursor = .{ .col = 3, .row = 2 } }, - }, - .{ - .kind = .file, - .tag = "nm /tmp/a.txt Save Del", - .body = " 1 alpha", - .cols = 20, - .rows = 5, - .file = .{ .path = "/tmp/a.txt", .content = "alpha\nbeta\n", .content_b64 = file_b64 }, - }, - }; - const col_panes = [_]usize{ 0, 1 }; - const columns = [_]Column{.{ .weight = 1, .panes = &col_panes }}; - const state: State = .{ - .screen = .{ .cols = 80, .rows = 24 }, - .topbar = "Kill Newcol Dump", - .theme = "dark", - .columns = &columns, - .panes = &panes, - }; - - var out: std.Io.Writer.Allocating = .init(gpa); - defer out.deinit(); - try std.zon.stringify.serialize(state, .{ .whitespace = true }, &out.writer); - const source = try out.toOwnedSliceSentinel(0); - defer gpa.free(source); - - var diag: std.zon.parse.Diagnostics = .{}; - defer diag.deinit(gpa); - const parsed = try std.zon.parse.fromSliceAlloc(State, gpa, source, &diag, .{}); - defer std.zon.parse.free(gpa, parsed); - try validate(parsed); - try std.testing.expectEqual(@as(usize, 2), parsed.panes.len); - try std.testing.expectEqualStrings("dark", parsed.theme); - try std.testing.expectEqualStrings("old\nhello\nworld", parsed.panes[0].terminal.?.stream); - try std.testing.expectEqualStrings("alpha\nbeta\n", parsed.panes[1].file.?.content); - { - const bytes = try decodeBytes(gpa, parsed.panes[0].terminal.?.stream_b64); - defer gpa.free(bytes); - try std.testing.expectEqualStrings("old\nhello\nworld", bytes); - } - { - const bytes = try decodeBytes(gpa, parsed.panes[1].file.?.content_b64); - defer gpa.free(bytes); - try std.testing.expectEqualStrings("alpha\nbeta\n", bytes); - } -} |
