345 lines
13 KiB
Zig
345 lines
13 KiB
Zig
const std = @import("std");
|
|
const patterns = @import("patterns.zig");
|
|
|
|
pub const JsonSerializer = struct {
|
|
allocator: std.mem.Allocator,
|
|
output: std.ArrayList(u8),
|
|
header_name: []const u8,
|
|
opaque_types: std.ArrayList(patterns.OpaqueType),
|
|
typedefs: std.ArrayList(patterns.TypedefDecl),
|
|
function_pointers: std.ArrayList(patterns.FunctionPointerDecl),
|
|
enums: std.ArrayList(patterns.EnumDecl),
|
|
structs: std.ArrayList(patterns.StructDecl),
|
|
unions: std.ArrayList(patterns.UnionDecl),
|
|
flags: std.ArrayList(patterns.FlagDecl),
|
|
functions: std.ArrayList(patterns.FunctionDecl),
|
|
|
|
pub fn init(allocator: std.mem.Allocator, header_name: []const u8) JsonSerializer {
|
|
return .{
|
|
.allocator = allocator,
|
|
.output = .{},
|
|
.header_name = header_name,
|
|
.opaque_types = .{},
|
|
.typedefs = .{},
|
|
.function_pointers = .{},
|
|
.enums = .{},
|
|
.structs = .{},
|
|
.unions = .{},
|
|
.flags = .{},
|
|
.functions = .{},
|
|
};
|
|
}
|
|
|
|
pub fn deinit(self: *JsonSerializer) void {
|
|
self.output.deinit(self.allocator);
|
|
self.opaque_types.deinit(self.allocator);
|
|
self.typedefs.deinit(self.allocator);
|
|
self.function_pointers.deinit(self.allocator);
|
|
self.enums.deinit(self.allocator);
|
|
self.structs.deinit(self.allocator);
|
|
self.unions.deinit(self.allocator);
|
|
self.flags.deinit(self.allocator);
|
|
self.functions.deinit(self.allocator);
|
|
}
|
|
|
|
pub fn addDeclarations(self: *JsonSerializer, decls: []const patterns.Declaration) !void {
|
|
for (decls) |decl| {
|
|
switch (decl) {
|
|
.opaque_type => |o| try self.opaque_types.append(self.allocator, o),
|
|
.typedef_decl => |t| try self.typedefs.append(self.allocator, t),
|
|
.function_pointer_decl => |fp| try self.function_pointers.append(self.allocator, fp),
|
|
.enum_decl => |e| try self.enums.append(self.allocator, e),
|
|
.struct_decl => |s| try self.structs.append(self.allocator, s),
|
|
.union_decl => |u| try self.unions.append(self.allocator, u),
|
|
.flag_decl => |f| try self.flags.append(self.allocator, f),
|
|
.function_decl => |fn_decl| try self.functions.append(self.allocator, fn_decl),
|
|
}
|
|
}
|
|
}
|
|
|
|
pub fn finalize(self: *JsonSerializer) ![]const u8 {
|
|
var writer = self.output.writer(self.allocator);
|
|
|
|
try writer.writeAll("{\n");
|
|
try writer.writeAll(" \"header\": ");
|
|
try self.writeString(writer, self.header_name);
|
|
try writer.writeAll(",\n");
|
|
|
|
// Serialize opaque types
|
|
try writer.writeAll(" \"opaque_types\": [\n");
|
|
for (self.opaque_types.items, 0..) |opaque_type, i| {
|
|
try writer.writeAll(" ");
|
|
try self.serializeOpaqueType(writer, opaque_type);
|
|
if (i < self.opaque_types.items.len - 1) try writer.writeAll(",");
|
|
try writer.writeAll("\n");
|
|
}
|
|
try writer.writeAll(" ],\n");
|
|
|
|
// Serialize typedefs
|
|
try writer.writeAll(" \"typedefs\": [\n");
|
|
for (self.typedefs.items, 0..) |typedef, i| {
|
|
try writer.writeAll(" ");
|
|
try self.serializeTypedef(writer, typedef);
|
|
if (i < self.typedefs.items.len - 1) try writer.writeAll(",");
|
|
try writer.writeAll("\n");
|
|
}
|
|
try writer.writeAll(" ],\n");
|
|
|
|
// Serialize function pointers
|
|
try writer.writeAll(" \"function_pointers\": [\n");
|
|
for (self.function_pointers.items, 0..) |fp, i| {
|
|
try writer.writeAll(" ");
|
|
try self.serializeFunctionPointer(writer, fp);
|
|
if (i < self.function_pointers.items.len - 1) try writer.writeAll(",");
|
|
try writer.writeAll("\n");
|
|
}
|
|
try writer.writeAll(" ],\n");
|
|
|
|
// Serialize enums
|
|
try writer.writeAll(" \"enums\": [\n");
|
|
for (self.enums.items, 0..) |enum_decl, i| {
|
|
try writer.writeAll(" ");
|
|
try self.serializeEnum(writer, enum_decl);
|
|
if (i < self.enums.items.len - 1) try writer.writeAll(",");
|
|
try writer.writeAll("\n");
|
|
}
|
|
try writer.writeAll(" ],\n");
|
|
|
|
// Serialize structs
|
|
try writer.writeAll(" \"structs\": [\n");
|
|
for (self.structs.items, 0..) |struct_decl, i| {
|
|
try writer.writeAll(" ");
|
|
try self.serializeStruct(writer, struct_decl);
|
|
if (i < self.structs.items.len - 1) try writer.writeAll(",");
|
|
try writer.writeAll("\n");
|
|
}
|
|
try writer.writeAll(" ],\n");
|
|
|
|
// Serialize unions
|
|
try writer.writeAll(" \"unions\": [\n");
|
|
for (self.unions.items, 0..) |union_decl, i| {
|
|
try writer.writeAll(" ");
|
|
try self.serializeUnion(writer, union_decl);
|
|
if (i < self.unions.items.len - 1) try writer.writeAll(",");
|
|
try writer.writeAll("\n");
|
|
}
|
|
try writer.writeAll(" ],\n");
|
|
|
|
// Serialize flags
|
|
try writer.writeAll(" \"flags\": [\n");
|
|
for (self.flags.items, 0..) |flag, i| {
|
|
try writer.writeAll(" ");
|
|
try self.serializeFlag(writer, flag);
|
|
if (i < self.flags.items.len - 1) try writer.writeAll(",");
|
|
try writer.writeAll("\n");
|
|
}
|
|
try writer.writeAll(" ],\n");
|
|
|
|
// Serialize functions
|
|
try writer.writeAll(" \"functions\": [\n");
|
|
for (self.functions.items, 0..) |func, i| {
|
|
try writer.writeAll(" ");
|
|
try self.serializeFunction(writer, func);
|
|
if (i < self.functions.items.len - 1) try writer.writeAll(",");
|
|
try writer.writeAll("\n");
|
|
}
|
|
try writer.writeAll(" ]\n");
|
|
|
|
try writer.writeAll("}\n");
|
|
|
|
return self.output.items;
|
|
}
|
|
|
|
fn serializeOpaqueType(self: *JsonSerializer, writer: anytype, opaque_type: patterns.OpaqueType) !void {
|
|
try writer.writeAll("{\"name\": ");
|
|
try self.writeString(writer, opaque_type.name);
|
|
if (opaque_type.doc_comment) |doc| {
|
|
try writer.writeAll(", \"doc\": ");
|
|
try self.writeString(writer, doc);
|
|
}
|
|
try writer.writeAll("}");
|
|
}
|
|
|
|
fn serializeTypedef(self: *JsonSerializer, writer: anytype, typedef: patterns.TypedefDecl) !void {
|
|
try writer.writeAll("{\"name\": ");
|
|
try self.writeString(writer, typedef.name);
|
|
try writer.writeAll(", \"underlying_type\": ");
|
|
try self.writeString(writer, typedef.underlying_type);
|
|
if (typedef.doc_comment) |doc| {
|
|
try writer.writeAll(", \"doc\": ");
|
|
try self.writeString(writer, doc);
|
|
}
|
|
try writer.writeAll("}");
|
|
}
|
|
|
|
fn serializeFunctionPointer(self: *JsonSerializer, writer: anytype, fp: patterns.FunctionPointerDecl) !void {
|
|
try writer.writeAll("{\"name\": ");
|
|
try self.writeString(writer, fp.name);
|
|
try writer.writeAll(", \"return_type\": ");
|
|
try self.writeString(writer, fp.return_type);
|
|
try writer.writeAll(", \"parameters\": [");
|
|
for (fp.params, 0..) |param, i| {
|
|
try writer.writeAll("{\"name\": ");
|
|
try self.writeString(writer, param.name);
|
|
try writer.writeAll(", \"type\": ");
|
|
try self.writeString(writer, param.type_name);
|
|
try writer.writeAll("}");
|
|
if (i < fp.params.len - 1) try writer.writeAll(", ");
|
|
}
|
|
try writer.writeAll("]");
|
|
if (fp.doc_comment) |doc| {
|
|
try writer.writeAll(", \"doc\": ");
|
|
try self.writeString(writer, doc);
|
|
}
|
|
try writer.writeAll("}");
|
|
}
|
|
|
|
fn serializeEnum(self: *JsonSerializer, writer: anytype, enum_decl: patterns.EnumDecl) !void {
|
|
try writer.writeAll("{\"name\": ");
|
|
try self.writeString(writer, enum_decl.name);
|
|
try writer.writeAll(", \"values\": [");
|
|
|
|
for (enum_decl.values, 0..) |value, i| {
|
|
try writer.writeAll("{\"name\": ");
|
|
try self.writeString(writer, value.name);
|
|
if (value.value) |val| {
|
|
try writer.writeAll(", \"value\": ");
|
|
try self.writeString(writer, val);
|
|
}
|
|
if (value.comment) |comment| {
|
|
try writer.writeAll(", \"comment\": ");
|
|
try self.writeString(writer, comment);
|
|
}
|
|
try writer.writeAll("}");
|
|
if (i < enum_decl.values.len - 1) try writer.writeAll(", ");
|
|
}
|
|
|
|
try writer.writeAll("]");
|
|
if (enum_decl.doc_comment) |doc| {
|
|
try writer.writeAll(", \"doc\": ");
|
|
try self.writeString(writer, doc);
|
|
}
|
|
try writer.writeAll("}");
|
|
}
|
|
|
|
fn serializeStruct(self: *JsonSerializer, writer: anytype, struct_decl: patterns.StructDecl) !void {
|
|
try writer.writeAll("{\"name\": ");
|
|
try self.writeString(writer, struct_decl.name);
|
|
try writer.writeAll(", \"fields\": [");
|
|
|
|
for (struct_decl.fields, 0..) |field, i| {
|
|
try writer.writeAll("{\"name\": ");
|
|
try self.writeString(writer, field.name);
|
|
try writer.writeAll(", \"type\": ");
|
|
try self.writeString(writer, field.type_name);
|
|
if (field.comment) |comment| {
|
|
try writer.writeAll(", \"comment\": ");
|
|
try self.writeString(writer, comment);
|
|
}
|
|
try writer.writeAll("}");
|
|
if (i < struct_decl.fields.len - 1) try writer.writeAll(", ");
|
|
}
|
|
|
|
try writer.writeAll("]");
|
|
if (struct_decl.doc_comment) |doc| {
|
|
try writer.writeAll(", \"doc\": ");
|
|
try self.writeString(writer, doc);
|
|
}
|
|
try writer.writeAll("}");
|
|
}
|
|
|
|
fn serializeUnion(self: *JsonSerializer, writer: anytype, union_decl: patterns.UnionDecl) !void {
|
|
try writer.writeAll("{\"name\": ");
|
|
try self.writeString(writer, union_decl.name);
|
|
try writer.writeAll(", \"fields\": [");
|
|
|
|
for (union_decl.fields, 0..) |field, i| {
|
|
try writer.writeAll("{\"name\": ");
|
|
try self.writeString(writer, field.name);
|
|
try writer.writeAll(", \"type\": ");
|
|
try self.writeString(writer, field.type_name);
|
|
if (field.comment) |comment| {
|
|
try writer.writeAll(", \"comment\": ");
|
|
try self.writeString(writer, comment);
|
|
}
|
|
try writer.writeAll("}");
|
|
if (i < union_decl.fields.len - 1) try writer.writeAll(", ");
|
|
}
|
|
|
|
try writer.writeAll("]");
|
|
if (union_decl.doc_comment) |doc| {
|
|
try writer.writeAll(", \"doc\": ");
|
|
try self.writeString(writer, doc);
|
|
}
|
|
try writer.writeAll("}");
|
|
}
|
|
|
|
fn serializeFlag(self: *JsonSerializer, writer: anytype, flag: patterns.FlagDecl) !void {
|
|
try writer.writeAll("{\"name\": ");
|
|
try self.writeString(writer, flag.name);
|
|
try writer.writeAll(", \"underlying_type\": ");
|
|
try self.writeString(writer, flag.underlying_type);
|
|
try writer.writeAll(", \"values\": [");
|
|
|
|
for (flag.flags, 0..) |value, i| {
|
|
try writer.writeAll("{\"name\": ");
|
|
try self.writeString(writer, value.name);
|
|
try writer.writeAll(", \"value\": ");
|
|
try self.writeString(writer, value.value);
|
|
if (value.comment) |comment| {
|
|
try writer.writeAll(", \"comment\": ");
|
|
try self.writeString(writer, comment);
|
|
}
|
|
try writer.writeAll("}");
|
|
if (i < flag.flags.len - 1) try writer.writeAll(", ");
|
|
}
|
|
|
|
try writer.writeAll("]");
|
|
if (flag.doc_comment) |doc| {
|
|
try writer.writeAll(", \"doc\": ");
|
|
try self.writeString(writer, doc);
|
|
}
|
|
try writer.writeAll("}");
|
|
}
|
|
|
|
fn serializeFunction(self: *JsonSerializer, writer: anytype, func: patterns.FunctionDecl) !void {
|
|
try writer.writeAll("{\"name\": ");
|
|
try self.writeString(writer, func.name);
|
|
try writer.writeAll(", \"return_type\": ");
|
|
try self.writeString(writer, func.return_type);
|
|
try writer.writeAll(", \"parameters\": [");
|
|
|
|
for (func.params, 0..) |param, i| {
|
|
try writer.writeAll("{\"name\": ");
|
|
try self.writeString(writer, param.name);
|
|
try writer.writeAll(", \"type\": ");
|
|
try self.writeString(writer, param.type_name);
|
|
try writer.writeAll("}");
|
|
if (i < func.params.len - 1) try writer.writeAll(", ");
|
|
}
|
|
|
|
try writer.writeAll("]");
|
|
if (func.doc_comment) |doc| {
|
|
try writer.writeAll(", \"doc\": ");
|
|
try self.writeString(writer, doc);
|
|
}
|
|
try writer.writeAll("}");
|
|
}
|
|
|
|
fn writeString(self: *JsonSerializer, writer: anytype, str: []const u8) !void {
|
|
_ = self;
|
|
try writer.writeAll("\"");
|
|
for (str) |c| {
|
|
switch (c) {
|
|
'"' => try writer.writeAll("\\\""),
|
|
'\\' => try writer.writeAll("\\\\"),
|
|
'\n' => try writer.writeAll("\\n"),
|
|
'\r' => try writer.writeAll("\\r"),
|
|
'\t' => try writer.writeAll("\\t"),
|
|
else => try writer.writeByte(c),
|
|
}
|
|
}
|
|
try writer.writeAll("\"");
|
|
}
|
|
};
|