diff options
Diffstat (limited to 'src/locations_config.zig')
| -rw-r--r-- | src/locations_config.zig | 75 |
1 files changed, 0 insertions, 75 deletions
diff --git a/src/locations_config.zig b/src/locations_config.zig deleted file mode 100644 index 6b23575a..00000000 --- a/src/locations_config.zig +++ /dev/null @@ -1,75 +0,0 @@ -const std = @import("std"); - -pub const Config = struct { - pub const Layout = enum { @"inline", stacked }; - context: u16 = 0, - tscontext: bool = false, - tslocations: bool = true, - layout: Layout = .stacked, - - /// Apply only supplied fields. A malformed token rejects the whole update. - /// Repeating a field uses its last supplied value. - pub fn parse(current: Config, text: []const u8) !Config { - var result = current; - var tokens = std.mem.tokenizeAny(u8, text, " \t\r\n"); - while (tokens.next()) |token| { - const colon = std.mem.indexOfScalar(u8, token, ':') orelse return error.ExpectedKeyValue; - const key = token[0..colon]; - const value = token[colon + 1 ..]; - var found = false; - inline for (@typeInfo(Config).@"struct".fields) |field| { - if (std.mem.eql(u8, key, field.name)) { - @field(result, field.name) = switch (@typeInfo(field.type)) { - .bool => if (std.mem.eql(u8, value, "on")) true else if (std.mem.eql(u8, value, "off")) false else return error.ExpectedOnOrOff, - .int => std.fmt.parseInt(field.type, value, 10) catch return error.InvalidContext, - .@"enum" => std.meta.stringToEnum(field.type, value) orelse return error.InvalidLayout, - else => @compileError("unsupported location setting type"), - }; - found = true; - } - } - if (!found) return error.UnknownLocationSetting; - } - return result; - } - - pub fn write(config: Config, writer: *std.Io.Writer) !void { - inline for (@typeInfo(Config).@"struct".fields, 0..) |field, index| { - if (index > 0) try writer.writeByte(' '); - try writer.writeAll(field.name ++ ":"); - const value = @field(config, field.name); - switch (@typeInfo(field.type)) { - .bool => try writer.writeAll(if (value) "on" else "off"), - .int => try writer.print("{d}", .{value}), - .@"enum" => try writer.writeAll(@tagName(value)), - else => @compileError("unsupported location setting type"), - } - } - } -}; - -test "LocationsConfig reflection round trip and partial updates" { - var config: Config = .{}; - config = try config.parse("context:5 tscontext:on"); - config = try config.parse("tslocations:off"); - try std.testing.expectEqual(Config{ .context = 5, .tscontext = true, .tslocations = false }, config); - var out: std.Io.Writer.Allocating = .init(std.testing.allocator); - defer out.deinit(); - try config.write(&out.writer); - try std.testing.expectEqualStrings("context:5 tscontext:on tslocations:off layout:stacked", out.written()); - try std.testing.expectEqual(config, try (Config{}).parse(out.written())); - try std.testing.expectEqual(config, try config.parse(" \n\t")); - try std.testing.expectEqual(@as(u16, 2), (try config.parse("context:1 context:2")).context); - try std.testing.expectEqual(Config.Layout.@"inline", (try config.parse("layout:inline")).layout); -} - -test "LocationsConfig rejects invalid updates atomically" { - const config: Config = .{ .context = 3, .tscontext = true }; - try std.testing.expectError(error.UnknownLocationSetting, config.parse("context:5 unknown:on")); - try std.testing.expectError(error.ExpectedOnOrOff, config.parse("context:5 tscontext:true")); - try std.testing.expectError(error.ExpectedKeyValue, config.parse("context")); - try std.testing.expectError(error.InvalidLayout, config.parse("context:5 layout:sideways")); - for ([_][]const u8{ "context:", "context:-1", "context:65536", "context:five" }) |input| - try std.testing.expectError(error.InvalidContext, config.parse(input)); - try std.testing.expectEqual(@as(u16, 3), config.context); -} |
