lib/choir/src/composition/loaded/fragment.zig
daab053ee43316e1809a84551d573ddd1e5bf3d2
1 const std = @import("std");
2 const composition = @import("../root.zig");
3 const loaded = @import("root.zig");
4
5 const Allocator = std.mem.Allocator;
6 const abi = composition.abi;
7 const model = composition.module;
8 const source = composition.source;
9
10 pub const FragmentVTable = struct {
11 invoke: ?*const fn (*anyopaque, *const model.CallSite, *abi.Context, *abi.Frame) abi.Status = null,
12 lookup_export: ?*const fn (*anyopaque, []const u8) ?usize = null,
13 deinit: *const fn (*anyopaque, Allocator) void,
14 };
15
16 pub const MaterializedFragment = struct {
17 state: *anyopaque,
18 vtable: *const FragmentVTable,
19 };
20
21 pub const FragmentMaterializer = struct {
22 id: source.FragmentId,
23 context: *anyopaque,
24 materialize: *const fn (*anyopaque, Allocator, *const model.CompositionModule, *const model.Fragment) anyerror!MaterializedFragment,
25 };
26
27 pub const LoadedFragment = struct {
28 id: source.FragmentId,
29 state: *anyopaque,
30 vtable: *const FragmentVTable,
31 };
32
33 pub fn deinitUnique(
34 allocator: Allocator,
35 fragments: []const LoadedFragment,
36 observer: ?loaded.LifecycleObserver,
37 ) void {
38 var index = fragments.len;
39 while (index != 0) {
40 index -= 1;
41 const fragment_value = fragments[index];
42 var earlier_index: usize = 0;
43 var aliased = false;
44 while (earlier_index < index) : (earlier_index += 1) {
45 if (fragments[earlier_index].state == fragment_value.state) {
46 aliased = true;
47 break;
48 }
49 }
50 if (aliased) continue;
51 fragment_value.vtable.deinit(fragment_value.state, allocator);
52 if (observer) |value| value.record(.{ .fragment_destroyed = fragment_value.id });
53 }
54 }