aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnhgelus Morhtuuzh <william@herges.fr>2026-04-19 14:02:37 +0200
committerAnhgelus Morhtuuzh <william@herges.fr>2026-04-19 14:02:37 +0200
commitd1480f97e3c8ce82151d409e7c9d1545d44f3a99 (patch)
tree08337cb10e5c3fb6ddd820b0f117f33a20fb4328
parent8c5214df39ab82c3d42ccd492d8699f8a5aadb0a (diff)
feat(lib): export functions
-rw-r--r--build.zig3
-rw-r--r--src/root.zig83
2 files changed, 76 insertions, 10 deletions
diff --git a/build.zig b/build.zig
index d7721ed..5e82cec 100644
--- a/build.zig
+++ b/build.zig
@@ -7,6 +7,7 @@ pub fn build(b: *std.Build) void {
const mod = b.addModule("typdown", .{
.root_source_file = b.path("src/root.zig"),
.target = target,
+ .link_libc = true,
});
//const exe = b.addExecutable(.{
@@ -30,7 +31,7 @@ pub fn build(b: *std.Build) void {
//if (b.args) |args| {
// run_cmd.addArgs(args);
//}
-
+
const mod_tests = b.addTest(.{
.root_module = mod,
});
diff --git a/src/root.zig b/src/root.zig
index 2bc3125..bd183ff 100644
--- a/src/root.zig
+++ b/src/root.zig
@@ -1,19 +1,84 @@
const std = @import("std");
pub const parser = @import("parser.zig");
+pub const Error = parser.Error;
-pub fn bufferedPrint() !void {
- // Stdout is for the actual output of your application, for example if you
- // are implementing gzip, then only the compressed bytes should be sent to
- // stdout, not any debugging messages.
- var stdout_buffer: [1024]u8 = undefined;
- var stdout_writer = std.fs.File.stdout().writer(&stdout_buffer);
- const stdout = &stdout_writer.interface;
+fn getErrorCode(err: Error) u8 {
+ return switch (err) {
+ Error.OutOfMemory => 1,
+ Error.InvalidUtf8 => 2,
+ Error.FeatureNotSupported => 3,
+ Error.ModifierNotClosed => 4,
+ Error.InvalidTitleContent => 5,
+ };
+}
- try stdout.print("Run `zig build test` to run the tests.\n", .{});
+/// Returns the static string linked with the error code.
+export fn getErrorString(code: u8) [*:0]const u8 {
+ return switch (code) {
+ 1 => "out of memory",
+ 2 => "invalid UTF-8",
+ 3 => "feature not supported",
+ 4 => "modifier not closed",
+ 5 => "invalid title content",
+ else => unreachable,
+ };
+}
- try stdout.flush(); // Don't forget to flush!
+/// Parse the content.
+/// Code is a pointer to an u8 populated with an error code > 0.
+///
+/// Returns a not null strings and set the code to 0 if everything is fine.
+/// Else, it returns null and set an error code above 0.
+/// Use getErrorString to retrieve the string linked with the error code.
+export fn parse(content: [*:0]const u8, code: *u8) ?[*:0]const u8 {
+ const alloc = std.heap.c_allocator;
+ const res = parser.parse(alloc, std.mem.span(content)) catch |err| {
+ code.* = getErrorCode(err);
+ return null;
+ };
+ defer alloc.free(res);
+ code.* = 0;
+ return alloc.dupeZ(u8, res) catch |err| {
+ code.* = getErrorCode(err);
+ return null;
+ };
}
test {
std.testing.refAllDeclsRecursive(@This());
}
+
+fn doTest(content: [*:0]const u8, exp: []const u8, exp_code: u8) !void {
+ const expect = std.testing.expect;
+
+ var code: u8 = undefined;
+ const raw = parse(content, &code) orelse {
+ expect(code == exp_code) catch |err| {
+ std.debug.print("{}\n", .{code});
+ return err;
+ };
+ return;
+ };
+ const res = std.mem.span(raw);
+ defer std.heap.c_allocator.free(res);
+
+ expect(code == 0) catch |err| {
+ std.debug.print("{}\n", .{code});
+ return err;
+ };
+ expect(std.mem.eql(u8, exp, res)) catch |err| {
+ std.debug.print("{s}\n", .{res});
+ return err;
+ };
+}
+
+test "exported parse" {
+ // valid
+ try doTest("hello world", "<p>hello world</p>", 0);
+ try doTest("he*ll*o world", "<p>he<b>ll</b>o world</p>", 0);
+ try doTest("# title", "<h1>title</h1>", 0);
+
+ // invalid
+ try doTest("he*llo world", "", getErrorCode(Error.ModifierNotClosed));
+ try doTest("# title :::", "", getErrorCode(Error.InvalidTitleContent));
+}