1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
|
const std = @import("std");
const Allocator = std.mem.Allocator;
const ArenaAllocator = std.heap.ArenaAllocator;
const Config = @This();
pub const Wrapper = struct {
arena: ArenaAllocator,
config: Config,
pub fn deinit(self: Wrapper) void {
self.arena.deinit();
}
pub fn merge(self: *Wrapper, filename: []const u8) !void {
const file = try std.fs.cwd().openFile(filename, .{});
defer file.close();
const allocator = self.arena.allocator();
var reader = std.json.reader(allocator, file.reader());
defer reader.deinit();
const new_config = try std.json.parseFromTokenSourceLeaky(
Nullable,
allocator,
&reader,
.{
.duplicate_field_behavior = .use_last,
.ignore_unknown_fields = true,
.allocate = .alloc_always,
},
);
inline for (std.meta.fields(Config)) |field| {
if (@field(new_config, field.name)) |value| {
@field(self.config, field.name) = value;
}
}
}
};
bot_name: []const u8,
bot_token: []const u8,
db_path: [:0]const u8,
dev_group: i64,
owner: i64,
pub fn load(parent_allocator: Allocator, filename: []const u8) !Wrapper {
const file = try std.fs.cwd().openFile(filename, .{});
defer file.close();
var arena = ArenaAllocator.init(parent_allocator);
errdefer arena.deinit();
const allocator = arena.allocator();
var reader = std.json.reader(allocator, file.reader());
defer reader.deinit();
const config = try std.json.parseFromTokenSourceLeaky(
Config,
allocator,
&reader,
.{
.duplicate_field_behavior = .use_last,
.ignore_unknown_fields = true,
.allocate = .alloc_always,
},
);
return .{ .arena = arena, .config = config };
}
const Nullable = blk: {
const template = @typeInfo(Config);
var fields: [template.@"struct".fields.len]std.builtin.Type.StructField = undefined;
for (template.@"struct".fields, 0..) |template_field, field_idx| {
fields[field_idx] = template_field;
fields[field_idx].type = ?template_field.type;
}
var new = template;
new.@"struct".fields = &fields;
new.@"struct".decls = &.{};
break :blk @Type(new);
};
|