lib/choir/src/composition/module/serialization/source.zig

daab053ee43316e1809a84551d573ddd1e5bf3d2

  1 const std = @import("std");
  2 const composition = @import("../../root.zig");
  3 const serialization = @import("root.zig");
  4 
  5 const source = composition.source;
  6 const Reader = serialization.format.Reader;
  7 const Writer = serialization.format.Writer;
  8 
  9 pub fn write(writer: *Writer, module: *const source.PartitionedModule) serialization.SerializeError!void {
 10     try writer.writeString(module.name);
 11     try writer.writeCount(module.boundaries.items.len);
 12     for (module.boundaries.items) |boundary_value| try writeBoundary(writer, boundary_value);
 13     try writer.writeCount(module.partitions.items.len);
 14     for (module.partitions.items) |partition_value| try writePartition(writer, partition_value);
 15     try writer.writeCount(module.call_sites.items.len);
 16     for (module.call_sites.items) |call_site| try writeCall(writer, call_site);
 17 }
 18 
 19 pub fn read(allocator: std.mem.Allocator, reader: *Reader) serialization.DeserializeError!source.PartitionedModule {
 20     var module = try source.PartitionedModule.init(allocator, try reader.readString());
 21     errdefer module.deinit();
 22 
 23     const boundary_count = try reader.readCount();
 24     for (0..boundary_count) |_| try readBoundary(allocator, reader, &module);
 25     const partition_count = try reader.readCount();
 26     for (0..partition_count) |_| try readPartition(allocator, reader, &module);
 27     const call_count = try reader.readCount();
 28     for (0..call_count) |_| try readCall(allocator, reader, &module);
 29     return module;
 30 }
 31 
 32 fn writeBoundary(writer: *Writer, value: source.Boundary) serialization.SerializeError!void {
 33     try writer.writeInt(u64, value.id.value);
 34     try writer.writeString(value.name);
 35     try writer.writeTag(value.element_type);
 36     try writeDimensions(writer, value.dimensions);
 37     try writer.writeInt(u64, value.byte_size);
 38     try writer.writeTag(value.access);
 39     try writer.writeTag(value.ownership);
 40     try writeAlias(writer, value.alias);
 41     try serialization.provenance.write(writer, value.provenance);
 42 }
 43 
 44 fn readBoundary(
 45     allocator: std.mem.Allocator,
 46     reader: *Reader,
 47     module: *source.PartitionedModule,
 48 ) serialization.DeserializeError!void {
 49     const id = source.BoundaryId{ .value = try reader.readInt(u64) };
 50     const name = try reader.readString();
 51     const element_type = try reader.readTag(source.ElementType);
 52     const dimensions = try readDimensions(allocator, reader);
 53     defer allocator.free(dimensions);
 54     const byte_size = try reader.readInt(u64);
 55     const access = try reader.readTag(source.Access);
 56     const ownership = try reader.readTag(source.Ownership);
 57     const alias = try readAlias(reader);
 58     const provenance = try serialization.provenance.read(reader);
 59     try module.addBoundary(.{
 60         .id = id,
 61         .name = name,
 62         .element_type = element_type,
 63         .dimensions = dimensions,
 64         .byte_size = byte_size,
 65         .access = access,
 66         .ownership = ownership,
 67         .alias = alias,
 68         .provenance = provenance,
 69     });
 70 }
 71 
 72 fn writeAlias(writer: *Writer, alias: source.Alias) serialization.SerializeError!void {
 73     const Tag = std.meta.Tag(source.Alias);
 74     try writer.writeTag(@as(Tag, alias));
 75     switch (alias) {
 76         .disjoint => {},
 77         .boundary => |id| try writer.writeInt(u64, id.value),
 78     }
 79 }
 80 
 81 fn readAlias(reader: *Reader) serialization.DeserializeError!source.Alias {
 82     const Tag = std.meta.Tag(source.Alias);
 83     return switch (try reader.readTag(Tag)) {
 84         .disjoint => .disjoint,
 85         .boundary => .{ .boundary = .{ .value = try reader.readInt(u64) } },
 86     };
 87 }
 88 
 89 fn writePartition(writer: *Writer, value: source.Partition) serialization.SerializeError!void {
 90     try writer.writeInt(u64, value.id.value);
 91     try writer.writeString(value.name);
 92     try writer.writeTag(value.pipeline);
 93     try writeBoundaryIds(writer, value.inputs);
 94     try writeBoundaryIds(writer, value.outputs);
 95     try serialization.reference.writeAddress(writer, value.product);
 96     try writer.writeTag(value.effect);
 97     try serialization.provenance.write(writer, value.provenance);
 98 }
 99 
100 fn readPartition(
101     allocator: std.mem.Allocator,
102     reader: *Reader,
103     module: *source.PartitionedModule,
104 ) serialization.DeserializeError!void {
105     const id = source.PartitionId{ .value = try reader.readInt(u64) };
106     const name = try reader.readString();
107     const pipeline = try reader.readTag(source.Pipeline);
108     const inputs = try readBoundaryIds(allocator, reader);
109     defer allocator.free(inputs);
110     const outputs = try readBoundaryIds(allocator, reader);
111     defer allocator.free(outputs);
112     const address = try serialization.reference.readAddress(reader);
113     const effect = try reader.readTag(source.Effect);
114     const provenance = try serialization.provenance.read(reader);
115     try module.addPartition(.{
116         .id = id,
117         .name = name,
118         .pipeline = pipeline,
119         .inputs = inputs,
120         .outputs = outputs,
121         .product = address,
122         .effect = effect,
123         .provenance = provenance,
124     });
125 }
126 
127 fn writeCall(writer: *Writer, value: source.SemanticCallSite) serialization.SerializeError!void {
128     try writer.writeInt(u64, value.id.value);
129     try writer.writeString(value.name);
130     try writer.writeInt(u64, value.caller.value);
131     try writer.writeInt(u64, value.callee.value);
132     try writeBoundaryIds(writer, value.inputs);
133     try writeBoundaryIds(writer, value.outputs);
134     try serialization.provenance.write(writer, value.provenance);
135 }
136 
137 fn readCall(
138     allocator: std.mem.Allocator,
139     reader: *Reader,
140     module: *source.PartitionedModule,
141 ) serialization.DeserializeError!void {
142     const id = source.CallSiteId{ .value = try reader.readInt(u64) };
143     const name = try reader.readString();
144     const caller = source.PartitionId{ .value = try reader.readInt(u64) };
145     const callee = source.PartitionId{ .value = try reader.readInt(u64) };
146     const inputs = try readBoundaryIds(allocator, reader);
147     defer allocator.free(inputs);
148     const outputs = try readBoundaryIds(allocator, reader);
149     defer allocator.free(outputs);
150     const provenance = try serialization.provenance.read(reader);
151     try module.addCallSite(.{
152         .id = id,
153         .name = name,
154         .caller = caller,
155         .callee = callee,
156         .inputs = inputs,
157         .outputs = outputs,
158         .provenance = provenance,
159     });
160 }
161 
162 pub fn writeBoundaryIds(writer: *Writer, ids: []const source.BoundaryId) serialization.SerializeError!void {
163     try writer.writeCount(ids.len);
164     for (ids) |id| try writer.writeInt(u64, id.value);
165 }
166 
167 pub fn readBoundaryIds(allocator: std.mem.Allocator, reader: *Reader) serialization.DeserializeError![]source.BoundaryId {
168     const count = try reader.readCount();
169     const ids = try allocator.alloc(source.BoundaryId, count);
170     errdefer allocator.free(ids);
171     for (ids) |*id| id.* = .{ .value = try reader.readInt(u64) };
172     return ids;
173 }
174 
175 fn writeDimensions(writer: *Writer, dimensions: []const u64) serialization.SerializeError!void {
176     try writer.writeCount(dimensions.len);
177     for (dimensions) |dimension| try writer.writeInt(u64, dimension);
178 }
179 
180 fn readDimensions(allocator: std.mem.Allocator, reader: *Reader) serialization.DeserializeError![]u64 {
181     const count = try reader.readCount();
182     const dimensions = try allocator.alloc(u64, count);
183     errdefer allocator.free(dimensions);
184     for (dimensions) |*dimension| dimension.* = try reader.readInt(u64);
185     return dimensions;
186 }