lib/machine/src/fabric/snapshot/codec.zig

daab053ee43316e1809a84551d573ddd1e5bf3d2

 1 const decode = @import("decode.zig");
 2 const encode = @import("encode.zig");
 3 const fabric = @import("../root.zig");
 4 const schema = @import("schema.zig");
 5 const snapshot_types = @import("types.zig");
 6 const std = @import("std");
 7 
 8 pub const Error = snapshot_types.Error;
 9 pub const stream_bytes = schema.stream_bytes;
10 
11 pub fn encodeDisjoint(
12     value: *const fabric.Fabric,
13     writer: *std.Io.Writer,
14 ) Error!void {
15     try validateSink(value, writer);
16     var bytes: [stream_bytes]u8 = undefined;
17     try encode.snapshot(value, &bytes);
18     try writer.writeAll(&bytes);
19 }
20 
21 pub fn decodeDisjoint(
22     reader: *std.Io.Reader,
23     expected_root: fabric.Root,
24 ) Error!fabric.Fabric {
25     var bytes: [stream_bytes]u8 = undefined;
26     try readExact(reader, &bytes);
27     var trailing: [1]u8 = undefined;
28     if (try reader.readSliceShort(&trailing) != 0) return error.TrailingData;
29     return decode.snapshot(&bytes, expected_root);
30 }
31 
32 fn readExact(reader: *std.Io.Reader, output: []u8) Error!void {
33     std.debug.assert(output.len == stream_bytes);
34     reader.readSliceAll(output) catch |failure| switch (failure) {
35         error.EndOfStream => return error.TruncatedStream,
36         error.ReadFailed => return error.ReadFailed,
37     };
38 }
39 
40 fn validateSink(
41     value: *const fabric.Fabric,
42     writer: *std.Io.Writer,
43 ) Error!void {
44     const source = std.mem.asBytes(value);
45     if (buffersOverlap(std.mem.asBytes(writer), source) or
46         buffersOverlap(writer.buffer, source))
47     {
48         return error.SinkAliasesFabric;
49     }
50 }
51 
52 fn buffersOverlap(left: []const u8, right: []const u8) bool {
53     if (left.len == 0 or right.len == 0) return false;
54     const left_start = @intFromPtr(left.ptr);
55     const right_start = @intFromPtr(right.ptr);
56     const left_end = std.math.add(usize, left_start, left.len) catch return true;
57     const right_end = std.math.add(usize, right_start, right.len) catch return true;
58     return left_start < right_end and right_start < left_end;
59 }