aboutsummaryrefslogtreecommitdiff
path: root/src/root.zig
diff options
context:
space:
mode:
Diffstat (limited to 'src/root.zig')
-rw-r--r--src/root.zig86
1 files changed, 57 insertions, 29 deletions
diff --git a/src/root.zig b/src/root.zig
index 3a7c134..30386e9 100644
--- a/src/root.zig
+++ b/src/root.zig
@@ -2,12 +2,14 @@ const std = @import("std");
const builtin = @import("builtin");
const Allocator = std.mem.Allocator;
const parser = @import("parser.zig");
+const Element = @import("eval/Element.zig");
pub const Document = parser.Document;
pub const Error = parser.Error;
/// Parse the content.
///
/// Use typdown_parse if you are not in Zig.
pub const parse = parser.parse;
+pub const parseReader = parser.parseReader;
inline fn getErrorCode(err: Error) u8 {
return switch (err) {
@@ -43,6 +45,40 @@ export fn typdown_getErrorString(code: u8) [*:0]const u8 {
};
}
+/// typdown_Document is a Document for the C ABI.
+const typdown_Document = extern struct {
+ root: ?*anyopaque = null,
+ errors: ?[*]typdown_Error = null,
+ errors_len: usize = 0,
+
+ const typdown_Error = extern struct {
+ code: u8,
+ location: extern struct { beg: usize, end: usize },
+ };
+};
+
+fn from(alloc: Allocator, doc: Document) typdown_Document {
+ var res = typdown_Document{ .root = doc.root };
+ if (doc.errors) |errors| {
+ defer alloc.free(errors);
+ res.errors = (alloc.alloc(typdown_Document.typdown_Error, errors.len) catch |err| @panic(@errorName(err))).ptr;
+ for (errors) |err| {
+ res.errors.?[0] = .{
+ .code = getErrorCode(err.err),
+ .location = .{ .beg = err.location.beg, .end = err.location.end },
+ };
+ }
+ res.errors_len = errors.len;
+ }
+ return res;
+}
+
+fn fromError(alloc: Allocator, err: Error) typdown_Document {
+ var v = alloc.alloc(typdown_Document.typdown_Error, 1) catch |e| @panic(@errorName(e));
+ v[0] = .{ .code = getErrorCode(err), .location = .{ .beg = 0, .end = 0 } };
+ return .{ .errors = v.ptr, .errors_len = 1 };
+}
+
var default_alloc: std.mem.Allocator =
if (builtin.target.isWasiLibC())
std.heap.wasm_allocator
@@ -52,31 +88,29 @@ var default_alloc: std.mem.Allocator =
std.heap.c_allocator;
/// Parse the content.
-/// Code is a pointer to an u8 populated with an error code > 0.
-///
-/// Returns a non-null void pointer containing the document and set the code to 0 if everything is fine.
-/// Else, it returns null and set an error code above 0.
-/// Use typdown_getErrorString to retrieve the string linked with the error code.
-/// Use parse if you are in Zig.
///
/// You must free the document with typdown_free.
-export fn typdown_parse(content: [*:0]const u8, code: *u8) ?*anyopaque {
- return parse(default_alloc, std.mem.span(content)) catch |err| {
- code.* = getErrorCode(err);
- return null;
- };
+export fn typdown_parse(content: [*:0]const u8) typdown_Document {
+ const alloc = default_alloc;
+ return from(alloc, parse(alloc, std.mem.span(content)) catch |err| {
+ return fromError(alloc, err);
+ });
}
/// Free the document.
-export fn typdown_free(document: *anyopaque) void {
- const doc: *Document = @ptrCast(@alignCast(document));
- doc.deinit();
+export fn typdown_free(self: typdown_Document) void {
+ const alloc = default_alloc;
+ if (self.root) |r| {
+ const root: *Element.Root = @ptrCast(@alignCast(r));
+ root.deinit();
+ }
+ if (self.errors) |errors| alloc.free(errors[0..self.errors_len]);
}
/// Render an HTML from the document.
-export fn typdown_renderHTML(document: *anyopaque, code: *u8) ?[*:0]const u8 {
- const doc: *Document = @ptrCast(@alignCast(document));
- const res = doc.renderHTML(default_alloc) catch |err| {
+export fn typdown_renderHTML(document: typdown_Document, code: *u8) ?[*:0]const u8 {
+ const root: *Element.Root = @ptrCast(@alignCast(document.root));
+ const res = root.renderHTML(default_alloc) catch |err| {
code.* = getErrorCode(err);
return null;
};
@@ -88,10 +122,6 @@ export fn typdown_renderHTML(document: *anyopaque, code: *u8) ?[*:0]const u8 {
};
}
-pub fn parseReader(alloc: std.mem.Allocator, r: *std.io.Reader) (Error || std.io.Reader.Error)!*Document {
- return parser.parseReader(alloc, r);
-}
-
test {
std.testing.refAllDeclsRecursive(@This());
}
@@ -99,15 +129,13 @@ test {
fn doTest(content: [*:0]const u8, exp: []const u8, comptime exp_code: u8) !void {
const expect = std.testing.expect;
- var code: u8 = undefined;
- const doc = typdown_parse(content, &code) orelse {
- expect(code == exp_code) catch |err| {
- std.debug.print("{}\n", .{code});
- return err;
- };
- return;
- };
+ const doc = typdown_parse(content);
defer typdown_free(doc);
+ if (doc.errors) |errors| {
+ for (0..doc.errors_len) |i| if (errors[i].code == exp_code) return;
+ return try expect(false);
+ }
+ var code: u8 = undefined;
const raw = typdown_renderHTML(doc, &code) orelse {
expect(code == exp_code) catch |err| {
std.debug.print("{}\n", .{code});