diff options
| author | s-ol <s+removethis@s-ol.nu> | 2025-03-10 17:28:29 +0000 |
|---|---|---|
| committer | s-ol <s+removethis@s-ol.nu> | 2025-03-15 13:05:19 +0000 |
| commit | 7a7e0909fd016b95f70448f227c251a5a7da8423 (patch) | |
| tree | d68ae85cee257205d710f281077dbb9e73107a10 /src | |
| parent | fix conditional compilation (diff) | |
| download | glsl-view-7a7e0909fd016b95f70448f227c251a5a7da8423.tar.gz glsl-view-7a7e0909fd016b95f70448f227c251a5a7da8423.zip | |
texture-share-vk output support
Diffstat (limited to 'src')
| -rw-r--r-- | src/c.zig | 5 | ||||
| -rw-r--r-- | src/config.zig | 317 | ||||
| -rw-r--r-- | src/main.zig | 10 | ||||
| -rw-r--r-- | src/output.zig | 203 | ||||
| -rw-r--r-- | src/yaml.zig | 127 |
5 files changed, 423 insertions, 239 deletions
@@ -15,4 +15,9 @@ pub usingnamespace @cImport({ if (build_config.have_hap) { @cInclude("hap.h"); } + + if (build_config.have_tsv) { + @cInclude("texture_share_gl/texture_share_gl_client.h"); + @cInclude("texture_share_vk/config.hpp"); + } }); diff --git a/src/config.zig b/src/config.zig index f8613bd..f1f65f9 100644 --- a/src/config.zig +++ b/src/config.zig @@ -2,25 +2,13 @@ const c = @import("c.zig"); const fs = @import("std").fs; const std = @import("std"); const debug = @import("std").debug; +const yaml = @import("yaml.zig"); +const out = @import("output.zig"); +const build_config = @import("build_config"); -pub const OutputConfig = struct { - const Type = enum { - window, - }; - - const FilterMode = enum(c.GLuint) { - nearest = c.GL_NEAREST, - linear = c.GL_LINEAR, - }; - - type: Type, - width: i32, - height: i32, - filter: FilterMode, - - // only for 'window' - monitor: []const u8, - fullscreen: bool, +pub const OutputConfig = union(enum) { + window: out.WindowOutput.Config, + texture_share_vk: if (build_config.have_tsv) out.TSVOutput.Config else void, }; pub const ParameterConfig = struct { @@ -42,14 +30,7 @@ pub const OSCConfig = union(enum) { URL: []const u8, }; -const defaultOutput = OutputConfig{ - .type = .window, - .width = 800, - .height = 600, - .filter = .linear, - .monitor = "", - .fullscreen = false, -}; +const defaultOutput: OutputConfig = .{ .window = .default }; pub const Config = struct { width: i32, @@ -60,7 +41,7 @@ pub const Config = struct { project_root: fs.Dir, osc: OSCConfig, - pub fn parse(allocator: *const std.mem.Allocator, filename: []const u8) !Config { + pub fn parse(allocator: std.mem.Allocator, filename: []const u8) !Config { var parser: c.yaml_parser_t = undefined; _ = c.yaml_parser_initialize(&parser); defer c.yaml_parser_delete(&parser); @@ -82,9 +63,9 @@ pub const Config = struct { .osc = .{ .URL = "osc.udp://:9000" }, }; - try expectEvent(&parser, c.YAML_STREAM_START_EVENT); - try expectEvent(&parser, c.YAML_DOCUMENT_START_EVENT); - try expectEvent(&parser, c.YAML_MAPPING_START_EVENT); + try yaml.expectEvent(&parser, c.YAML_STREAM_START_EVENT); + try yaml.expectEvent(&parser, c.YAML_DOCUMENT_START_EVENT); + try yaml.expectEvent(&parser, c.YAML_MAPPING_START_EVENT); while (true) { var event: c.yaml_event_t = undefined; @@ -99,22 +80,22 @@ pub const Config = struct { const key: []const u8 = data.value[0..data.length]; if (std.mem.eql(u8, key, "width")) { - config.width = try parseInt(&parser, i32); + config.width = try yaml.parseInt(&parser, i32); } else if (std.mem.eql(u8, key, "height")) { - config.height = try parseInt(&parser, i32); + config.height = try yaml.parseInt(&parser, i32); } else if (std.mem.eql(u8, key, "fragment")) { - config.fragment = try parseString(&parser, allocator); + config.fragment = try yaml.parseString(&parser, allocator); } else if (std.mem.eql(u8, key, "outputs")) { config.outputs = try parseOutputs(&parser, allocator); } else if (std.mem.eql(u8, key, "parameters")) { config.parameters = try parseParameters(&parser, allocator); } else if (std.mem.eql(u8, key, "project_root")) { - config.project_root = try fs.cwd().openDir(try parseString(&parser, allocator), .{}); + config.project_root = try fs.cwd().openDir(try yaml.parseString(&parser, allocator), .{}); } else if (std.mem.eql(u8, key, "osc")) { config.osc = try parseOSC(&parser, allocator); } else { debug.print("unknown key: '{s}'\n", .{key}); - try skipAny(&parser); + try yaml.skipAny(&parser); } }, else => { @@ -124,164 +105,95 @@ pub const Config = struct { } } - try expectEvent(&parser, c.YAML_DOCUMENT_END_EVENT); - try expectEvent(&parser, c.YAML_STREAM_END_EVENT); + try yaml.expectEvent(&parser, c.YAML_DOCUMENT_END_EVENT); + try yaml.expectEvent(&parser, c.YAML_STREAM_END_EVENT); return config; } }; -fn expectEvent(parser: *c.yaml_parser_t, expectedType: c.yaml_event_type_t) !void { - var event: c.yaml_event_t = undefined; - - if (c.yaml_parser_parse(parser, &event) != 1) - return error.YAMLParserError; - defer c.yaml_event_delete(&event); - - if (event.type != expectedType) { - debug.print("unexpected event: {}\n", .{event.type}); - return error.InvalidConfiguration; - } -} - -fn parseStringEvent(event: *c.yaml_event_t, allocator: *const std.mem.Allocator) ![]const u8 { - if (event.type != c.YAML_SCALAR_EVENT) - return error.InvalidType; - - const data = event.data.scalar; - const value: []const u8 = data.value[0..data.length]; - return try allocator.dupe(u8, value); -} - -fn parseString(parser: *c.yaml_parser_t, allocator: *const std.mem.Allocator) ![]const u8 { - var event: c.yaml_event_t = undefined; - if (c.yaml_parser_parse(parser, &event) != 1) - return error.YAMLParserError; - defer c.yaml_event_delete(&event); - - return parseStringEvent(&event, allocator); -} - -fn parseInt(parser: *c.yaml_parser_t, comptime T: type) !T { - var event: c.yaml_event_t = undefined; - if (c.yaml_parser_parse(parser, &event) != 1) - return error.YAMLParserError; - defer c.yaml_event_delete(&event); - - if (event.type != c.YAML_SCALAR_EVENT) - return error.InvalidType; - - const data = event.data.scalar; - const value: []const u8 = data.value[0..data.length]; - return try std.fmt.parseInt(T, value, 10); -} - -fn parseEnum(parser: *c.yaml_parser_t, comptime T: type) !T { - var event: c.yaml_event_t = undefined; - if (c.yaml_parser_parse(parser, &event) != 1) - return error.YAMLParserError; - defer c.yaml_event_delete(&event); - - if (event.type != c.YAML_SCALAR_EVENT) - return error.InvalidType; - - const data = event.data.scalar; - const value: []const u8 = data.value[0..data.length]; - - inline for (@typeInfo(T).@"enum".fields) |field| { - if (std.mem.eql(u8, value, field.name)) - return @field(T, field.name); - } - - return error.InvalidValue; -} - -fn parseBool(parser: *c.yaml_parser_t) !bool { - var event: c.yaml_event_t = undefined; - if (c.yaml_parser_parse(parser, &event) != 1) - return error.YAMLParserError; - defer c.yaml_event_delete(&event); - - if (event.type != c.YAML_SCALAR_EVENT) - return error.InvalidType; - - const data = event.data.scalar; - const value: []const u8 = data.value[0..data.length]; - - if (data.style != c.YAML_PLAIN_SCALAR_STYLE) - return false; - return std.mem.eql(u8, value, "true") or std.mem.eql(u8, value, "1"); -} - -fn parseOutputs(parser: *c.yaml_parser_t, allocator: *const std.mem.Allocator) ![]OutputConfig { - try expectEvent(parser, c.YAML_SEQUENCE_START_EVENT); +fn parseOutputs(parser: *c.yaml_parser_t, allocator: std.mem.Allocator) ![]OutputConfig { + try yaml.expectEvent(parser, c.YAML_SEQUENCE_START_EVENT); var outputs = try allocator.alloc(OutputConfig, 1024); var output_count: usize = 0; while (true) { - var seqEvent: c.yaml_event_t = undefined; - if (c.yaml_parser_parse(parser, &seqEvent) != 1) - return error.YAMLParserError; - defer c.yaml_event_delete(&seqEvent); - - switch (seqEvent.type) { - c.YAML_SEQUENCE_END_EVENT => break, - c.YAML_MAPPING_START_EVENT => { - const output = &outputs[output_count]; - output.* = defaultOutput; - - while (true) { - var event: c.yaml_event_t = undefined; - if (c.yaml_parser_parse(parser, &event) != 1) - return error.YAMLParserError; - defer c.yaml_event_delete(&event); - - switch (event.type) { - c.YAML_MAPPING_END_EVENT => break, - c.YAML_SCALAR_EVENT => { - const data = event.data.scalar; - const key: []const u8 = data.value[0..data.length]; - - if (std.mem.eql(u8, key, "type")) { - output.*.type = try parseEnum(parser, OutputConfig.Type); - } else if (std.mem.eql(u8, key, "width")) { - output.*.width = try parseInt(parser, i32); - } else if (std.mem.eql(u8, key, "height")) { - output.*.height = try parseInt(parser, i32); - } else if (std.mem.eql(u8, key, "filter")) { - output.*.filter = try parseEnum(parser, OutputConfig.FilterMode); - } else if (std.mem.eql(u8, key, "monitor")) { - output.*.monitor = try parseString(parser, allocator); - } else if (std.mem.eql(u8, key, "fullscreen")) { - output.*.fullscreen = try parseBool(parser); - } else { - debug.print("unknown key: '{s}'\n", .{key}); - try skipAny(parser); - } - }, - else => { - debug.print("unexpected event: {}\n", .{event.type}); - return error.InvalidConfiguration; - }, - } - } - - output_count += 1; - }, - else => { - debug.print("unexpected event: {}\n", .{seqEvent.type}); - return error.InvalidConfiguration; - }, - } + outputs[output_count] = yaml.parseUnion(parser, OutputConfig, allocator) catch |err| { + if (err == error.InvalidType) break; + return err; + }; + output_count += 1; + + // var seqEvent: c.yaml_event_t = undefined; + // if (c.yaml_parser_parse(parser, &seqEvent) != 1) + // return error.YAMLParserError; + // defer c.yaml_event_delete(&seqEvent); + + // switch (seqEvent.type) { + // c.YAML_SEQUENCE_END_EVENT => break, + // c.YAML_MAPPING_START_EVENT => { + // const output = &outputs[output_count]; + // output.* = defaultOutput; + // + // while (true) { + // var event: c.yaml_event_t = undefined; + // if (c.yaml_parser_parse(parser, &event) != 1) + // return error.YAMLParserError; + // defer c.yaml_event_delete(&event); + // + // switch (event.type) { + // c.YAML_MAPPING_END_EVENT => break, + // c.YAML_SCALAR_EVENT => { + // const data = event.data.scalar; + // const key: []const u8 = data.value[0..data.length]; + // + // if (!std.mem.eql(u8, key, "type")) { + // const ouput_type = try yaml.parseEnum(parser, OutputConfig.Type); + // output.* = switch (ouput_type) { + // inline else => |t| { + // + // } + // } + // } + // + // if (std.mem.eql(u8, key, "width")) { + // output.*.width = try yaml.parseInt(parser, i32); + // } else if (std.mem.eql(u8, key, "height")) { + // output.*.height = try yaml.parseInt(parser, i32); + // } else if (std.mem.eql(u8, key, "filter")) { + // output.*.filter = try yaml.parseEnum(parser, OutputConfig.FilterMode); + // } else if (std.mem.eql(u8, key, "monitor")) { + // output.*.monitor = try yaml.parseString(parser, allocator); + // } else if (std.mem.eql(u8, key, "fullscreen")) { + // output.*.fullscreen = try yaml.parseBool(parser); + // } else { + // debug.print("unknown key: '{s}'\n", .{key}); + // try yaml.skipAny(parser); + // } + // }, + // else => { + // debug.print("unexpected event: {}\n", .{event.type}); + // return error.InvalidConfiguration; + // }, + // } + // } + // + // output_count += 1; + // }, + // else => { + // debug.print("unexpected event: {}\n", .{seqEvent.type}); + // return error.InvalidConfiguration; + // }, + // } } _ = allocator.realloc(outputs, output_count) catch 0; return outputs[0..output_count]; } -fn parseParameters(parser: *c.yaml_parser_t, allocator: *const std.mem.Allocator) ![]ParameterConfig { - try expectEvent(parser, c.YAML_SEQUENCE_START_EVENT); +fn parseParameters(parser: *c.yaml_parser_t, allocator: std.mem.Allocator) ![]ParameterConfig { + try yaml.expectEvent(parser, c.YAML_SEQUENCE_START_EVENT); var parameters = try allocator.alloc(ParameterConfig, 1024); var param_count: usize = 0; @@ -312,14 +224,14 @@ fn parseParameters(parser: *c.yaml_parser_t, allocator: *const std.mem.Allocator const key: []const u8 = data.value[0..data.length]; if (std.mem.eql(u8, key, "name")) { - param.*.name = try parseString(parser, allocator); + param.*.name = try yaml.parseString(parser, allocator); have_name = true; } else if (std.mem.eql(u8, key, "type")) { - param.*.type = try parseString(parser, allocator); + param.*.type = try yaml.parseString(parser, allocator); have_type = true; } else { debug.print("unknown key: '{s}'\n", .{key}); - try skipAny(parser); + try yaml.skipAny(parser); } }, else => { @@ -347,14 +259,14 @@ fn parseParameters(parser: *c.yaml_parser_t, allocator: *const std.mem.Allocator return parameters[0..param_count]; } -fn parseOSC(parser: *c.yaml_parser_t, allocator: *const std.mem.Allocator) !OSCConfig { +fn parseOSC(parser: *c.yaml_parser_t, allocator: std.mem.Allocator) !OSCConfig { var event: c.yaml_event_t = undefined; if (c.yaml_parser_parse(parser, &event) != 1) return error.YAMLParserError; defer c.yaml_event_delete(&event); if (event.type == c.YAML_SCALAR_EVENT) { - const url = try parseStringEvent(&event, allocator); + const url = try yaml.parseStringEvent(&event, allocator); return OSCConfig{ .URL = url }; } else if (event.type != c.YAML_MAPPING_START_EVENT) { debug.print("unexpected event: {}\n", .{event.type}); @@ -375,12 +287,12 @@ fn parseOSC(parser: *c.yaml_parser_t, allocator: *const std.mem.Allocator) !OSCC const key: []const u8 = data.value[0..data.length]; if (std.mem.eql(u8, key, "protocol")) { - config.Manual.protocol = try parseEnum(parser, OSCConfig.Protocol); + config.Manual.protocol = try yaml.parseEnum(parser, OSCConfig.Protocol); } else if (std.mem.eql(u8, key, "port")) { - config.Manual.port = try parseInt(parser, u16); + config.Manual.port = try yaml.parseInt(parser, u16); } else { debug.print("unknown key: '{s}'\n", .{key}); - try skipAny(parser); + try yaml.skipAny(parser); } }, else => { @@ -392,38 +304,3 @@ fn parseOSC(parser: *c.yaml_parser_t, allocator: *const std.mem.Allocator) !OSCC return config; } - -fn skipAny(parser: *c.yaml_parser_t) !void { - var event: c.yaml_event_t = undefined; - var depth: u32 = 0; - while (true) { - if (c.yaml_parser_parse(parser, &event) != 1) - return error.YAMLParserError; - defer c.yaml_event_delete(&event); - - switch (event.type) { - c.YAML_SCALAR_EVENT => { - if (depth == 0) - break; - }, - - c.YAML_SEQUENCE_START_EVENT, - c.YAML_MAPPING_START_EVENT, - => depth += 1, - - c.YAML_SEQUENCE_END_EVENT, - c.YAML_MAPPING_END_EVENT, - => { - depth -= 1; - - if (depth == 0) - break; - }, - - else => { - debug.print("unexpected event: {}\n", .{event.type}); - return error.InvalidConfiguration; - }, - } - } -} diff --git a/src/main.zig b/src/main.zig index ae567bd..932fdca 100644 --- a/src/main.zig +++ b/src/main.zig @@ -28,7 +28,7 @@ pub fn main() !void { _ = args.next(); const filename = args.next() orelse "config.yaml"; - var config = try cfg.Config.parse(&arena.allocator(), filename); + var config = try cfg.Config.parse(arena.allocator(), filename); _ = c.glfwSetErrorCallback(errorCallback); @@ -68,11 +68,11 @@ pub fn main() !void { var outputs = try std.ArrayList(*out.Output).initCapacity(arena.allocator(), config.outputs.len); defer outputs.deinit(); - for (config.outputs) |output_config| { + for (config.outputs) |*output_config| { try outputs.append(out.Output.create(arena.allocator(), output_config, &constants)); } defer for (outputs.items) |output| { - output.destroy(output); + output.destroy(arena.allocator()); }; c.glfwMakeContextCurrent(window); @@ -147,10 +147,10 @@ pub fn main() !void { fbo.unbind(); for (outputs.items, 0..) |output, i| { - const close = output.update(output, fbo.texture_id); + const close = output.update(fbo.texture_id); if (close) { const removed = outputs.swapRemove(i); - removed.destroy(removed); + removed.destroy(arena.allocator()); break; } } diff --git a/src/output.zig b/src/output.zig index 459bedb..960c8ae 100644 --- a/src/output.zig +++ b/src/output.zig @@ -1,31 +1,202 @@ -const c = @import("c.zig"); const std = @import("std"); +const c = @import("c.zig"); +const build_config = @import("build_config"); const cfg = @import("config.zig"); const gl = @import("gl.zig"); +const yaml = @import("yaml.zig"); pub const Output = struct { - update: *const fn (*Output, c.GLuint) bool, - destroy: *const fn (*Output) void, + update_fn: *const fn (output: *Output, texture_id: c.GLuint) bool, + destroy_fn: *const fn (output: *Output, allocator: std.mem.Allocator) void, - fn init(update: *const fn (*Output, c.GLuint) bool, destroy: *const fn (*Output) void) Output { - return Output{ - .update = update, - .destroy = destroy, + pub fn create( + allocator: std.mem.Allocator, + config: *const cfg.OutputConfig, + constants: *gl.Constants, + ) *Output { + return switch (config.*) { + .window => |*con| WindowOutput.create(allocator, con, constants), + .texture_share_vk => |*con| if (build_config.have_tsv) TSVOutput.create(allocator, con, constants) else unreachable, }; } + pub fn update(self: *Output, texture_id: c.GLuint) bool { + return self.update_fn(self, texture_id); + } + + pub fn destroy(self: *Output, allocator: std.mem.Allocator) void { + return self.destroy_fn(self, allocator); + } +}; + +pub const TSVOutput = struct { + pub const Config = struct { + name: [:0]const u8, + + pub const default: Config = .{ + .name = "glsl-view", + }; + + pub fn parse(parser: *c.yaml_parser_t, allocator: std.mem.Allocator) !Config { + var self: Config = .default; + + while (true) { + var event: c.yaml_event_t = undefined; + if (c.yaml_parser_parse(parser, &event) != 1) + return error.YAMLParserError; + defer c.yaml_event_delete(&event); + + switch (event.type) { + c.YAML_MAPPING_END_EVENT => break, + c.YAML_SCALAR_EVENT => { + const data = event.data.scalar; + const key: []const u8 = data.value[0..data.length]; + + if (std.mem.eql(u8, key, "name")) { + self.name = try yaml.parseStringZ(parser, allocator); + } else { + std.debug.print("unknown key: '{s}'\n", .{key}); + try yaml.skipAny(parser); + } + }, + else => { + std.debug.print("unexpected event: {}\n", .{event.type}); + return error.InvalidConfiguration; + }, + } + } + + return self; + } + }; + + output: Output, + config: *const Config, + client: *c.GlClient, + image_size: c.GlImageExtent, + pub fn create( allocator: std.mem.Allocator, - config: cfg.OutputConfig, + config: *const Config, constants: *gl.Constants, ) *Output { - return switch (config.type) { - .window => WindowOutput.create(allocator, config, constants), + const self = allocator.create(TSVOutput) catch unreachable; + + _ = c.gl_client_initialize_external_gl() or unreachable; + + self.* = .{ + .output = .{ + .update_fn = update, + .destroy_fn = destroy, + }, + .config = config, + .client = c.gl_client_new(c.VK_SERVER_DEFAULT_SOCKET_PATH, 1000) orelse unreachable, + .image_size = .{ + .top_left = .{ 0, 0 }, + .bottom_right = .{ constants.config.width, constants.config.height }, + }, }; + + _ = c.gl_client_init_image( + self.client, + config.name, + @intCast(constants.config.width), + @intCast(constants.config.height), + c.R8G8B8A8, + true, + ); + + return &self.output; + } + + fn update(output: *Output, texture_id: c.GLuint) bool { + const self: *TSVOutput = @fieldParentPtr("output", output); + + var fbo: c.GLint = undefined; + c.glGetIntegerv(c.GL_DRAW_FRAMEBUFFER_BINDING, &fbo); + + _ = c.gl_client_send_image( + self.client, + self.config.name, + texture_id, + c.GL_TEXTURE_2D, + false, + @intCast(fbo), + &self.image_size, + ); + return false; + } + + fn destroy(output: *Output, allocator: std.mem.Allocator) void { + const self: *TSVOutput = @fieldParentPtr("output", output); + + allocator.destroy(self); } }; pub const WindowOutput = struct { + pub const Config = struct { + const FilterMode = enum(c.GLuint) { + nearest = c.GL_NEAREST, + linear = c.GL_LINEAR, + }; + + width: i32, + height: i32, + filter: FilterMode, + + monitor: []const u8, + fullscreen: bool, + + pub const default: Config = .{ + .width = 800, + .height = 600, + .filter = .linear, + .monitor = "", + .fullscreen = false, + }; + + pub fn parse(parser: *c.yaml_parser_t, allocator: std.mem.Allocator) !Config { + var self: Config = .default; + + while (true) { + var event: c.yaml_event_t = undefined; + if (c.yaml_parser_parse(parser, &event) != 1) + return error.YAMLParserError; + defer c.yaml_event_delete(&event); + + switch (event.type) { + c.YAML_MAPPING_END_EVENT => break, + c.YAML_SCALAR_EVENT => { + const data = event.data.scalar; + const key: []const u8 = data.value[0..data.length]; + + if (std.mem.eql(u8, key, "width")) { + self.width = try yaml.parseInt(parser, i32); + } else if (std.mem.eql(u8, key, "height")) { + self.height = try yaml.parseInt(parser, i32); + } else if (std.mem.eql(u8, key, "filter")) { + self.filter = try yaml.parseEnum(parser, FilterMode); + } else if (std.mem.eql(u8, key, "monitor")) { + self.monitor = try yaml.parseString(parser, allocator); + } else if (std.mem.eql(u8, key, "fullscreen")) { + self.fullscreen = try yaml.parseBool(parser); + } else { + std.debug.print("unknown key: '{s}'\n", .{key}); + try yaml.skipAny(parser); + } + }, + else => { + std.debug.print("unexpected event: {}\n", .{event.type}); + return error.InvalidConfiguration; + }, + } + } + + return self; + } + }; + output: Output, window: *c.GLFWwindow, constants: *gl.Constants, @@ -34,16 +205,19 @@ pub const WindowOutput = struct { pub fn create( allocator: std.mem.Allocator, - config: cfg.OutputConfig, + config: *const Config, constants: *gl.Constants, ) *Output { const self = allocator.create(WindowOutput) catch unreachable; c.glfwDefaultWindowHints(); - self.* = WindowOutput{ + self.* = .{ .constants = constants, - .output = Output.init(update, destroy), + .output = .{ + .update_fn = update, + .destroy_fn = destroy, + }, .window = c.glfwCreateWindow( config.width, config.height, @@ -108,10 +282,11 @@ pub const WindowOutput = struct { return false; } - fn destroy(output: *Output) void { + fn destroy(output: *Output, allocator: std.mem.Allocator) void { const self: *WindowOutput = @fieldParentPtr("output", output); c.glfwDestroyWindow(self.window); + allocator.destroy(self); } fn keyCallback( diff --git a/src/yaml.zig b/src/yaml.zig new file mode 100644 index 0000000..36e1770 --- /dev/null +++ b/src/yaml.zig @@ -0,0 +1,127 @@ +const c = @import("c.zig"); +const std = @import("std"); +const debug = @import("std").debug; + +pub fn expectEvent(parser: *c.yaml_parser_t, expectedType: c.yaml_event_type_t) !void { + var event: c.yaml_event_t = undefined; + + if (c.yaml_parser_parse(parser, &event) != 1) + return error.YAMLParserError; + defer c.yaml_event_delete(&event); + + if (event.type != expectedType) { + debug.print("unexpected event: {}\n", .{event.type}); + return error.InvalidConfiguration; + } +} + +pub fn parseStringEvent(event: *c.yaml_event_t, allocator: std.mem.Allocator) ![]const u8 { + if (event.type != c.YAML_SCALAR_EVENT) + return error.InvalidType; + + const data = event.data.scalar; + const value: []const u8 = data.value[0..data.length]; + return try allocator.dupe(u8, value); +} + +pub fn parseString(parser: *c.yaml_parser_t, allocator: std.mem.Allocator) ![]const u8 { + var event: c.yaml_event_t = undefined; + if (c.yaml_parser_parse(parser, &event) != 1) + return error.YAMLParserError; + defer c.yaml_event_delete(&event); + + return parseStringEvent(&event, allocator); +} + +pub fn parseInt(parser: *c.yaml_parser_t, comptime T: type) !T { + var event: c.yaml_event_t = undefined; + if (c.yaml_parser_parse(parser, &event) != 1) + return error.YAMLParserError; + defer c.yaml_event_delete(&event); + + if (event.type != c.YAML_SCALAR_EVENT) + return error.InvalidType; + + const data = event.data.scalar; + const value: []const u8 = data.value[0..data.length]; + return try std.fmt.parseInt(T, value, 10); +} + +pub fn parseEnum(parser: *c.yaml_parser_t, comptime T: type) !T { + var event: c.yaml_event_t = undefined; + if (c.yaml_parser_parse(parser, &event) != 1) + return error.YAMLParserError; + defer c.yaml_event_delete(&event); + + if (event.type != c.YAML_SCALAR_EVENT) + return error.InvalidType; + + const data = event.data.scalar; + const value: []const u8 = data.value[0..data.length]; + + inline for (@typeInfo(T).@"enum".fields) |field| { + if (std.mem.eql(u8, value, field.name)) + return @field(T, field.name); + } + + return error.InvalidValue; +} + +pub fn parseUnion(parser: *c.yaml_parser_t, comptime T: type, allocator: std.mem.Allocator) !T { + _ = parser; + _ = allocator; + // sorry, i lost this code in a git accident and have since moved on 🤡 + unreachable; +} + +pub fn parseBool(parser: *c.yaml_parser_t) !bool { + var event: c.yaml_event_t = undefined; + if (c.yaml_parser_parse(parser, &event) != 1) + return error.YAMLParserError; + defer c.yaml_event_delete(&event); + + if (event.type != c.YAML_SCALAR_EVENT) + return error.InvalidType; + + const data = event.data.scalar; + const value: []const u8 = data.value[0..data.length]; + + if (data.style != c.YAML_PLAIN_SCALAR_STYLE) + return false; + return std.mem.eql(u8, value, "true") or std.mem.eql(u8, value, "1"); +} + +pub fn skipAny(parser: *c.yaml_parser_t) !void { + var event: c.yaml_event_t = undefined; + var depth: u32 = 0; + while (true) { + if (c.yaml_parser_parse(parser, &event) != 1) + return error.YAMLParserError; + defer c.yaml_event_delete(&event); + + switch (event.type) { + c.YAML_SCALAR_EVENT => { + if (depth == 0) + break; + }, + + c.YAML_SEQUENCE_START_EVENT, + c.YAML_MAPPING_START_EVENT, + => depth += 1, + + c.YAML_SEQUENCE_END_EVENT, + c.YAML_MAPPING_END_EVENT, + => { + depth -= 1; + + if (depth == 0) + break; + }, + + else => { + debug.print("unexpected event: {}\n", .{event.type}); + return error.InvalidConfiguration; + }, + } + } +} |
