Skip to content

Commit faceb71

Browse files
committed
iterate over struct fields instead of parameters slice when saving state
1 parent 2d1c9dd commit faceb71

File tree

4 files changed

+64
-43
lines changed

4 files changed

+64
-43
lines changed

src/clap/extensions/parameters.zig

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,7 @@ const clap = @import("clap");
55

66
const std = @import("std");
77

8-
pub fn makeParameters(comptime Plugin: type) *const c.clap_plugin_params_t {
9-
std.debug.assert(@hasDecl(Plugin, "Parameters"));
10-
const UserParameters = Plugin.Parameters;
11-
8+
pub fn makeParameters(comptime UserParameters: type) *const c.clap_plugin_params_t {
129
comptime for (std.meta.fields(UserParameters)) |field| {
1310
const name = switch (field.defaultValue().?) {
1411
inline else => |p| p.options.name,

src/clap/extensions/state.zig

Lines changed: 22 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -3,28 +3,32 @@ const clap = @import("clap");
33

44
const std = @import("std");
55

6-
pub fn save(clap_plugin: [*c]const c.clap_plugin, stream: [*c]const c.clap_ostream) callconv(.c) bool {
7-
var writer = Writer.init(stream);
8-
const plugin_state = clap.State.fromClap(clap_plugin);
9-
plugin_state.plugin.parameters.?.serialize(&writer.writer) catch |e|
10-
plugin_state.plugin.log.err("failed to save parameters: {}", .{e});
6+
pub fn makeState(comptime UserParameters: type) *const c.clap_plugin_state {
7+
const state = struct {
8+
pub fn save(clap_plugin: [*c]const c.clap_plugin, stream: [*c]const c.clap_ostream) callconv(.c) bool {
9+
var writer = Writer.init(stream);
10+
const plugin_state = clap.State.fromClap(clap_plugin);
11+
plugin_state.plugin.parameters.?.serialize(&writer.writer, UserParameters) catch |e|
12+
plugin_state.plugin.log.err("failed to save parameters: {}", .{e});
1113

12-
return true;
13-
}
14+
return true;
15+
}
1416

15-
pub fn load(clap_plugin: [*c]const c.clap_plugin, stream: [*c]const c.clap_istream) callconv(.c) bool {
16-
var reader = Reader.init(stream);
17-
const plugin_state = clap.State.fromClap(clap_plugin);
18-
plugin_state.plugin.parameters.?.deserialize(&reader.reader) catch |e|
19-
plugin_state.plugin.log.err("failed to read parameters: {}", .{e});
17+
pub fn load(clap_plugin: [*c]const c.clap_plugin, stream: [*c]const c.clap_istream) callconv(.c) bool {
18+
var reader = Reader.init(stream);
19+
const plugin_state = clap.State.fromClap(clap_plugin);
20+
plugin_state.plugin.parameters.?.deserialize(&reader.reader, UserParameters) catch |e|
21+
plugin_state.plugin.log.err("failed to read parameters: {}", .{e});
2022

21-
return true;
22-
}
23+
return true;
24+
}
25+
};
2326

24-
pub const state = c.clap_plugin_state{
25-
.save = save,
26-
.load = load,
27-
};
27+
return &.{
28+
.save = state.save,
29+
.load = state.load,
30+
};
31+
}
2832

2933
pub const Writer = struct {
3034
clap_stream: *const c.clap_ostream,

src/clap/root.zig

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -312,11 +312,13 @@ fn ClapPlugin(comptime Plugin: type, meta: Meta) type {
312312
}
313313

314314
if (@hasDecl(Plugin, "Parameters")) {
315+
const UserParameters = Plugin.Parameters;
316+
315317
if (std.mem.eql(u8, id_slice, &c.CLAP_EXT_PARAMS))
316-
return @import("extensions/parameters.zig").makeParameters(Plugin);
318+
return @import("extensions/parameters.zig").makeParameters(UserParameters);
317319

318320
if (std.mem.eql(u8, id_slice, &c.CLAP_EXT_STATE))
319-
return &@import("extensions/state.zig").state;
321+
return @import("extensions/state.zig").makeState(UserParameters);
320322
}
321323

322324
state.plugin.log.warn("host requested unsupported extension '{s}'", .{id});
@@ -551,5 +553,6 @@ pub inline fn exportClap(comptime Plugin: type, meta: Meta) void {
551553
}
552554

553555
comptime {
554-
std.testing.refAllDecls(@This());
556+
@setEvalBranchQuota(2000);
557+
std.testing.refAllDeclsRecursive(@This());
555558
}

src/core/parameters.zig

Lines changed: 35 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -9,21 +9,22 @@ pub const State = struct {
99
slice: []*Parameter,
1010
allocator: std.mem.Allocator,
1111

12-
pub fn serialize(self: *const State, writer: *std.Io.Writer) !void {
12+
pub fn serialize(self: *const State, writer: *std.Io.Writer, comptime UserParameters: type) !void {
1313
var aw = std.Io.Writer.Allocating.init(self.allocator);
1414
defer aw.deinit();
1515

1616
var w = bufzilla.Writer.init(&aw.writer);
1717

1818
try w.startObject();
1919

20-
for (self.slice) |parameter|
21-
switch (parameter.*) {
22-
inline else => |*p| {
23-
const id = p.options.id.?;
24-
const value = p.get();
20+
const parameters: *UserParameters = @ptrCast(@alignCast(self.context));
21+
inline for (std.meta.fields(UserParameters)) |field|
22+
switch (@field(parameters, field.name)) {
23+
inline else => |*parameter| {
24+
const id = parameter.options.id.?;
25+
const value = parameter.get();
2526

26-
try w.writeAny(id);
27+
try w.writeAny(parameter.options.id.?);
2728
try w.writeAnyExplicit(@TypeOf(value), value);
2829

2930
self.log.debug("saved parameter '{s}' = {any}", .{ id, value });
@@ -38,7 +39,7 @@ pub const State = struct {
3839
try writer.flush();
3940
}
4041

41-
pub fn deserialize(self: *State, reader: *std.Io.Reader) !void {
42+
pub fn deserialize(self: *State, reader: *std.Io.Reader, comptime UserParameters: type) !void {
4243
var aw = std.Io.Writer.Allocating.init(self.allocator);
4344
defer aw.deinit();
4445

@@ -49,23 +50,39 @@ pub const State = struct {
4950

5051
var r = bufzilla.Reader(.{}).init(bytes);
5152

52-
for (self.slice) |parameter|
53-
switch (parameter.*) {
54-
inline else => |*p| {
55-
const id = p.options.id.?;
56-
const decoded_value = try r.readPath(id);
57-
if (decoded_value) |value| {
53+
const parameters: *UserParameters = @ptrCast(@alignCast(self.context));
54+
const fields = std.meta.fields(UserParameters);
55+
56+
var queries: [fields.len]bufzilla.PathQuery = undefined;
57+
58+
inline for (fields, 0..) |field, i|
59+
queries[i] = .{
60+
.path = switch (@field(parameters, field.name)) {
61+
inline else => |p| p.options.id.?,
62+
},
63+
};
64+
65+
try r.readPaths(&queries);
66+
67+
inline for (fields, 0..) |field, i|
68+
switch (@field(parameters, field.name)) {
69+
inline else => |*parameter| {
70+
const id = parameter.options.id.?;
71+
const param_type = @TypeOf(parameter.*).param_type;
72+
73+
if (queries[i].value) |value|
5874
switch (value) {
59-
@TypeOf(p.*).param_type.bufzillaValueTag() => |v| {
60-
p.set(v);
75+
param_type.bufzillaValueTag() => |v| {
76+
parameter.set(v);
6177
self.log.debug("read parameter '{s}' = {any}", .{ id, v });
6278
},
6379
else => self.log.warn(
6480
"wrong type for parameter '{s}': expected {s}, got {s}",
65-
.{ id, @tagName(@TypeOf(p.*).param_type), @tagName(value) },
81+
.{ id, @tagName(param_type), @tagName(value) },
6682
),
6783
}
68-
} else self.log.warn("did not find parameter '{s}'", .{id});
84+
else
85+
self.log.warn("did not find parameter '{s}'", .{id});
6986
},
7087
};
7188
}

0 commit comments

Comments
 (0)