forked from mirror/vulkan-zig
Begin wrapper rendering
This commit is contained in:
@@ -60,6 +60,7 @@ pub const Container = struct {
|
|||||||
name: []const u8,
|
name: []const u8,
|
||||||
field_type: TypeInfo,
|
field_type: TypeInfo,
|
||||||
bits: ?usize,
|
bits: ?usize,
|
||||||
|
is_buffer_len: bool,
|
||||||
};
|
};
|
||||||
|
|
||||||
fields: []Field,
|
fields: []Field,
|
||||||
@@ -99,6 +100,7 @@ pub const Command = struct {
|
|||||||
pub const Param = struct {
|
pub const Param = struct {
|
||||||
name: []const u8,
|
name: []const u8,
|
||||||
param_type: TypeInfo,
|
param_type: TypeInfo,
|
||||||
|
is_buffer_len: bool,
|
||||||
};
|
};
|
||||||
|
|
||||||
params: []Param,
|
params: []Param,
|
||||||
@@ -108,9 +110,10 @@ pub const Command = struct {
|
|||||||
};
|
};
|
||||||
|
|
||||||
pub const Pointer = struct {
|
pub const Pointer = struct {
|
||||||
pub const PointerSize = enum {
|
pub const PointerSize = union(enum) {
|
||||||
one,
|
one,
|
||||||
many, // The length is given by some expression
|
many, // The length is given by some complex expression, possibly involving another field
|
||||||
|
other_field: []const u8, // The length is given by some other field or parameter
|
||||||
zero_terminated
|
zero_terminated
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -246,6 +246,7 @@ pub fn parseMember(allocator: *Allocator, xctok: *XmlCTokenizer) !registry.Conta
|
|||||||
.name = decl.name orelse return error.MissingTypeIdentifier,
|
.name = decl.name orelse return error.MissingTypeIdentifier,
|
||||||
.field_type = decl.decl_type,
|
.field_type = decl.decl_type,
|
||||||
.bits = null,
|
.bits = null,
|
||||||
|
.is_buffer_len = false,
|
||||||
};
|
};
|
||||||
|
|
||||||
if (try xctok.peek()) |tok| {
|
if (try xctok.peek()) |tok| {
|
||||||
@@ -404,6 +405,7 @@ fn parseFnPtrSuffix(allocator: *Allocator, xctok: *XmlCTokenizer, return_type: T
|
|||||||
try params.append(.{
|
try params.append(.{
|
||||||
.name = first_param.name.?,
|
.name = first_param.name.?,
|
||||||
.param_type = first_param.decl_type,
|
.param_type = first_param.decl_type,
|
||||||
|
.is_buffer_len = false,
|
||||||
});
|
});
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
@@ -417,6 +419,7 @@ fn parseFnPtrSuffix(allocator: *Allocator, xctok: *XmlCTokenizer, return_type: T
|
|||||||
try params.append(.{
|
try params.append(.{
|
||||||
.name = decl.name orelse return error.MissingTypeIdentifier,
|
.name = decl.name orelse return error.MissingTypeIdentifier,
|
||||||
.param_type = decl.decl_type,
|
.param_type = decl.decl_type,
|
||||||
|
.is_buffer_len = false,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -455,7 +458,7 @@ fn parsePointers(allocator: *Allocator, xctok: *XmlCTokenizer, inner_const: bool
|
|||||||
type_info = .{
|
type_info = .{
|
||||||
.pointer = .{
|
.pointer = .{
|
||||||
.is_const = is_const or first_const,
|
.is_const = is_const or first_const,
|
||||||
.is_optional = true, // set elsewhere
|
.is_optional = false, // set elsewhere
|
||||||
.size = .one, // set elsewhere
|
.size = .one, // set elsewhere
|
||||||
.child = child,
|
.child = child,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -173,18 +173,31 @@ fn parseContainer(allocator: *Allocator, ty: *xml.Element, is_union: bool) !regi
|
|||||||
while (it.next()) |member| {
|
while (it.next()) |member| {
|
||||||
var xctok = cparse.XmlCTokenizer.init(member);
|
var xctok = cparse.XmlCTokenizer.init(member);
|
||||||
members[i] = try cparse.parseMember(allocator, &xctok);
|
members[i] = try cparse.parseMember(allocator, &xctok);
|
||||||
try parsePointerMeta(&members[i].field_type, member);
|
|
||||||
i += 1;
|
i += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
members = allocator.shrink(members, i);
|
||||||
|
const decl_type = registry.DeclarationType{
|
||||||
|
.container = .{
|
||||||
|
.fields = members,
|
||||||
|
.is_union = is_union,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
it = ty.findChildrenByTag("member");
|
||||||
|
for (members) |*member| {
|
||||||
|
const member_elem = it.next().?;
|
||||||
|
try parsePointerMeta(decl_type, &member.field_type, member_elem);
|
||||||
|
|
||||||
|
// pNext isn't properly marked as optional, so just manually override it,
|
||||||
|
if (mem.eql(u8, member.name, "pNext")) {
|
||||||
|
member.field_type.pointer.is_optional = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return registry.Declaration{
|
return registry.Declaration{
|
||||||
.name = name,
|
.name = name,
|
||||||
.decl_type = .{
|
.decl_type = decl_type,
|
||||||
.container = .{
|
|
||||||
.fields = allocator.shrink(members, i),
|
|
||||||
.is_union = is_union,
|
|
||||||
}
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -193,7 +206,27 @@ fn parseFuncPointer(allocator: *Allocator, ty: *xml.Element) !registry.Declarati
|
|||||||
return try cparse.parseTypedef(allocator, &xctok);
|
return try cparse.parseTypedef(allocator, &xctok);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn lenToPointerSize(len: []const u8) registry.Pointer.PointerSize {
|
fn lenToPointerSize(decl_type: registry.DeclarationType, len: []const u8) registry.Pointer.PointerSize {
|
||||||
|
switch (decl_type) {
|
||||||
|
.command => |command| {
|
||||||
|
for (command.params) |*param| {
|
||||||
|
if (mem.eql(u8, param.name, len)) {
|
||||||
|
param.is_buffer_len = true;
|
||||||
|
return .{.other_field = param.name};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
.container => |container| {
|
||||||
|
for (container.fields) |*field| {
|
||||||
|
if (mem.eql(u8, field.name, len)) {
|
||||||
|
field.is_buffer_len = true;
|
||||||
|
return .{.other_field = field.name};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
else => {},
|
||||||
|
}
|
||||||
|
|
||||||
if (mem.eql(u8, len, "null-terminated")) {
|
if (mem.eql(u8, len, "null-terminated")) {
|
||||||
return .zero_terminated;
|
return .zero_terminated;
|
||||||
} else {
|
} else {
|
||||||
@@ -201,12 +234,13 @@ fn lenToPointerSize(len: []const u8) registry.Pointer.PointerSize {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parsePointerMeta(type_info: *registry.TypeInfo, elem: *xml.Element) !void {
|
fn parsePointerMeta(decl_type: registry.DeclarationType, type_info: *registry.TypeInfo, elem: *xml.Element) !void {
|
||||||
if (elem.getAttribute("len")) |lens| {
|
if (elem.getAttribute("len")) |lens| {
|
||||||
var it = mem.split(lens, ",");
|
var it = mem.split(lens, ",");
|
||||||
var current_type_info = type_info;
|
var current_type_info = type_info;
|
||||||
while (current_type_info.* == .pointer) {
|
while (current_type_info.* == .pointer) {
|
||||||
const size = if (it.next()) |len_str| lenToPointerSize(len_str) else .one;
|
// TODO: Check altlen
|
||||||
|
const size = if (it.next()) |len_str| lenToPointerSize(decl_type, len_str) else .one;
|
||||||
current_type_info.pointer.size = size;
|
current_type_info.pointer.size = size;
|
||||||
current_type_info = current_type_info.pointer.child;
|
current_type_info = current_type_info.pointer.child;
|
||||||
}
|
}
|
||||||
@@ -372,8 +406,11 @@ fn parseCommand(allocator: *Allocator, elem: *xml.Element) !registry.Declaration
|
|||||||
while (it.next()) |param| {
|
while (it.next()) |param| {
|
||||||
var xctok = cparse.XmlCTokenizer.init(param);
|
var xctok = cparse.XmlCTokenizer.init(param);
|
||||||
const decl = try cparse.parseParamOrProto(allocator, &xctok);
|
const decl = try cparse.parseParamOrProto(allocator, &xctok);
|
||||||
params[i] = .{.name = decl.name, .param_type = decl.decl_type.typedef};
|
params[i] = .{
|
||||||
try parsePointerMeta(¶ms[i].param_type, param);
|
.name = decl.name,
|
||||||
|
.param_type = decl.decl_type.typedef,
|
||||||
|
.is_buffer_len = false,
|
||||||
|
};
|
||||||
i += 1;
|
i += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -390,16 +427,25 @@ fn parseCommand(allocator: *Allocator, elem: *xml.Element) !registry.Declaration
|
|||||||
else
|
else
|
||||||
&[_][]const u8{};
|
&[_][]const u8{};
|
||||||
|
|
||||||
|
params = allocator.shrink(params, i);
|
||||||
|
var decl_type = registry.DeclarationType{
|
||||||
|
.command = .{
|
||||||
|
.params = params,
|
||||||
|
.return_type = return_type,
|
||||||
|
.success_codes = success_codes,
|
||||||
|
.error_codes = error_codes,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
it = elem.findChildrenByTag("param");
|
||||||
|
for (params) |*param| {
|
||||||
|
const param_elem = it.next().?;
|
||||||
|
try parsePointerMeta(decl_type, ¶m.param_type, param_elem);
|
||||||
|
}
|
||||||
|
|
||||||
return registry.Declaration{
|
return registry.Declaration{
|
||||||
.name = command_decl.name,
|
.name = command_decl.name,
|
||||||
.decl_type = .{
|
.decl_type = decl_type,
|
||||||
.command = .{
|
|
||||||
.params = allocator.shrink(params, i),
|
|
||||||
.return_type = return_type,
|
|
||||||
.success_codes = success_codes,
|
|
||||||
.error_codes = error_codes,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -88,6 +88,15 @@ fn Renderer(comptime WriterType: type) type {
|
|||||||
tag: ?[]const u8,
|
tag: ?[]const u8,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const ParamType = enum {
|
||||||
|
in_pointer,
|
||||||
|
out_pointer,
|
||||||
|
bitflags,
|
||||||
|
mut_buffer_len,
|
||||||
|
buffer_len,
|
||||||
|
other,
|
||||||
|
};
|
||||||
|
|
||||||
writer: WriterType,
|
writer: WriterType,
|
||||||
allocator: *Allocator,
|
allocator: *Allocator,
|
||||||
registry: *const reg.Registry,
|
registry: *const reg.Registry,
|
||||||
@@ -131,7 +140,7 @@ fn Renderer(comptime WriterType: type) type {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn exctractBitflagName(self: Self, name: []const u8) ?BitflagName {
|
fn extractBitflagName(self: Self, name: []const u8) ?BitflagName {
|
||||||
const tag = util.getAuthorTag(name, self.registry.tags);
|
const tag = util.getAuthorTag(name, self.registry.tags);
|
||||||
const base_name = if (tag) |tag_name| name[0 .. name.len - tag_name.len] else name;
|
const base_name = if (tag) |tag_name| name[0 .. name.len - tag_name.len] else name;
|
||||||
|
|
||||||
@@ -145,6 +154,41 @@ fn Renderer(comptime WriterType: type) type {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn classifyParam(self: Self, param: reg.Command.Param) !ParamType {
|
||||||
|
switch (param.param_type) {
|
||||||
|
.pointer => |ptr| {
|
||||||
|
if (param.is_buffer_len) {
|
||||||
|
if (ptr.is_const or ptr.is_optional) {
|
||||||
|
return error.InvalidRegistry;
|
||||||
|
}
|
||||||
|
|
||||||
|
return .mut_buffer_len;
|
||||||
|
}
|
||||||
|
|
||||||
|
const child_is_void = ptr.child.* == .name and mem.eql(u8, ptr.child.name, "void");
|
||||||
|
if (!child_is_void and ptr.size == .one and !ptr.is_optional) {
|
||||||
|
if (ptr.is_const) {
|
||||||
|
return .in_pointer;
|
||||||
|
} else {
|
||||||
|
return .out_pointer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
.name => |name| {
|
||||||
|
if (self.extractBitflagName(param.param_type.name) != null) {
|
||||||
|
return .bitflags;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
else => {},
|
||||||
|
}
|
||||||
|
|
||||||
|
if (param.is_buffer_len) {
|
||||||
|
return .buffer_len;
|
||||||
|
}
|
||||||
|
|
||||||
|
return .other;
|
||||||
|
}
|
||||||
|
|
||||||
fn render(self: *Self) !void {
|
fn render(self: *Self) !void {
|
||||||
try self.writer.writeAll(preamble);
|
try self.writer.writeAll(preamble);
|
||||||
|
|
||||||
@@ -157,6 +201,7 @@ fn Renderer(comptime WriterType: type) type {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try self.renderCommandPtrs();
|
try self.renderCommandPtrs();
|
||||||
|
try self.renderWrappers();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn renderApiConstant(self: *Self, api_constant: reg.ApiConstant) !void {
|
fn renderApiConstant(self: *Self, api_constant: reg.ApiConstant) !void {
|
||||||
@@ -238,7 +283,7 @@ fn Renderer(comptime WriterType: type) type {
|
|||||||
if (builtin_types.get(name)) |zig_name| {
|
if (builtin_types.get(name)) |zig_name| {
|
||||||
try self.writer.writeAll(zig_name);
|
try self.writer.writeAll(zig_name);
|
||||||
return;
|
return;
|
||||||
} else if (self.exctractBitflagName(name)) |bitflag_name| {
|
} else if (self.extractBitflagName(name)) |bitflag_name| {
|
||||||
try self.writer.print("{}Flags{}", .{
|
try self.writer.print("{}Flags{}", .{
|
||||||
util.trimVkNamespace(bitflag_name.base_name),
|
util.trimVkNamespace(bitflag_name.base_name),
|
||||||
@as([]const u8, if (bitflag_name.tag) |tag| tag else "")
|
@as([]const u8, if (bitflag_name.tag) |tag| tag else "")
|
||||||
@@ -286,7 +331,7 @@ fn Renderer(comptime WriterType: type) type {
|
|||||||
const size = if (child_is_void) .one else pointer.size;
|
const size = if (child_is_void) .one else pointer.size;
|
||||||
switch (size) {
|
switch (size) {
|
||||||
.one => try self.writer.writeByte('*'),
|
.one => try self.writer.writeByte('*'),
|
||||||
.many => try self.writer.writeAll("[*]"),
|
.many, .other_field => try self.writer.writeAll("[*]"),
|
||||||
.zero_terminated => try self.writer.writeAll("[*:0]"),
|
.zero_terminated => try self.writer.writeAll("[*:0]"),
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -412,6 +457,38 @@ fn Renderer(comptime WriterType: type) type {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try self.writer.writeAll("};\n");
|
try self.writer.writeAll("};\n");
|
||||||
|
|
||||||
|
if (mem.eql(u8, name, "VkResult")) {
|
||||||
|
try self.renderResultErrorSet(enumeration);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn renderResultAsError(self: *Self, name: []const u8) !void {
|
||||||
|
const error_prefix = "VK_ERROR_";
|
||||||
|
if (!mem.startsWith(u8, name, error_prefix)) {
|
||||||
|
return error.NotErrorResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
try self.writeIdentifierWithCase(.title, name[error_prefix.len ..]);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn renderResultErrorSet(self: *Self, enumeration: reg.Enum) !void {
|
||||||
|
try self.writer.writeAll("pub const Error = error{\n");
|
||||||
|
const error_prefix = "VK_ERROR_";
|
||||||
|
for (enumeration.fields) |field| {
|
||||||
|
if (field.value != .int) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.renderResultAsError(field.name) catch |err| switch (err) {
|
||||||
|
error.NotErrorResult => continue,
|
||||||
|
else => |narrowed| return narrowed
|
||||||
|
};
|
||||||
|
|
||||||
|
try self.writer.writeAll(",\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
try self.writer.writeAll("};\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
fn renderBitmaskBits(self: *Self, name: []const u8, bits: reg.Enum) !void {
|
fn renderBitmaskBits(self: *Self, name: []const u8, bits: reg.Enum) !void {
|
||||||
@@ -470,7 +547,7 @@ fn Renderer(comptime WriterType: type) type {
|
|||||||
fn renderAlias(self: *Self, name: []const u8, alias: reg.Alias) !void {
|
fn renderAlias(self: *Self, name: []const u8, alias: reg.Alias) !void {
|
||||||
if (alias.target == .other_command) {
|
if (alias.target == .other_command) {
|
||||||
return;
|
return;
|
||||||
} else if (self.exctractBitflagName(name) != null) {
|
} else if (self.extractBitflagName(name) != null) {
|
||||||
// Don't make aliases of the bitflag names, as those are replaced by just the flags type
|
// Don't make aliases of the bitflag names, as those are replaced by just the flags type
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -526,28 +603,188 @@ fn Renderer(comptime WriterType: type) type {
|
|||||||
try self.writer.writeAll(";\n");
|
try self.writer.writeAll(";\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// try self.writer.writeAll(
|
||||||
|
// \\const commands = struct {
|
||||||
|
// \\ const CommandInfo = struct {
|
||||||
|
// \\ Pfn: type,
|
||||||
|
// \\ link_name: [:0]const u8,
|
||||||
|
// \\ };
|
||||||
|
// \\
|
||||||
|
// );
|
||||||
|
// for (self.registry.decls) |decl| {
|
||||||
|
// if (decl.decl_type != .command) {
|
||||||
|
// continue;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// try self.writer.writeAll("const ");
|
||||||
|
// try self.renderTypeName(decl.name);
|
||||||
|
// try self.writer.print(
|
||||||
|
// " = CommandInfo{{ .Pfn = PFN_{}, .link_name = \"{}\" }};\n",
|
||||||
|
// .{decl.name, decl.name}
|
||||||
|
// );
|
||||||
|
// }
|
||||||
|
|
||||||
|
// try self.writer.writeAll("};\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
fn renderWrappers(self: *Self) !void {
|
||||||
try self.writer.writeAll(
|
try self.writer.writeAll(
|
||||||
\\const commands = struct {
|
\\pub fn Wrapper(comptime Self: type) type {
|
||||||
\\ const CommandInfo = struct {
|
\\ return struct {
|
||||||
\\ Pfn: type,
|
|
||||||
\\ link_name: [:0]const u8,
|
|
||||||
\\ };
|
|
||||||
\\
|
\\
|
||||||
);
|
);
|
||||||
for (self.registry.decls) |decl| {
|
|
||||||
if (decl.decl_type != .command) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
try self.writer.writeAll("const ");
|
for (self.registry.decls) |decl| {
|
||||||
try self.renderTypeName(decl.name);
|
if (decl.decl_type == .command) {
|
||||||
try self.writer.print(
|
try self.renderWrapper(decl.name, decl.decl_type.command);
|
||||||
" = CommandInfo{{ .Pfn = PFN_{}, .link_name = \"{}\" }};\n",
|
}
|
||||||
.{decl.name, decl.name}
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
try self.writer.writeAll("};\n");
|
try self.writer.writeAll("};}\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
fn inPointerAdjustedName(name: []const u8) []const u8 {
|
||||||
|
var it = util.SegmentIterator.init(name);
|
||||||
|
return if (mem.eql(u8, it.next().?, "p"))
|
||||||
|
name[1..]
|
||||||
|
else
|
||||||
|
name;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn renderWrapperPrototype(self: *Self, name: []const u8, command: reg.Command) !void {
|
||||||
|
try self.writer.writeAll("pub fn ");
|
||||||
|
try self.writeIdentifierWithCase(.camel, util.trimVkNamespace(name));
|
||||||
|
try self.writer.writeAll("(self: Self, ");
|
||||||
|
|
||||||
|
for (command.params) |param| {
|
||||||
|
switch (try self.classifyParam(param)) {
|
||||||
|
.in_pointer => {
|
||||||
|
// Remove one pointer level
|
||||||
|
try self.writeIdentifierWithCase(.snake, inPointerAdjustedName(param.name));
|
||||||
|
try self.writer.writeAll(": ");
|
||||||
|
try self.renderTypeInfo(param.param_type.pointer.child.*);
|
||||||
|
},
|
||||||
|
.out_pointer => continue, // Return vaPlue
|
||||||
|
.bitflags, // Special stuff handled in renderWrapperCall
|
||||||
|
.buffer_len,
|
||||||
|
.mut_buffer_len,
|
||||||
|
.other => {
|
||||||
|
try self.writeIdentifierWithCase(.snake, param.name);
|
||||||
|
try self.writer.writeAll(": ");
|
||||||
|
try self.renderTypeInfo(param.param_type);
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
try self.writer.writeAll(", ");
|
||||||
|
}
|
||||||
|
|
||||||
|
try self.writer.writeAll(") ");
|
||||||
|
}
|
||||||
|
|
||||||
|
fn renderWrapperCall(self: *Self, name: []const u8, command: reg.Command) !void {
|
||||||
|
try self.writer.writeAll("return self.");
|
||||||
|
try self.writeIdentifier(name);
|
||||||
|
try self.writer.writeAll("(");
|
||||||
|
|
||||||
|
for (command.params) |param| {
|
||||||
|
switch (try self.classifyParam(param)) {
|
||||||
|
.in_pointer => {
|
||||||
|
try self.writer.writeByte('&');
|
||||||
|
try self.writeIdentifierWithCase(.snake, inPointerAdjustedName(param.name));
|
||||||
|
},
|
||||||
|
.out_pointer => {
|
||||||
|
try self.writer.writeByte('&');
|
||||||
|
try self.writeIdentifierWithCase(.snake, param.name);
|
||||||
|
},
|
||||||
|
.bitflags => {
|
||||||
|
try self.writeIdentifierWithCase(.snake, param.name);
|
||||||
|
try self.writer.writeAll(".toInt()"); // TODO: Generate wrapper
|
||||||
|
},
|
||||||
|
.buffer_len, .mut_buffer_len, .other => {
|
||||||
|
try self.writeIdentifierWithCase(.snake, param.name);
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
try self.writer.writeAll(", ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn extractReturns(self: *Self, command: reg.Command) !reg.Container {
|
||||||
|
var returns = std.ArrayList(reg.Container.Field).init(self.allocator);
|
||||||
|
|
||||||
|
// if (command.return_type.* == .name) {
|
||||||
|
// const return_name = command.return_type.name;
|
||||||
|
// if (!mem.eql(u8, return_name, "void") and !mem.eql(u8, command.return_type.name))
|
||||||
|
// }
|
||||||
|
|
||||||
|
if (command.success_codes.len > 0) {
|
||||||
|
if (command.return_type.* != .name or !mem.eql(u8, command.return_type.name, "VkResult")) {
|
||||||
|
return error.InvalidRegistry;
|
||||||
|
}
|
||||||
|
|
||||||
|
try returns.append(.{
|
||||||
|
.name = "result",
|
||||||
|
.field_type = command.return_type.*,
|
||||||
|
.bits = null,
|
||||||
|
.is_buffer_len = false,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
for (command.params) |param| {
|
||||||
|
if ((try self.classifyParam(param)) == .out_pointer) {
|
||||||
|
try returns.append(.{
|
||||||
|
.name = param.name,
|
||||||
|
.field_type = param.param_type,
|
||||||
|
.bits = null,
|
||||||
|
.is_buffer_len = param.is_buffer_len,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return reg.Container{
|
||||||
|
.fields = returns.toOwnedSlice(),
|
||||||
|
.is_union = false,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
fn renderWrapper(self: *Self, name: []const u8, command: reg.Command) !void {
|
||||||
|
// const returns = try self.extractReturns(command);
|
||||||
|
// const return_struct_name = if (returns.fields.len > 1)
|
||||||
|
// try std.fmt.allocPrint(self.allocator, "{}Result", .{name})
|
||||||
|
// else
|
||||||
|
// null;
|
||||||
|
// defer if (return_struct_name) |rsn| self.sfa.allocator.free(rsn);
|
||||||
|
|
||||||
|
|
||||||
|
// if (self.returns.items.len > 1) {
|
||||||
|
|
||||||
|
// }
|
||||||
|
|
||||||
|
try self.renderWrapperPrototype(name, command);
|
||||||
|
|
||||||
|
// if (command.error_codes.len != 0) {
|
||||||
|
// try self.renderErrorSet(command.error_codes);
|
||||||
|
// try self.writer.writeByte('!');
|
||||||
|
// }
|
||||||
|
|
||||||
|
try self.renderTypeInfo(command.return_type.*);
|
||||||
|
try self.writer.writeAll("{\n");
|
||||||
|
try self.renderWrapperCall(name, command);
|
||||||
|
try self.writer.writeAll(");\n}\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
fn renderErrorSet(self: *Self, errors: []const []const u8) !void {
|
||||||
|
try self.writer.writeAll("error{");
|
||||||
|
for (errors) |name| {
|
||||||
|
self.renderResultAsError(name) catch |err| switch (err) {
|
||||||
|
// Apparently some commands return a non-error code as error code
|
||||||
|
error.NotErrorResult => continue,
|
||||||
|
else => |narrowed| return narrowed
|
||||||
|
};
|
||||||
|
|
||||||
|
try self.writer.writeAll(", ");
|
||||||
|
}
|
||||||
|
try self.writer.writeAll("}");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -555,6 +792,5 @@ fn Renderer(comptime WriterType: type) type {
|
|||||||
pub fn render(writer: var, allocator: *Allocator, registry: *const reg.Registry) !void {
|
pub fn render(writer: var, allocator: *Allocator, registry: *const reg.Registry) !void {
|
||||||
var renderer = Renderer(@TypeOf(writer)).init(writer, allocator, registry);
|
var renderer = Renderer(@TypeOf(writer)).init(writer, allocator, registry);
|
||||||
defer renderer.deinit();
|
defer renderer.deinit();
|
||||||
|
|
||||||
try renderer.render();
|
try renderer.render();
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user