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

daab053ee43316e1809a84551d573ddd1e5bf3d2

  1 const admission = @import("../../admission/root.zig");
  2 const fabric = @import("../root.zig");
  3 const os = @import("os");
  4 const schema = @import("schema.zig");
  5 const std = @import("std");
  6 
  7 const State = @FieldType(fabric.Fabric, "state");
  8 const NodeState = @typeInfo(@FieldType(State, "nodes")).array.child;
  9 const QueuedPacket = @typeInfo(@FieldType(State, "packets")).array.child;
 10 const wire = os.abi.wire;
 11 
 12 pub fn snapshot(
 13     value: *const fabric.Fabric,
 14     output: *[schema.stream_bytes]u8,
 15 ) fabric.Error!void {
 16     _ = try value.cut();
 17     std.debug.assert(!value.turnPending());
 18     var encoded: [schema.stream_bytes]u8 = @splat(0);
 19     encodeEnvelope(&encoded);
 20     encodeRoot(value.root(), &encoded);
 21     encodeState(value.state, &encoded);
 22     for (value.state.nodes[0..value.state.node_count], 0..) |node, index| {
 23         encodeNode(node, index, &encoded);
 24     }
 25     for (value.state.packets[0..value.state.packet_count], 0..) |packet, index| {
 26         encodePacket(packet, index, &encoded);
 27     }
 28     output.* = encoded;
 29 }
 30 
 31 fn encodeEnvelope(output: *[schema.stream_bytes]u8) void {
 32     const layout = schema.Envelope;
 33     @memcpy(output[layout.magic_offset..layout.version_offset], &schema.magic);
 34     put16(output, layout.version_offset, schema.version);
 35     put16(output, layout.stream_bytes_offset, schema.stream_bytes);
 36     put16(output, layout.flags_offset, schema.flags);
 37     put16(output, layout.format_offset, schema.format);
 38     put16(output, layout.dialect_offset, @backingInt(fabric.Dialect.ordered_effect_fabric_v3));
 39     put16(output, layout.node_capacity_offset, fabric.node_limit);
 40     put16(output, layout.packet_capacity_offset, fabric.packet_limit);
 41     put16(output, layout.node_bytes_offset, schema.node_bytes);
 42     put16(output, layout.packet_bytes_offset, schema.packet_bytes);
 43     put16(output, layout.packet_payload_bytes_offset, schema.packet_payload_bytes);
 44     put16(output, layout.digest_bytes_offset, schema.digest_bytes);
 45     put16(output, layout.root_bytes_offset, schema.root_bytes);
 46     put16(output, layout.state_header_bytes_offset, schema.state_header_bytes);
 47 }
 48 
 49 fn encodeRoot(value: fabric.Root, output: *[schema.stream_bytes]u8) void {
 50     const layout = schema.RootLayout;
 51     putDigest(output, layout.digest_offset, value.digest);
 52     putDigest(output, layout.contract_offset, value.machine_contract.digest);
 53     put64(output, layout.entry_frontier_offset, value.entry_frontier);
 54     put64(output, layout.admission_frontier_offset, value.admission_frontier);
 55     put64(output, layout.fault_frontier_offset, value.fault_frontier);
 56     put16(output, layout.dialect_offset, @backingInt(value.dialect));
 57 }
 58 
 59 fn encodeState(value: State, output: *[schema.stream_bytes]u8) void {
 60     const layout = schema.StateLayout;
 61     @memcpy(output[layout.world_offset..][0..16], &value.world);
 62     output[layout.node_count_offset] = value.node_count;
 63     output[layout.packet_count_offset] = value.packet_count;
 64     output[layout.partition_bits_offset] = value.partition_bits;
 65     output[layout.capacity_bits_offset] = value.capacity_bits;
 66     put64(output, layout.virtual_time_offset, value.virtual_time_tick);
 67     put64(output, layout.entropy_frontier_offset, value.entropy_frontier);
 68     put64(output, layout.entropy_bytes_offset, value.entropy_bytes);
 69     put64(output, layout.packet_next_id_offset, value.packet_next_id);
 70     put64(output, layout.entry_frontier_offset, value.entry_frontier);
 71     put64(output, layout.admission_frontier_offset, value.admission_frontier);
 72     put64(output, layout.fault_frontier_offset, value.fault_frontier);
 73     put32(output, layout.admission_limit_offset, value.admission_limit);
 74     putDigest(output, layout.ledger_digest_offset, value.ledger_digest);
 75     putDigest(output, layout.fault_digest_offset, value.fault_digest);
 76 }
 77 
 78 fn encodeNode(
 79     value: NodeState,
 80     index: usize,
 81     output: *[schema.stream_bytes]u8,
 82 ) void {
 83     std.debug.assert(index < fabric.node_limit);
 84     const layout = schema.NodeLayout;
 85     const start = schema.nodes_offset + index * schema.node_bytes;
 86     std.debug.assert(start + schema.node_bytes <= schema.packets_offset);
 87     @memcpy(output[start + layout.id_offset ..][0..16], &value.id.bytes);
 88     encodeBasis(value.basis, start, output);
 89     output[start + layout.machine_kind_offset] = @backingInt(value.machine.kind);
 90     output[start + layout.available_offset] = @intFromBool(value.available);
 91     putDigest(output, start + layout.machine_digest_offset, value.machine.digest);
 92 }
 93 
 94 fn encodeBasis(
 95     value: admission.Basis,
 96     start: usize,
 97     output: *[schema.stream_bytes]u8,
 98 ) void {
 99     std.debug.assert(start >= schema.nodes_offset);
100     std.debug.assert(start + schema.node_bytes <= schema.packets_offset);
101     const layout = schema.NodeLayout;
102     putDigest(output, start + layout.contract_offset, value.contract.digest);
103     putDigest(output, start + layout.source_root_offset, value.source_root);
104     put64(output, start + layout.input_frontier_offset, value.frontiers.input);
105     put64(output, start + layout.terminal_input_offset, value.frontiers.terminal_input_offset);
106     put64(output, start + layout.virtual_time_offset, value.frontiers.virtual_time_tick);
107     put64(output, start + layout.entropy_offset, value.frontiers.entropy_generation);
108     put64(output, start + layout.effect_offset, value.frontiers.effect);
109     if (value.outstanding_effect) |request| {
110         output[start + layout.request_present_offset] = 1;
111         putDigest(output, start + layout.request_receipt_offset, request.receipt.digest);
112         put64(output, start + layout.request_correlation_offset, request.correlation);
113     }
114 }
115 
116 fn encodePacket(
117     value: QueuedPacket,
118     index: usize,
119     output: *[schema.stream_bytes]u8,
120 ) void {
121     std.debug.assert(index < fabric.packet_limit);
122     std.debug.assert(value.packet.length > 0);
123     std.debug.assert(value.packet.length <= fabric.packet_bytes_max);
124     const layout = schema.PacketLayout;
125     const start = schema.packets_offset + index * schema.packet_bytes;
126     std.debug.assert(start + schema.packet_bytes <= schema.material_limit);
127     put64(output, start + layout.id_offset, value.packet.id);
128     @memcpy(output[start + layout.source_offset ..][0..16], &value.packet.source.bytes);
129     @memcpy(output[start + layout.destination_offset ..][0..16], &value.packet.destination.bytes);
130     put16(output, start + layout.channel_offset, value.packet.channel);
131     put16(output, start + layout.length_offset, value.packet.length);
132     output[start + layout.ready_offset] = @intFromBool(value.ready);
133     putDigest(
134         output,
135         start + layout.request_receipt_offset,
136         value.packet.request.receipt.digest,
137     );
138     put64(output, start + layout.request_correlation_offset, value.packet.request.correlation);
139     put64(output, start + layout.ready_at_offset, value.ready_at_tick);
140     put64(output, start + layout.order_offset, value.order);
141     putDigest(output, start + layout.digest_offset, value.packet.digest);
142     @memcpy(output[start + layout.storage_offset ..][0..value.packet.length], value.packet.bytes());
143 }
144 
145 fn putDigest(
146     output: *[schema.stream_bytes]u8,
147     offset: usize,
148     value: os.abi.Digest,
149 ) void {
150     std.debug.assert(offset + schema.digest_bytes <= output.len);
151     @memcpy(output[offset..][0..schema.digest_bytes], &value);
152 }
153 
154 fn put16(output: *[schema.stream_bytes]u8, offset: usize, value: anytype) void {
155     std.debug.assert(offset + 2 <= output.len);
156     wire.write16(output[offset..][0..2], @intCast(value));
157 }
158 
159 fn put32(output: *[schema.stream_bytes]u8, offset: usize, value: u32) void {
160     std.debug.assert(offset + 4 <= output.len);
161     wire.write32(output[offset..][0..4], value);
162 }
163 
164 fn put64(output: *[schema.stream_bytes]u8, offset: usize, value: u64) void {
165     std.debug.assert(offset + 8 <= output.len);
166     wire.write64(output[offset..][0..8], value);
167 }