zuletzt/src/apply_rule.zig
mitteneer a2a739bc9c Refactor upload.zig
I have been unhappy with the branches, but didn't quite know what to do about it. THis feels much nicer. Also fixes datetime stuff with jetquery.  The HTML element parsing isn't quite where I want it to be, but it works for the time being.
2025-05-20 15:07:51 -04:00

71 lines
3.1 KiB
Zig

const std = @import("std");
const Rule = @import("./types.zig").Rule;
const Data = @import("./types.zig");
// Wrapper for containsAtLeast to make the switch below to work
fn containsWrapper(haystack: []const u8, needle: []const u8) bool {
return std.mem.containsAtLeast(u8, haystack, 1, needle);
}
fn eqlWrapper(haystack: []const u8, needle: []const u8) bool {
return std.mem.eql(u8, haystack, needle);
}
pub fn applyScrobbleRule(allocator: std.mem.Allocator, scrobble: Data.Scrobble, rules: []Rule) !Data.Scrobble {
var output_scrobble = scrobble;
for (rules) |rule| {
var match_found: bool = switch (rule.cond_req) {
.any => false,
.all => true,
};
for (rule.conditionals) |cond| {
const match_fn: *const fn ([]const u8, []const u8) bool = switch (cond.match_cond) {
.is => eqlWrapper,
.contains => containsWrapper,
};
switch (rule.cond_req) {
.any => switch (cond.match_on) {
inline .album, .track => |on| match_found = match_found or match_fn(@field(scrobble, @tagName(on)), cond.match_txt),
inline .artists_album, .artists_track => |on| {
for (@field(scrobble, @tagName(on))) |artist| match_found = match_found or match_fn(artist, cond.match_txt);
},
},
.all => switch (cond.match_on) {
inline .album, .track => |on| match_found = match_found and match_fn(@field(scrobble, @tagName(on)), cond.match_txt),
inline .artists_album, .artists_track => |on| {
for (@field(scrobble, @tagName(on))) |artist| match_found = match_found and match_fn(artist, cond.match_txt);
},
},
}
}
if (match_found) {
for (rule.actions) |act| {
switch (act.action) {
.add => {
var al = std.ArrayList([]const u8).init(allocator);
switch (act.action_on) {
.album, .track => unreachable,
inline else => |on| {
try al.appendSlice(@field(output_scrobble, @tagName(on)));
try al.append(act.action_txt);
const list = try al.toOwnedSlice();
@field(output_scrobble, @tagName(on)) = list;
},
}
},
.replace => switch (act.action_on) {
inline .album, .track => |on| @field(output_scrobble, @tagName(on)) = act.action_txt,
inline .artists_album, .artists_track => |on| {
const artist = try allocator.alloc([]const u8, 1);
artist[0] = act.action_txt;
@field(output_scrobble, @tagName(on)) = artist;
},
},
}
}
}
}
return output_scrobble;
}