feat: restore buffer manager state on restart

This commit is contained in:
CJ van den Berg 2025-08-05 20:08:29 +02:00
parent 1babf86ce4
commit 991c47f3b3
Signed by: neurocyte
GPG key ID: 8EB1E1BB660E3FB9
6 changed files with 121 additions and 14 deletions

View file

@ -1,5 +1,7 @@
const std = @import("std");
const builtin = @import("builtin");
const cbor = @import("cbor");
const file_type_config = @import("file_type_config");
const Allocator = std.mem.Allocator;
const ArrayList = std.ArrayList;
const cwd = std.fs.cwd;
@ -1487,3 +1489,58 @@ pub fn redo(self: *Self) error{Stop}![]const u8 {
self.mtime = std.time.milliTimestamp();
return h.meta;
}
pub fn write_state(self: *const Self, writer: MetaWriter) error{ Stop, OutOfMemory }!void {
var content = std.ArrayListUnmanaged(u8).empty;
defer content.deinit(self.external_allocator);
try self.root.store(content.writer(self.external_allocator), self.file_eol_mode);
try cbor.writeArrayHeader(writer, 8);
try cbor.writeValue(writer, self.get_file_path());
try cbor.writeValue(writer, self.file_exists);
try cbor.writeValue(writer, self.file_eol_mode);
try cbor.writeValue(writer, self.hidden);
try cbor.writeValue(writer, self.ephemeral);
try cbor.writeValue(writer, self.meta orelse &.{});
try cbor.writeValue(writer, self.file_type_name);
try cbor.writeValue(writer, content.items);
}
pub const ExtractStateOperation = enum { none, open_file };
pub fn extract_state(self: *Self, iter: *[]const u8) !void {
var file_path: []const u8 = undefined;
var file_type_name: []const u8 = undefined;
var meta: []const u8 = &.{};
var content: []const u8 = undefined;
if (!try cbor.matchValue(iter, .{
cbor.extract(&file_path),
cbor.extract(&self.file_exists),
cbor.extract(&self.file_eol_mode),
cbor.extract(&self.hidden),
cbor.extract(&self.ephemeral),
cbor.extract(&meta),
cbor.extract(&file_type_name),
cbor.extract(&content),
}))
return error.Stop;
self.set_file_path(file_path);
if (try file_type_config.get(try self.allocator.dupe(u8, file_type_name))) |config| {
self.file_type_name = config.name;
self.file_type_icon = config.icon;
self.file_type_color = config.color;
} else {
self.file_type_name = file_type_config.default.name;
self.file_type_icon = file_type_config.default.icon;
self.file_type_color = file_type_config.default.color;
}
if (meta.len > 0) {
if (self.meta) |buf| self.external_allocator.free(buf);
self.meta = if (self.meta) |buf| try self.external_allocator.dupe(u8, buf) else null;
}
try self.reset_from_string_and_update(content);
}

View file

@ -1,4 +1,5 @@
const std = @import("std");
const cbor = @import("cbor");
const tp = @import("thespian");
const Buffer = @import("Buffer.zig");
@ -51,6 +52,34 @@ pub fn open_scratch(self: *Self, file_path: []const u8, content: []const u8) Buf
return buffer;
}
pub fn write_state(self: *const Self, writer: Buffer.MetaWriter) error{ Stop, OutOfMemory }!void {
const buffers = self.list_unordered(self.allocator) catch return;
defer self.allocator.free(buffers);
try cbor.writeArrayHeader(writer, buffers.len);
for (buffers) |buffer| {
tp.trace(tp.channel.debug, .{ @typeName(Self), "write_state", buffer.get_file_path(), buffer.file_type_name });
buffer.write_state(writer) catch |e| {
tp.trace(tp.channel.debug, .{ @typeName(Self), "write_state", "failed", e });
return;
};
}
}
pub fn extract_state(self: *Self, iter: *[]const u8) !void {
var len = try cbor.decodeArrayHeader(iter);
tp.trace(tp.channel.debug, .{ @typeName(Self), "extract_state", len });
while (len > 0) : (len -= 1) {
var buffer = try Buffer.create(self.allocator);
errdefer |e| {
tp.trace(tp.channel.debug, .{ "buffer", "extract", "failed", buffer.get_file_path(), e });
buffer.deinit();
}
try buffer.extract_state(iter);
try self.buffers.put(self.allocator, try self.allocator.dupe(u8, buffer.get_file_path()), buffer);
tp.trace(tp.channel.debug, .{ "buffer", "extract", buffer.get_file_path(), buffer.file_type_name });
}
}
pub fn get_buffer_for_file(self: *Self, file_path: []const u8) ?*Buffer {
return self.buffers.get(file_path);
}
@ -89,7 +118,7 @@ pub fn list_most_recently_used(self: *Self, allocator: std.mem.Allocator) error{
return result;
}
pub fn list_unordered(self: *Self, allocator: std.mem.Allocator) error{OutOfMemory}![]*Buffer {
pub fn list_unordered(self: *const Self, allocator: std.mem.Allocator) error{OutOfMemory}![]*Buffer {
var buffers = try std.ArrayListUnmanaged(*Buffer).initCapacity(allocator, self.buffers.size);
var i = self.buffers.iterator();
while (i.next()) |kv|