From f3f9aa31dc86582ed1a7ddc64bdeebeb213add7a Mon Sep 17 00:00:00 2001 From: Anhgelus Morhtuuzh Date: Mon, 4 May 2026 17:17:32 +0200 Subject: feat(go): update bindings --- examples/main.c | 2 +- go/typdown.go | 65 ++++++++++++++++++++++++++++++++++++++++++------------- include/typdown.h | 2 +- src/root.zig | 6 ++--- 4 files changed, 55 insertions(+), 20 deletions(-) diff --git a/examples/main.c b/examples/main.c index 2b3c3ca..6ab775f 100644 --- a/examples/main.c +++ b/examples/main.c @@ -18,7 +18,7 @@ void foo(char *v) { return; } uint8_t code; - char *res = typdown_renderHTML(doc, &code); + char *res = typdown_renderHTML(doc.root, &code); if (code != 0) { printf("cannot render '%s', error: %s (%d)\n", v, typdown_getErrorString(code), code); typdown_free(doc); diff --git a/go/typdown.go b/go/typdown.go index d93d4ca..5e784b4 100644 --- a/go/typdown.go +++ b/go/typdown.go @@ -1,11 +1,16 @@ package typdown -// #cgo LDFLAGS: -L${SRCDIR}/zig-out/lib -ltypdown -// #include -// #include "typdown.h" +/* +#cgo LDFLAGS: -L${SRCDIR}/zig-out/lib -ltypdown +#include +#include "typdown.h" + +typedef struct typdown_Document Document; +*/ import "C" import ( "errors" + "fmt" "html/template" "unsafe" ) @@ -36,32 +41,62 @@ var ( ErrInvalidMathBlock = errors.New("invalid math block") ) +type Error struct { + code uint8 + source *string + location ErrorLocation +} + +func (e Error) Unwrap() error { + return codeErrors[uint8(e.code)] +} + +func (e Error) Error() string { + loc := e.location + return fmt.Sprintf("%s: %s (line %d)", e.Unwrap().Error(), loc.source, loc.line) +} + +func (e Error) Is(err error) bool { + return errors.Is(e.Unwrap(), err) +} + +type ErrorLocation struct { + source string + line uint +} + type Document struct { - ptr unsafe.Pointer + Errors []Error + embed C.Document } -func Parse(content string) (*Document, error) { - code := C.uchar(0) +func Parse(content string) Document { conv := C.CString(content) - raw := C.typdown_parse(conv, &code) defer C.free(unsafe.Pointer(conv)) - if code > 0 { - err := codeErrors[uint8(code)] - if code == 1 { - panic(err) + rawDoc := C.typdown_parse(conv) + doc := Document{embed: rawDoc} + if rawDoc.errors_len > 0 { + doc.Errors = make([]Error, rawDoc.errors_len) + errs := unsafe.Slice(rawDoc.errors, rawDoc.errors_len) + for i := range rawDoc.errors_len { + raw := errs[i] + doc.Errors[i] = Error{ + code: uint8(raw.code), + source: &content, + location: ErrorLocation{source: content[raw.location.beg:raw.location.end], line: uint(raw.location.line)}, + } } - return nil, err } - return &Document{raw}, nil + return doc } func (d *Document) Close() { - C.typdown_free(d.ptr) + C.typdown_free(d.embed) } func (d *Document) RenderHTML() (template.HTML, error) { code := C.uchar(0) - raw := C.typdown_renderHTML(d.ptr, &code) + raw := C.typdown_renderHTML(d.embed.root, &code) defer C.free(unsafe.Pointer(raw)) if code > 0 { err := codeErrors[uint8(code)] diff --git a/include/typdown.h b/include/typdown.h index e9d7f19..0e954d4 100644 --- a/include/typdown.h +++ b/include/typdown.h @@ -17,4 +17,4 @@ char * typdown_getErrorString(uint8_t); struct typdown_Document typdown_parse(char *); void typdown_free(struct typdown_Document); -char * typdown_renderHTML(struct typdown_Document, uint8_t *); +char * typdown_renderHTML(void *, uint8_t *); diff --git a/src/root.zig b/src/root.zig index cef8519..5d8125f 100644 --- a/src/root.zig +++ b/src/root.zig @@ -108,8 +108,8 @@ export fn typdown_free(self: typdown_Document) void { } /// Render an HTML from the document. -export fn typdown_renderHTML(document: typdown_Document, code: *u8) ?[*:0]const u8 { - const root: *Element.Root = @ptrCast(@alignCast(document.root)); +export fn typdown_renderHTML(context: *anyopaque, code: *u8) ?[*:0]const u8 { + const root: *Element.Root = @ptrCast(@alignCast(context)); const res = root.renderHTML(default_alloc) catch |err| { code.* = getErrorCode(err); return null; @@ -136,7 +136,7 @@ fn doTest(content: [*:0]const u8, exp: []const u8, comptime exp_code: u8) !void return try expect(false); } var code: u8 = undefined; - const raw = typdown_renderHTML(doc, &code) orelse { + const raw = typdown_renderHTML(doc.root, &code) orelse { expect(code == exp_code) catch |err| { std.debug.print("{}\n", .{code}); return err; -- cgit v1.2.3