1988 lines
50 KiB
Go
1988 lines
50 KiB
Go
|
|
// This file is auto-generated by alef — DO NOT EDIT.
|
||
|
|
// alef:hash:4e15143f4af1ae8bafbdb1506ef057da924484c66a19483966333558ad437e75
|
||
|
|
// To regenerate: alef generate
|
||
|
|
// To verify freshness: alef verify --exit-code
|
||
|
|
// Issues & docs: https://github.com/kreuzberg-dev/alef
|
||
|
|
package kreuzberg
|
||
|
|
|
||
|
|
/*
|
||
|
|
#cgo CFLAGS: -I${SRCDIR}/include
|
||
|
|
#include "kreuzberg.h"
|
||
|
|
#include <stdlib.h>
|
||
|
|
#include <string.h>
|
||
|
|
|
||
|
|
extern int32_t goOcrBackendProcessImage(void* user_data, uint8_t* image_bytes, size_t image_bytes_len, char* config, char** out_result, char** out_error);
|
||
|
|
extern int32_t goOcrBackendProcessImageFile(void* user_data, char* path, char* config, char** out_result, char** out_error);
|
||
|
|
extern int32_t goOcrBackendSupportsLanguage(void* user_data, char* lang, char** out_result, char** out_error);
|
||
|
|
extern int32_t goOcrBackendBackendType(void* user_data, char** out_result, char** out_error);
|
||
|
|
extern int32_t goOcrBackendSupportedLanguages(void* user_data, char** out_result, char** out_error);
|
||
|
|
extern int32_t goOcrBackendSupportsTableDetection(void* user_data, char** out_result, char** out_error);
|
||
|
|
extern int32_t goOcrBackendSupportsDocumentProcessing(void* user_data, char** out_result, char** out_error);
|
||
|
|
extern int32_t goOcrBackendProcessDocument(void* user_data, char* _path, char* _config, char** out_result, char** out_error);
|
||
|
|
extern int32_t goOcrBackendName(void*, char**, char**);
|
||
|
|
extern int32_t goOcrBackendVersion(void*, char**, char**);
|
||
|
|
extern int32_t goOcrBackendInitialize(void*, char**);
|
||
|
|
extern int32_t goOcrBackendShutdown(void*, char**);
|
||
|
|
extern void goOcrBackendFreeUserData(void*);
|
||
|
|
extern void goOcrBackendFreeString(char*);
|
||
|
|
extern int32_t goPostProcessorProcess(void* user_data, char* result, char* config, char** out_error);
|
||
|
|
extern int32_t goPostProcessorProcessingStage(void* user_data, char** out_result, char** out_error);
|
||
|
|
extern int32_t goPostProcessorShouldProcess(void* user_data, char* _result, char* _config, char** out_result, char** out_error);
|
||
|
|
extern int32_t goPostProcessorEstimatedDurationMs(void* user_data, char* _result, char** out_result, char** out_error);
|
||
|
|
extern int32_t goPostProcessorPriority(void* user_data, char** out_result, char** out_error);
|
||
|
|
extern int32_t goPostProcessorName(void*, char**, char**);
|
||
|
|
extern int32_t goPostProcessorVersion(void*, char**, char**);
|
||
|
|
extern int32_t goPostProcessorInitialize(void*, char**);
|
||
|
|
extern int32_t goPostProcessorShutdown(void*, char**);
|
||
|
|
extern void goPostProcessorFreeUserData(void*);
|
||
|
|
extern void goPostProcessorFreeString(char*);
|
||
|
|
extern int32_t goValidatorValidate(void* user_data, char* result, char* config, char** out_error);
|
||
|
|
extern int32_t goValidatorShouldValidate(void* user_data, char* _result, char* _config, char** out_result, char** out_error);
|
||
|
|
extern int32_t goValidatorPriority(void* user_data, char** out_result, char** out_error);
|
||
|
|
extern int32_t goValidatorName(void*, char**, char**);
|
||
|
|
extern int32_t goValidatorVersion(void*, char**, char**);
|
||
|
|
extern int32_t goValidatorInitialize(void*, char**);
|
||
|
|
extern int32_t goValidatorShutdown(void*, char**);
|
||
|
|
extern void goValidatorFreeUserData(void*);
|
||
|
|
extern void goValidatorFreeString(char*);
|
||
|
|
extern int32_t goEmbeddingBackendDimensions(void* user_data, char** out_result, char** out_error);
|
||
|
|
extern int32_t goEmbeddingBackendEmbed(void* user_data, char* texts, char** out_result, char** out_error);
|
||
|
|
extern int32_t goEmbeddingBackendName(void*, char**, char**);
|
||
|
|
extern int32_t goEmbeddingBackendVersion(void*, char**, char**);
|
||
|
|
extern int32_t goEmbeddingBackendInitialize(void*, char**);
|
||
|
|
extern int32_t goEmbeddingBackendShutdown(void*, char**);
|
||
|
|
extern void goEmbeddingBackendFreeUserData(void*);
|
||
|
|
extern void goEmbeddingBackendFreeString(char*);
|
||
|
|
extern int32_t goDocumentExtractorExtractBytes(void* user_data, uint8_t* content, size_t content_len, char* mime_type, char* config, char** out_result, char** out_error);
|
||
|
|
extern int32_t goDocumentExtractorExtractFile(void* user_data, char* path, char* mime_type, char* config, char** out_result, char** out_error);
|
||
|
|
extern int32_t goDocumentExtractorSupportedMimeTypes(void* user_data, char** out_result, char** out_error);
|
||
|
|
extern int32_t goDocumentExtractorPriority(void* user_data, char** out_result, char** out_error);
|
||
|
|
extern int32_t goDocumentExtractorCanHandle(void* user_data, char* _path, char* _mime_type, char** out_result, char** out_error);
|
||
|
|
extern int32_t goDocumentExtractorName(void*, char**, char**);
|
||
|
|
extern int32_t goDocumentExtractorVersion(void*, char**, char**);
|
||
|
|
extern int32_t goDocumentExtractorInitialize(void*, char**);
|
||
|
|
extern int32_t goDocumentExtractorShutdown(void*, char**);
|
||
|
|
extern void goDocumentExtractorFreeUserData(void*);
|
||
|
|
extern void goDocumentExtractorFreeString(char*);
|
||
|
|
extern int32_t goRendererRender(void* user_data, char* doc, char** out_result, char** out_error);
|
||
|
|
extern int32_t goRendererName(void*, char**, char**);
|
||
|
|
extern int32_t goRendererVersion(void*, char**, char**);
|
||
|
|
extern int32_t goRendererInitialize(void*, char**);
|
||
|
|
extern int32_t goRendererShutdown(void*, char**);
|
||
|
|
extern void goRendererFreeUserData(void*);
|
||
|
|
extern void goRendererFreeString(char*);
|
||
|
|
*/
|
||
|
|
import "C"
|
||
|
|
|
||
|
|
import (
|
||
|
|
"encoding/json"
|
||
|
|
"fmt"
|
||
|
|
"runtime/cgo"
|
||
|
|
"sync"
|
||
|
|
"unsafe"
|
||
|
|
)
|
||
|
|
|
||
|
|
// handleRegistry tracks cgo.Handles by name to ensure proper cleanup on unregister.
|
||
|
|
// Without this, unregistered plugins can cause use-after-free crashes when Rust
|
||
|
|
// still holds vtable pointers and tries to invoke callbacks on deleted handles.
|
||
|
|
type handleRegistry struct {
|
||
|
|
mu sync.Mutex
|
||
|
|
handles map[string]cgo.Handle
|
||
|
|
}
|
||
|
|
|
||
|
|
var (
|
||
|
|
ocr_backendRegistry = &handleRegistry{handles: make(map[string]cgo.Handle)}
|
||
|
|
post_processorRegistry = &handleRegistry{handles: make(map[string]cgo.Handle)}
|
||
|
|
validatorRegistry = &handleRegistry{handles: make(map[string]cgo.Handle)}
|
||
|
|
embedding_backendRegistry = &handleRegistry{handles: make(map[string]cgo.Handle)}
|
||
|
|
document_extractorRegistry = &handleRegistry{handles: make(map[string]cgo.Handle)}
|
||
|
|
rendererRegistry = &handleRegistry{handles: make(map[string]cgo.Handle)}
|
||
|
|
)
|
||
|
|
|
||
|
|
// store adds a handle to the registry, keyed by name.
|
||
|
|
func (reg *handleRegistry) store(name string, handle cgo.Handle) {
|
||
|
|
reg.mu.Lock()
|
||
|
|
defer reg.mu.Unlock()
|
||
|
|
if old, ok := reg.handles[name]; ok {
|
||
|
|
old.Delete()
|
||
|
|
}
|
||
|
|
reg.handles[name] = handle
|
||
|
|
}
|
||
|
|
|
||
|
|
// delete removes and deletes a handle from the registry by name.
|
||
|
|
func (reg *handleRegistry) delete(name string) {
|
||
|
|
reg.mu.Lock()
|
||
|
|
defer reg.mu.Unlock()
|
||
|
|
if handle, ok := reg.handles[name]; ok {
|
||
|
|
delete(reg.handles, name)
|
||
|
|
handle.Delete()
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// clear removes and deletes all handles from the registry.
|
||
|
|
func (reg *handleRegistry) clear() {
|
||
|
|
reg.mu.Lock()
|
||
|
|
defer reg.mu.Unlock()
|
||
|
|
for _, handle := range reg.handles {
|
||
|
|
handle.Delete()
|
||
|
|
}
|
||
|
|
reg.handles = make(map[string]cgo.Handle)
|
||
|
|
}
|
||
|
|
|
||
|
|
// OcrBackend defines the Go interface for the OcrBackend trait.
|
||
|
|
type OcrBackend interface {
|
||
|
|
// Name returns the plugin name.
|
||
|
|
Name() string
|
||
|
|
// Version returns the plugin version.
|
||
|
|
Version() string
|
||
|
|
// Initialize is called when the plugin is loaded.
|
||
|
|
Initialize() error
|
||
|
|
// Shutdown is called when the plugin is unloaded.
|
||
|
|
Shutdown() error
|
||
|
|
// process_image
|
||
|
|
ProcessImage(image_bytes []byte, config OcrConfig) (ExtractionResult, error)
|
||
|
|
|
||
|
|
// process_image_file
|
||
|
|
ProcessImageFile(path string, config OcrConfig) (ExtractionResult, error)
|
||
|
|
|
||
|
|
// supports_language
|
||
|
|
SupportsLanguage(lang string) bool
|
||
|
|
|
||
|
|
// backend_type
|
||
|
|
BackendType() OcrBackendType
|
||
|
|
|
||
|
|
// supported_languages
|
||
|
|
SupportedLanguages() []string
|
||
|
|
|
||
|
|
// supports_table_detection
|
||
|
|
SupportsTableDetection() bool
|
||
|
|
|
||
|
|
// supports_document_processing
|
||
|
|
SupportsDocumentProcessing() bool
|
||
|
|
|
||
|
|
// process_document
|
||
|
|
ProcessDocument(_path string, _config OcrConfig) (ExtractionResult, error)
|
||
|
|
|
||
|
|
}
|
||
|
|
|
||
|
|
//export goOcrBackendProcessImage
|
||
|
|
func goOcrBackendProcessImage(
|
||
|
|
userData unsafe.Pointer,
|
||
|
|
image_bytes *C.uint8_t,
|
||
|
|
image_bytesLen C.size_t,
|
||
|
|
config *C.char,
|
||
|
|
outResult **C.char,
|
||
|
|
outError **C.char,
|
||
|
|
) C.int32_t {
|
||
|
|
|
||
|
|
handle := cgo.Handle(uintptr(unsafe.Pointer(userData)))
|
||
|
|
impl, ok := handle.Value().(OcrBackend)
|
||
|
|
|
||
|
|
if !ok {
|
||
|
|
return 1 // error: invalid handle
|
||
|
|
}
|
||
|
|
|
||
|
|
var goImage_bytes []byte
|
||
|
|
if image_bytes != nil {
|
||
|
|
goImage_bytes = unsafe.Slice((*byte)(unsafe.Pointer(image_bytes)), int(image_bytesLen))
|
||
|
|
}
|
||
|
|
|
||
|
|
var goConfig OcrConfig
|
||
|
|
if config != nil {
|
||
|
|
json.Unmarshal([]byte(C.GoString(config)), &goConfig)
|
||
|
|
|
||
|
|
}
|
||
|
|
|
||
|
|
// Call the method
|
||
|
|
result, err := impl.ProcessImage(goImage_bytes, goConfig)
|
||
|
|
|
||
|
|
if err != nil {
|
||
|
|
cErr := C.CString(err.Error())
|
||
|
|
*outError = cErr
|
||
|
|
return 1
|
||
|
|
}
|
||
|
|
jsonBytes, _ := json.Marshal(result)
|
||
|
|
cResult := C.CString(string(jsonBytes))
|
||
|
|
*outResult = cResult
|
||
|
|
return 0 // success
|
||
|
|
}
|
||
|
|
|
||
|
|
//export goOcrBackendProcessImageFile
|
||
|
|
func goOcrBackendProcessImageFile(
|
||
|
|
userData unsafe.Pointer,
|
||
|
|
path *C.char,
|
||
|
|
config *C.char,
|
||
|
|
outResult **C.char,
|
||
|
|
outError **C.char,
|
||
|
|
) C.int32_t {
|
||
|
|
|
||
|
|
handle := cgo.Handle(uintptr(unsafe.Pointer(userData)))
|
||
|
|
impl, ok := handle.Value().(OcrBackend)
|
||
|
|
|
||
|
|
if !ok {
|
||
|
|
return 1 // error: invalid handle
|
||
|
|
}
|
||
|
|
|
||
|
|
goPath := C.GoString(path)
|
||
|
|
|
||
|
|
var goConfig OcrConfig
|
||
|
|
if config != nil {
|
||
|
|
json.Unmarshal([]byte(C.GoString(config)), &goConfig)
|
||
|
|
|
||
|
|
}
|
||
|
|
|
||
|
|
// Call the method
|
||
|
|
result, err := impl.ProcessImageFile(goPath, goConfig)
|
||
|
|
|
||
|
|
if err != nil {
|
||
|
|
cErr := C.CString(err.Error())
|
||
|
|
*outError = cErr
|
||
|
|
return 1
|
||
|
|
}
|
||
|
|
jsonBytes, _ := json.Marshal(result)
|
||
|
|
cResult := C.CString(string(jsonBytes))
|
||
|
|
*outResult = cResult
|
||
|
|
return 0 // success
|
||
|
|
}
|
||
|
|
|
||
|
|
//export goOcrBackendSupportsLanguage
|
||
|
|
func goOcrBackendSupportsLanguage(
|
||
|
|
userData unsafe.Pointer,
|
||
|
|
lang *C.char,
|
||
|
|
outResult **C.char,
|
||
|
|
outError **C.char,
|
||
|
|
) C.int32_t {
|
||
|
|
|
||
|
|
handle := cgo.Handle(uintptr(unsafe.Pointer(userData)))
|
||
|
|
impl, ok := handle.Value().(OcrBackend)
|
||
|
|
|
||
|
|
if !ok {
|
||
|
|
return 1 // error: invalid handle
|
||
|
|
}
|
||
|
|
|
||
|
|
goLang := C.GoString(lang)
|
||
|
|
|
||
|
|
// Call the method
|
||
|
|
result := impl.SupportsLanguage(goLang)
|
||
|
|
|
||
|
|
jsonBytes, _ := json.Marshal(result)
|
||
|
|
cResult := C.CString(string(jsonBytes))
|
||
|
|
*outResult = cResult
|
||
|
|
return 0 // success
|
||
|
|
}
|
||
|
|
|
||
|
|
//export goOcrBackendBackendType
|
||
|
|
func goOcrBackendBackendType(
|
||
|
|
userData unsafe.Pointer,
|
||
|
|
outResult **C.char,
|
||
|
|
outError **C.char,
|
||
|
|
) C.int32_t {
|
||
|
|
|
||
|
|
handle := cgo.Handle(uintptr(unsafe.Pointer(userData)))
|
||
|
|
impl, ok := handle.Value().(OcrBackend)
|
||
|
|
|
||
|
|
if !ok {
|
||
|
|
return 1 // error: invalid handle
|
||
|
|
}
|
||
|
|
|
||
|
|
// Call the method
|
||
|
|
result := impl.BackendType()
|
||
|
|
|
||
|
|
jsonBytes, _ := json.Marshal(result)
|
||
|
|
cResult := C.CString(string(jsonBytes))
|
||
|
|
*outResult = cResult
|
||
|
|
return 0 // success
|
||
|
|
}
|
||
|
|
|
||
|
|
//export goOcrBackendSupportedLanguages
|
||
|
|
func goOcrBackendSupportedLanguages(
|
||
|
|
userData unsafe.Pointer,
|
||
|
|
outResult **C.char,
|
||
|
|
outError **C.char,
|
||
|
|
) C.int32_t {
|
||
|
|
|
||
|
|
handle := cgo.Handle(uintptr(unsafe.Pointer(userData)))
|
||
|
|
impl, ok := handle.Value().(OcrBackend)
|
||
|
|
|
||
|
|
if !ok {
|
||
|
|
return 1 // error: invalid handle
|
||
|
|
}
|
||
|
|
|
||
|
|
// Call the method
|
||
|
|
result := impl.SupportedLanguages()
|
||
|
|
|
||
|
|
jsonBytes, _ := json.Marshal(result)
|
||
|
|
cResult := C.CString(string(jsonBytes))
|
||
|
|
*outResult = cResult
|
||
|
|
return 0 // success
|
||
|
|
}
|
||
|
|
|
||
|
|
//export goOcrBackendSupportsTableDetection
|
||
|
|
func goOcrBackendSupportsTableDetection(
|
||
|
|
userData unsafe.Pointer,
|
||
|
|
outResult **C.char,
|
||
|
|
outError **C.char,
|
||
|
|
) C.int32_t {
|
||
|
|
|
||
|
|
handle := cgo.Handle(uintptr(unsafe.Pointer(userData)))
|
||
|
|
impl, ok := handle.Value().(OcrBackend)
|
||
|
|
|
||
|
|
if !ok {
|
||
|
|
return 1 // error: invalid handle
|
||
|
|
}
|
||
|
|
|
||
|
|
// Call the method
|
||
|
|
result := impl.SupportsTableDetection()
|
||
|
|
|
||
|
|
jsonBytes, _ := json.Marshal(result)
|
||
|
|
cResult := C.CString(string(jsonBytes))
|
||
|
|
*outResult = cResult
|
||
|
|
return 0 // success
|
||
|
|
}
|
||
|
|
|
||
|
|
//export goOcrBackendSupportsDocumentProcessing
|
||
|
|
func goOcrBackendSupportsDocumentProcessing(
|
||
|
|
userData unsafe.Pointer,
|
||
|
|
outResult **C.char,
|
||
|
|
outError **C.char,
|
||
|
|
) C.int32_t {
|
||
|
|
|
||
|
|
handle := cgo.Handle(uintptr(unsafe.Pointer(userData)))
|
||
|
|
impl, ok := handle.Value().(OcrBackend)
|
||
|
|
|
||
|
|
if !ok {
|
||
|
|
return 1 // error: invalid handle
|
||
|
|
}
|
||
|
|
|
||
|
|
// Call the method
|
||
|
|
result := impl.SupportsDocumentProcessing()
|
||
|
|
|
||
|
|
jsonBytes, _ := json.Marshal(result)
|
||
|
|
cResult := C.CString(string(jsonBytes))
|
||
|
|
*outResult = cResult
|
||
|
|
return 0 // success
|
||
|
|
}
|
||
|
|
|
||
|
|
//export goOcrBackendProcessDocument
|
||
|
|
func goOcrBackendProcessDocument(
|
||
|
|
userData unsafe.Pointer,
|
||
|
|
_path *C.char,
|
||
|
|
_config *C.char,
|
||
|
|
outResult **C.char,
|
||
|
|
outError **C.char,
|
||
|
|
) C.int32_t {
|
||
|
|
|
||
|
|
handle := cgo.Handle(uintptr(unsafe.Pointer(userData)))
|
||
|
|
impl, ok := handle.Value().(OcrBackend)
|
||
|
|
|
||
|
|
if !ok {
|
||
|
|
return 1 // error: invalid handle
|
||
|
|
}
|
||
|
|
|
||
|
|
go_path := C.GoString(_path)
|
||
|
|
|
||
|
|
var go_config OcrConfig
|
||
|
|
if _config != nil {
|
||
|
|
json.Unmarshal([]byte(C.GoString(_config)), &go_config)
|
||
|
|
|
||
|
|
}
|
||
|
|
|
||
|
|
// Call the method
|
||
|
|
result, err := impl.ProcessDocument(go_path, go_config)
|
||
|
|
|
||
|
|
if err != nil {
|
||
|
|
cErr := C.CString(err.Error())
|
||
|
|
*outError = cErr
|
||
|
|
return 1
|
||
|
|
}
|
||
|
|
jsonBytes, _ := json.Marshal(result)
|
||
|
|
cResult := C.CString(string(jsonBytes))
|
||
|
|
*outResult = cResult
|
||
|
|
return 0 // success
|
||
|
|
}
|
||
|
|
|
||
|
|
//export goOcrBackendName
|
||
|
|
func goOcrBackendName(userData unsafe.Pointer, outResult **C.char, outError **C.char) C.int32_t {
|
||
|
|
|
||
|
|
handle := cgo.Handle(uintptr(unsafe.Pointer(userData)))
|
||
|
|
impl, ok := handle.Value().(OcrBackend)
|
||
|
|
|
||
|
|
if !ok {
|
||
|
|
return 1
|
||
|
|
}
|
||
|
|
name := impl.Name()
|
||
|
|
cName := C.CString(name)
|
||
|
|
*outResult = cName
|
||
|
|
return 0
|
||
|
|
}
|
||
|
|
|
||
|
|
//export goOcrBackendVersion
|
||
|
|
func goOcrBackendVersion(userData unsafe.Pointer, outResult **C.char, outError **C.char) C.int32_t {
|
||
|
|
|
||
|
|
handle := cgo.Handle(uintptr(unsafe.Pointer(userData)))
|
||
|
|
impl, ok := handle.Value().(OcrBackend)
|
||
|
|
|
||
|
|
if !ok {
|
||
|
|
return 1
|
||
|
|
}
|
||
|
|
version := impl.Version()
|
||
|
|
cVersion := C.CString(version)
|
||
|
|
*outResult = cVersion
|
||
|
|
return 0
|
||
|
|
}
|
||
|
|
|
||
|
|
//export goOcrBackendInitialize
|
||
|
|
func goOcrBackendInitialize(userData unsafe.Pointer, outError **C.char) C.int32_t {
|
||
|
|
|
||
|
|
handle := cgo.Handle(uintptr(unsafe.Pointer(userData)))
|
||
|
|
impl, ok := handle.Value().(OcrBackend)
|
||
|
|
|
||
|
|
if !ok {
|
||
|
|
return 1
|
||
|
|
}
|
||
|
|
err := impl.Initialize()
|
||
|
|
if err != nil {
|
||
|
|
cErr := C.CString(err.Error())
|
||
|
|
*outError = cErr
|
||
|
|
return 1
|
||
|
|
}
|
||
|
|
return 0
|
||
|
|
}
|
||
|
|
|
||
|
|
//export goOcrBackendShutdown
|
||
|
|
func goOcrBackendShutdown(userData unsafe.Pointer, outError **C.char) C.int32_t {
|
||
|
|
|
||
|
|
handle := cgo.Handle(uintptr(unsafe.Pointer(userData)))
|
||
|
|
impl, ok := handle.Value().(OcrBackend)
|
||
|
|
|
||
|
|
if !ok {
|
||
|
|
return 1
|
||
|
|
}
|
||
|
|
err := impl.Shutdown()
|
||
|
|
if err != nil {
|
||
|
|
cErr := C.CString(err.Error())
|
||
|
|
*outError = cErr
|
||
|
|
return 1
|
||
|
|
}
|
||
|
|
return 0
|
||
|
|
}
|
||
|
|
|
||
|
|
//export goOcrBackendFreeUserData
|
||
|
|
func goOcrBackendFreeUserData(userData unsafe.Pointer) {
|
||
|
|
|
||
|
|
// No-op to avoid cleanup-queue panics. Handles cleaned in Unregister().
|
||
|
|
}
|
||
|
|
|
||
|
|
//export goOcrBackendFreeString
|
||
|
|
func goOcrBackendFreeString(ptr *C.char) {
|
||
|
|
if ptr != nil {
|
||
|
|
C.free(unsafe.Pointer(ptr))
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// RegisterOcrBackend registers a OcrBackend implementation with the C runtime.
|
||
|
|
func RegisterOcrBackend(impl OcrBackend) error {
|
||
|
|
handle := cgo.NewHandle(impl)
|
||
|
|
// Build the C vtable DEBUG:c_vtable_struct=KREUZBERGKreuzbergOcrBackendVTable
|
||
|
|
vtable := C.KREUZBERGKreuzbergOcrBackendVTable{
|
||
|
|
process_image: (*[0]byte)(unsafe.Pointer(C.goOcrBackendProcessImage)),
|
||
|
|
process_image_file: (*[0]byte)(unsafe.Pointer(C.goOcrBackendProcessImageFile)),
|
||
|
|
supports_language: (*[0]byte)(unsafe.Pointer(C.goOcrBackendSupportsLanguage)),
|
||
|
|
backend_type: (*[0]byte)(unsafe.Pointer(C.goOcrBackendBackendType)),
|
||
|
|
supported_languages: (*[0]byte)(unsafe.Pointer(C.goOcrBackendSupportedLanguages)),
|
||
|
|
supports_table_detection: (*[0]byte)(unsafe.Pointer(C.goOcrBackendSupportsTableDetection)),
|
||
|
|
supports_document_processing: (*[0]byte)(unsafe.Pointer(C.goOcrBackendSupportsDocumentProcessing)),
|
||
|
|
process_document: (*[0]byte)(unsafe.Pointer(C.goOcrBackendProcessDocument)),
|
||
|
|
name_fn: (*[0]byte)(unsafe.Pointer(C.goOcrBackendName)),
|
||
|
|
version_fn: (*[0]byte)(unsafe.Pointer(C.goOcrBackendVersion)),
|
||
|
|
initialize_fn: (*[0]byte)(unsafe.Pointer(C.goOcrBackendInitialize)),
|
||
|
|
shutdown_fn: (*[0]byte)(unsafe.Pointer(C.goOcrBackendShutdown)),
|
||
|
|
free_string: (*[0]byte)(unsafe.Pointer(C.goOcrBackendFreeString)),
|
||
|
|
free_user_data: (*[0]byte)(unsafe.Pointer(C.goOcrBackendFreeUserData)),
|
||
|
|
}
|
||
|
|
|
||
|
|
// Call C registration
|
||
|
|
cName := C.CString(impl.Name())
|
||
|
|
defer C.free(unsafe.Pointer(cName))
|
||
|
|
|
||
|
|
var cErr *C.char
|
||
|
|
rc := C.kreuzberg_register_ocr_backend(
|
||
|
|
cName,
|
||
|
|
vtable,
|
||
|
|
unsafe.Pointer(uintptr(handle)),
|
||
|
|
&cErr,
|
||
|
|
)
|
||
|
|
|
||
|
|
if rc != 0 {
|
||
|
|
msg := "failed to register OcrBackend"
|
||
|
|
if cErr != nil {
|
||
|
|
msg = C.GoString(cErr)
|
||
|
|
C.kreuzberg_free_string(cErr)
|
||
|
|
}
|
||
|
|
handle.Delete()
|
||
|
|
return fmt.Errorf("%s", msg)
|
||
|
|
}
|
||
|
|
|
||
|
|
// Store handle by name for later cleanup on unregister
|
||
|
|
ocr_backendRegistry.store(impl.Name(), handle)
|
||
|
|
return nil
|
||
|
|
}
|
||
|
|
|
||
|
|
// UnregisterOcrBackend unregisters a OcrBackend implementation.
|
||
|
|
func UnregisterOcrBackend(name string) error {
|
||
|
|
cName := C.CString(name)
|
||
|
|
defer C.free(unsafe.Pointer(cName))
|
||
|
|
var cErr *C.char
|
||
|
|
rc := C.kreuzberg_unregister_ocr_backend(cName, &cErr)
|
||
|
|
|
||
|
|
if rc != 0 {
|
||
|
|
msg := "failed to unregister OcrBackend"
|
||
|
|
if cErr != nil {
|
||
|
|
msg = C.GoString(cErr)
|
||
|
|
C.kreuzberg_free_string(cErr)
|
||
|
|
}
|
||
|
|
return fmt.Errorf("%s", msg)
|
||
|
|
}
|
||
|
|
|
||
|
|
// Delete the handle now that Rust has unregistered the plugin
|
||
|
|
ocr_backendRegistry.delete(name)
|
||
|
|
return nil
|
||
|
|
}
|
||
|
|
|
||
|
|
// ClearOcrBackends removes all registered OcrBackend implementations.
|
||
|
|
func ClearOcrBackends() error {
|
||
|
|
var cErr *C.char
|
||
|
|
rc := C.kreuzberg_clear_ocr_backend(&cErr)
|
||
|
|
|
||
|
|
if rc != 0 {
|
||
|
|
msg := "failed to clear OcrBackend plugins"
|
||
|
|
if cErr != nil {
|
||
|
|
msg = C.GoString(cErr)
|
||
|
|
C.free(unsafe.Pointer(cErr))
|
||
|
|
}
|
||
|
|
return fmt.Errorf("%s", msg)
|
||
|
|
}
|
||
|
|
|
||
|
|
// Delete all handles now that Rust has cleared all plugins
|
||
|
|
ocr_backendRegistry.clear()
|
||
|
|
return nil
|
||
|
|
}
|
||
|
|
|
||
|
|
// PostProcessor defines the Go interface for the PostProcessor trait.
|
||
|
|
type PostProcessor interface {
|
||
|
|
// Name returns the plugin name.
|
||
|
|
Name() string
|
||
|
|
// Version returns the plugin version.
|
||
|
|
Version() string
|
||
|
|
// Initialize is called when the plugin is loaded.
|
||
|
|
Initialize() error
|
||
|
|
// Shutdown is called when the plugin is unloaded.
|
||
|
|
Shutdown() error
|
||
|
|
// process
|
||
|
|
Process(result ExtractionResult, config ExtractionConfig) error
|
||
|
|
|
||
|
|
// processing_stage
|
||
|
|
ProcessingStage() ProcessingStage
|
||
|
|
|
||
|
|
// should_process
|
||
|
|
ShouldProcess(_result ExtractionResult, _config ExtractionConfig) bool
|
||
|
|
|
||
|
|
// estimated_duration_ms
|
||
|
|
EstimatedDurationMs(_result ExtractionResult) uint64
|
||
|
|
|
||
|
|
// priority
|
||
|
|
Priority() int32
|
||
|
|
|
||
|
|
}
|
||
|
|
|
||
|
|
//export goPostProcessorProcess
|
||
|
|
func goPostProcessorProcess(
|
||
|
|
userData unsafe.Pointer,
|
||
|
|
result *C.char,
|
||
|
|
config *C.char,
|
||
|
|
outError **C.char,
|
||
|
|
) C.int32_t {
|
||
|
|
|
||
|
|
handle := cgo.Handle(uintptr(unsafe.Pointer(userData)))
|
||
|
|
impl, ok := handle.Value().(PostProcessor)
|
||
|
|
|
||
|
|
if !ok {
|
||
|
|
return 1 // error: invalid handle
|
||
|
|
}
|
||
|
|
|
||
|
|
var goResult ExtractionResult
|
||
|
|
if result != nil {
|
||
|
|
json.Unmarshal([]byte(C.GoString(result)), &goResult)
|
||
|
|
|
||
|
|
}
|
||
|
|
|
||
|
|
var goConfig ExtractionConfig
|
||
|
|
if config != nil {
|
||
|
|
json.Unmarshal([]byte(C.GoString(config)), &goConfig)
|
||
|
|
|
||
|
|
}
|
||
|
|
|
||
|
|
// Call the method
|
||
|
|
err := impl.Process(goResult, goConfig)
|
||
|
|
|
||
|
|
if err != nil {
|
||
|
|
cErr := C.CString(err.Error())
|
||
|
|
*outError = cErr
|
||
|
|
return 1
|
||
|
|
}
|
||
|
|
return 0 // success
|
||
|
|
}
|
||
|
|
|
||
|
|
//export goPostProcessorProcessingStage
|
||
|
|
func goPostProcessorProcessingStage(
|
||
|
|
userData unsafe.Pointer,
|
||
|
|
outResult **C.char,
|
||
|
|
outError **C.char,
|
||
|
|
) C.int32_t {
|
||
|
|
|
||
|
|
handle := cgo.Handle(uintptr(unsafe.Pointer(userData)))
|
||
|
|
impl, ok := handle.Value().(PostProcessor)
|
||
|
|
|
||
|
|
if !ok {
|
||
|
|
return 1 // error: invalid handle
|
||
|
|
}
|
||
|
|
|
||
|
|
// Call the method
|
||
|
|
result := impl.ProcessingStage()
|
||
|
|
|
||
|
|
jsonBytes, _ := json.Marshal(result)
|
||
|
|
cResult := C.CString(string(jsonBytes))
|
||
|
|
*outResult = cResult
|
||
|
|
return 0 // success
|
||
|
|
}
|
||
|
|
|
||
|
|
//export goPostProcessorShouldProcess
|
||
|
|
func goPostProcessorShouldProcess(
|
||
|
|
userData unsafe.Pointer,
|
||
|
|
_result *C.char,
|
||
|
|
_config *C.char,
|
||
|
|
outResult **C.char,
|
||
|
|
outError **C.char,
|
||
|
|
) C.int32_t {
|
||
|
|
|
||
|
|
handle := cgo.Handle(uintptr(unsafe.Pointer(userData)))
|
||
|
|
impl, ok := handle.Value().(PostProcessor)
|
||
|
|
|
||
|
|
if !ok {
|
||
|
|
return 1 // error: invalid handle
|
||
|
|
}
|
||
|
|
|
||
|
|
var go_result ExtractionResult
|
||
|
|
if _result != nil {
|
||
|
|
json.Unmarshal([]byte(C.GoString(_result)), &go_result)
|
||
|
|
|
||
|
|
}
|
||
|
|
|
||
|
|
var go_config ExtractionConfig
|
||
|
|
if _config != nil {
|
||
|
|
json.Unmarshal([]byte(C.GoString(_config)), &go_config)
|
||
|
|
|
||
|
|
}
|
||
|
|
|
||
|
|
// Call the method
|
||
|
|
result := impl.ShouldProcess(go_result, go_config)
|
||
|
|
|
||
|
|
jsonBytes, _ := json.Marshal(result)
|
||
|
|
cResult := C.CString(string(jsonBytes))
|
||
|
|
*outResult = cResult
|
||
|
|
return 0 // success
|
||
|
|
}
|
||
|
|
|
||
|
|
//export goPostProcessorEstimatedDurationMs
|
||
|
|
func goPostProcessorEstimatedDurationMs(
|
||
|
|
userData unsafe.Pointer,
|
||
|
|
_result *C.char,
|
||
|
|
outResult **C.char,
|
||
|
|
outError **C.char,
|
||
|
|
) C.int32_t {
|
||
|
|
|
||
|
|
handle := cgo.Handle(uintptr(unsafe.Pointer(userData)))
|
||
|
|
impl, ok := handle.Value().(PostProcessor)
|
||
|
|
|
||
|
|
if !ok {
|
||
|
|
return 1 // error: invalid handle
|
||
|
|
}
|
||
|
|
|
||
|
|
var go_result ExtractionResult
|
||
|
|
if _result != nil {
|
||
|
|
json.Unmarshal([]byte(C.GoString(_result)), &go_result)
|
||
|
|
|
||
|
|
}
|
||
|
|
|
||
|
|
// Call the method
|
||
|
|
result := impl.EstimatedDurationMs(go_result)
|
||
|
|
|
||
|
|
jsonBytes, _ := json.Marshal(result)
|
||
|
|
cResult := C.CString(string(jsonBytes))
|
||
|
|
*outResult = cResult
|
||
|
|
return 0 // success
|
||
|
|
}
|
||
|
|
|
||
|
|
//export goPostProcessorPriority
|
||
|
|
func goPostProcessorPriority(
|
||
|
|
userData unsafe.Pointer,
|
||
|
|
outResult **C.char,
|
||
|
|
outError **C.char,
|
||
|
|
) C.int32_t {
|
||
|
|
|
||
|
|
handle := cgo.Handle(uintptr(unsafe.Pointer(userData)))
|
||
|
|
impl, ok := handle.Value().(PostProcessor)
|
||
|
|
|
||
|
|
if !ok {
|
||
|
|
return 1 // error: invalid handle
|
||
|
|
}
|
||
|
|
|
||
|
|
// Call the method
|
||
|
|
result := impl.Priority()
|
||
|
|
|
||
|
|
jsonBytes, _ := json.Marshal(result)
|
||
|
|
cResult := C.CString(string(jsonBytes))
|
||
|
|
*outResult = cResult
|
||
|
|
return 0 // success
|
||
|
|
}
|
||
|
|
|
||
|
|
//export goPostProcessorName
|
||
|
|
func goPostProcessorName(userData unsafe.Pointer, outResult **C.char, outError **C.char) C.int32_t {
|
||
|
|
|
||
|
|
handle := cgo.Handle(uintptr(unsafe.Pointer(userData)))
|
||
|
|
impl, ok := handle.Value().(PostProcessor)
|
||
|
|
|
||
|
|
if !ok {
|
||
|
|
return 1
|
||
|
|
}
|
||
|
|
name := impl.Name()
|
||
|
|
cName := C.CString(name)
|
||
|
|
*outResult = cName
|
||
|
|
return 0
|
||
|
|
}
|
||
|
|
|
||
|
|
//export goPostProcessorVersion
|
||
|
|
func goPostProcessorVersion(userData unsafe.Pointer, outResult **C.char, outError **C.char) C.int32_t {
|
||
|
|
|
||
|
|
handle := cgo.Handle(uintptr(unsafe.Pointer(userData)))
|
||
|
|
impl, ok := handle.Value().(PostProcessor)
|
||
|
|
|
||
|
|
if !ok {
|
||
|
|
return 1
|
||
|
|
}
|
||
|
|
version := impl.Version()
|
||
|
|
cVersion := C.CString(version)
|
||
|
|
*outResult = cVersion
|
||
|
|
return 0
|
||
|
|
}
|
||
|
|
|
||
|
|
//export goPostProcessorInitialize
|
||
|
|
func goPostProcessorInitialize(userData unsafe.Pointer, outError **C.char) C.int32_t {
|
||
|
|
|
||
|
|
handle := cgo.Handle(uintptr(unsafe.Pointer(userData)))
|
||
|
|
impl, ok := handle.Value().(PostProcessor)
|
||
|
|
|
||
|
|
if !ok {
|
||
|
|
return 1
|
||
|
|
}
|
||
|
|
err := impl.Initialize()
|
||
|
|
if err != nil {
|
||
|
|
cErr := C.CString(err.Error())
|
||
|
|
*outError = cErr
|
||
|
|
return 1
|
||
|
|
}
|
||
|
|
return 0
|
||
|
|
}
|
||
|
|
|
||
|
|
//export goPostProcessorShutdown
|
||
|
|
func goPostProcessorShutdown(userData unsafe.Pointer, outError **C.char) C.int32_t {
|
||
|
|
|
||
|
|
handle := cgo.Handle(uintptr(unsafe.Pointer(userData)))
|
||
|
|
impl, ok := handle.Value().(PostProcessor)
|
||
|
|
|
||
|
|
if !ok {
|
||
|
|
return 1
|
||
|
|
}
|
||
|
|
err := impl.Shutdown()
|
||
|
|
if err != nil {
|
||
|
|
cErr := C.CString(err.Error())
|
||
|
|
*outError = cErr
|
||
|
|
return 1
|
||
|
|
}
|
||
|
|
return 0
|
||
|
|
}
|
||
|
|
|
||
|
|
//export goPostProcessorFreeUserData
|
||
|
|
func goPostProcessorFreeUserData(userData unsafe.Pointer) {
|
||
|
|
|
||
|
|
// No-op to avoid cleanup-queue panics. Handles cleaned in Unregister().
|
||
|
|
}
|
||
|
|
|
||
|
|
//export goPostProcessorFreeString
|
||
|
|
func goPostProcessorFreeString(ptr *C.char) {
|
||
|
|
if ptr != nil {
|
||
|
|
C.free(unsafe.Pointer(ptr))
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// RegisterPostProcessor registers a PostProcessor implementation with the C runtime.
|
||
|
|
func RegisterPostProcessor(impl PostProcessor) error {
|
||
|
|
handle := cgo.NewHandle(impl)
|
||
|
|
// Build the C vtable DEBUG:c_vtable_struct=KREUZBERGKreuzbergPostProcessorVTable
|
||
|
|
vtable := C.KREUZBERGKreuzbergPostProcessorVTable{
|
||
|
|
process: (*[0]byte)(unsafe.Pointer(C.goPostProcessorProcess)),
|
||
|
|
processing_stage: (*[0]byte)(unsafe.Pointer(C.goPostProcessorProcessingStage)),
|
||
|
|
should_process: (*[0]byte)(unsafe.Pointer(C.goPostProcessorShouldProcess)),
|
||
|
|
estimated_duration_ms: (*[0]byte)(unsafe.Pointer(C.goPostProcessorEstimatedDurationMs)),
|
||
|
|
priority: (*[0]byte)(unsafe.Pointer(C.goPostProcessorPriority)),
|
||
|
|
name_fn: (*[0]byte)(unsafe.Pointer(C.goPostProcessorName)),
|
||
|
|
version_fn: (*[0]byte)(unsafe.Pointer(C.goPostProcessorVersion)),
|
||
|
|
initialize_fn: (*[0]byte)(unsafe.Pointer(C.goPostProcessorInitialize)),
|
||
|
|
shutdown_fn: (*[0]byte)(unsafe.Pointer(C.goPostProcessorShutdown)),
|
||
|
|
free_string: (*[0]byte)(unsafe.Pointer(C.goPostProcessorFreeString)),
|
||
|
|
free_user_data: (*[0]byte)(unsafe.Pointer(C.goPostProcessorFreeUserData)),
|
||
|
|
}
|
||
|
|
|
||
|
|
// Call C registration
|
||
|
|
cName := C.CString(impl.Name())
|
||
|
|
defer C.free(unsafe.Pointer(cName))
|
||
|
|
|
||
|
|
var cErr *C.char
|
||
|
|
rc := C.kreuzberg_register_post_processor(
|
||
|
|
cName,
|
||
|
|
vtable,
|
||
|
|
unsafe.Pointer(uintptr(handle)),
|
||
|
|
&cErr,
|
||
|
|
)
|
||
|
|
|
||
|
|
if rc != 0 {
|
||
|
|
msg := "failed to register PostProcessor"
|
||
|
|
if cErr != nil {
|
||
|
|
msg = C.GoString(cErr)
|
||
|
|
C.kreuzberg_free_string(cErr)
|
||
|
|
}
|
||
|
|
handle.Delete()
|
||
|
|
return fmt.Errorf("%s", msg)
|
||
|
|
}
|
||
|
|
|
||
|
|
// Store handle by name for later cleanup on unregister
|
||
|
|
post_processorRegistry.store(impl.Name(), handle)
|
||
|
|
return nil
|
||
|
|
}
|
||
|
|
|
||
|
|
// UnregisterPostProcessor unregisters a PostProcessor implementation.
|
||
|
|
func UnregisterPostProcessor(name string) error {
|
||
|
|
cName := C.CString(name)
|
||
|
|
defer C.free(unsafe.Pointer(cName))
|
||
|
|
var cErr *C.char
|
||
|
|
rc := C.kreuzberg_unregister_post_processor(cName, &cErr)
|
||
|
|
|
||
|
|
if rc != 0 {
|
||
|
|
msg := "failed to unregister PostProcessor"
|
||
|
|
if cErr != nil {
|
||
|
|
msg = C.GoString(cErr)
|
||
|
|
C.kreuzberg_free_string(cErr)
|
||
|
|
}
|
||
|
|
return fmt.Errorf("%s", msg)
|
||
|
|
}
|
||
|
|
|
||
|
|
// Delete the handle now that Rust has unregistered the plugin
|
||
|
|
post_processorRegistry.delete(name)
|
||
|
|
return nil
|
||
|
|
}
|
||
|
|
|
||
|
|
// ClearPostProcessors removes all registered PostProcessor implementations.
|
||
|
|
func ClearPostProcessors() error {
|
||
|
|
var cErr *C.char
|
||
|
|
rc := C.kreuzberg_clear_post_processor(&cErr)
|
||
|
|
|
||
|
|
if rc != 0 {
|
||
|
|
msg := "failed to clear PostProcessor plugins"
|
||
|
|
if cErr != nil {
|
||
|
|
msg = C.GoString(cErr)
|
||
|
|
C.free(unsafe.Pointer(cErr))
|
||
|
|
}
|
||
|
|
return fmt.Errorf("%s", msg)
|
||
|
|
}
|
||
|
|
|
||
|
|
// Delete all handles now that Rust has cleared all plugins
|
||
|
|
post_processorRegistry.clear()
|
||
|
|
return nil
|
||
|
|
}
|
||
|
|
|
||
|
|
// Validator defines the Go interface for the Validator trait.
|
||
|
|
type Validator interface {
|
||
|
|
// Name returns the plugin name.
|
||
|
|
Name() string
|
||
|
|
// Version returns the plugin version.
|
||
|
|
Version() string
|
||
|
|
// Initialize is called when the plugin is loaded.
|
||
|
|
Initialize() error
|
||
|
|
// Shutdown is called when the plugin is unloaded.
|
||
|
|
Shutdown() error
|
||
|
|
// validate
|
||
|
|
Validate(result ExtractionResult, config ExtractionConfig) error
|
||
|
|
|
||
|
|
// should_validate
|
||
|
|
ShouldValidate(_result ExtractionResult, _config ExtractionConfig) bool
|
||
|
|
|
||
|
|
// priority
|
||
|
|
Priority() int32
|
||
|
|
|
||
|
|
}
|
||
|
|
|
||
|
|
//export goValidatorValidate
|
||
|
|
func goValidatorValidate(
|
||
|
|
userData unsafe.Pointer,
|
||
|
|
result *C.char,
|
||
|
|
config *C.char,
|
||
|
|
outError **C.char,
|
||
|
|
) C.int32_t {
|
||
|
|
|
||
|
|
handle := cgo.Handle(uintptr(unsafe.Pointer(userData)))
|
||
|
|
impl, ok := handle.Value().(Validator)
|
||
|
|
|
||
|
|
if !ok {
|
||
|
|
return 1 // error: invalid handle
|
||
|
|
}
|
||
|
|
|
||
|
|
var goResult ExtractionResult
|
||
|
|
if result != nil {
|
||
|
|
json.Unmarshal([]byte(C.GoString(result)), &goResult)
|
||
|
|
|
||
|
|
}
|
||
|
|
|
||
|
|
var goConfig ExtractionConfig
|
||
|
|
if config != nil {
|
||
|
|
json.Unmarshal([]byte(C.GoString(config)), &goConfig)
|
||
|
|
|
||
|
|
}
|
||
|
|
|
||
|
|
// Call the method
|
||
|
|
err := impl.Validate(goResult, goConfig)
|
||
|
|
|
||
|
|
if err != nil {
|
||
|
|
cErr := C.CString(err.Error())
|
||
|
|
*outError = cErr
|
||
|
|
return 1
|
||
|
|
}
|
||
|
|
return 0 // success
|
||
|
|
}
|
||
|
|
|
||
|
|
//export goValidatorShouldValidate
|
||
|
|
func goValidatorShouldValidate(
|
||
|
|
userData unsafe.Pointer,
|
||
|
|
_result *C.char,
|
||
|
|
_config *C.char,
|
||
|
|
outResult **C.char,
|
||
|
|
outError **C.char,
|
||
|
|
) C.int32_t {
|
||
|
|
|
||
|
|
handle := cgo.Handle(uintptr(unsafe.Pointer(userData)))
|
||
|
|
impl, ok := handle.Value().(Validator)
|
||
|
|
|
||
|
|
if !ok {
|
||
|
|
return 1 // error: invalid handle
|
||
|
|
}
|
||
|
|
|
||
|
|
var go_result ExtractionResult
|
||
|
|
if _result != nil {
|
||
|
|
json.Unmarshal([]byte(C.GoString(_result)), &go_result)
|
||
|
|
|
||
|
|
}
|
||
|
|
|
||
|
|
var go_config ExtractionConfig
|
||
|
|
if _config != nil {
|
||
|
|
json.Unmarshal([]byte(C.GoString(_config)), &go_config)
|
||
|
|
|
||
|
|
}
|
||
|
|
|
||
|
|
// Call the method
|
||
|
|
result := impl.ShouldValidate(go_result, go_config)
|
||
|
|
|
||
|
|
jsonBytes, _ := json.Marshal(result)
|
||
|
|
cResult := C.CString(string(jsonBytes))
|
||
|
|
*outResult = cResult
|
||
|
|
return 0 // success
|
||
|
|
}
|
||
|
|
|
||
|
|
//export goValidatorPriority
|
||
|
|
func goValidatorPriority(
|
||
|
|
userData unsafe.Pointer,
|
||
|
|
outResult **C.char,
|
||
|
|
outError **C.char,
|
||
|
|
) C.int32_t {
|
||
|
|
|
||
|
|
handle := cgo.Handle(uintptr(unsafe.Pointer(userData)))
|
||
|
|
impl, ok := handle.Value().(Validator)
|
||
|
|
|
||
|
|
if !ok {
|
||
|
|
return 1 // error: invalid handle
|
||
|
|
}
|
||
|
|
|
||
|
|
// Call the method
|
||
|
|
result := impl.Priority()
|
||
|
|
|
||
|
|
jsonBytes, _ := json.Marshal(result)
|
||
|
|
cResult := C.CString(string(jsonBytes))
|
||
|
|
*outResult = cResult
|
||
|
|
return 0 // success
|
||
|
|
}
|
||
|
|
|
||
|
|
//export goValidatorName
|
||
|
|
func goValidatorName(userData unsafe.Pointer, outResult **C.char, outError **C.char) C.int32_t {
|
||
|
|
|
||
|
|
handle := cgo.Handle(uintptr(unsafe.Pointer(userData)))
|
||
|
|
impl, ok := handle.Value().(Validator)
|
||
|
|
|
||
|
|
if !ok {
|
||
|
|
return 1
|
||
|
|
}
|
||
|
|
name := impl.Name()
|
||
|
|
cName := C.CString(name)
|
||
|
|
*outResult = cName
|
||
|
|
return 0
|
||
|
|
}
|
||
|
|
|
||
|
|
//export goValidatorVersion
|
||
|
|
func goValidatorVersion(userData unsafe.Pointer, outResult **C.char, outError **C.char) C.int32_t {
|
||
|
|
|
||
|
|
handle := cgo.Handle(uintptr(unsafe.Pointer(userData)))
|
||
|
|
impl, ok := handle.Value().(Validator)
|
||
|
|
|
||
|
|
if !ok {
|
||
|
|
return 1
|
||
|
|
}
|
||
|
|
version := impl.Version()
|
||
|
|
cVersion := C.CString(version)
|
||
|
|
*outResult = cVersion
|
||
|
|
return 0
|
||
|
|
}
|
||
|
|
|
||
|
|
//export goValidatorInitialize
|
||
|
|
func goValidatorInitialize(userData unsafe.Pointer, outError **C.char) C.int32_t {
|
||
|
|
|
||
|
|
handle := cgo.Handle(uintptr(unsafe.Pointer(userData)))
|
||
|
|
impl, ok := handle.Value().(Validator)
|
||
|
|
|
||
|
|
if !ok {
|
||
|
|
return 1
|
||
|
|
}
|
||
|
|
err := impl.Initialize()
|
||
|
|
if err != nil {
|
||
|
|
cErr := C.CString(err.Error())
|
||
|
|
*outError = cErr
|
||
|
|
return 1
|
||
|
|
}
|
||
|
|
return 0
|
||
|
|
}
|
||
|
|
|
||
|
|
//export goValidatorShutdown
|
||
|
|
func goValidatorShutdown(userData unsafe.Pointer, outError **C.char) C.int32_t {
|
||
|
|
|
||
|
|
handle := cgo.Handle(uintptr(unsafe.Pointer(userData)))
|
||
|
|
impl, ok := handle.Value().(Validator)
|
||
|
|
|
||
|
|
if !ok {
|
||
|
|
return 1
|
||
|
|
}
|
||
|
|
err := impl.Shutdown()
|
||
|
|
if err != nil {
|
||
|
|
cErr := C.CString(err.Error())
|
||
|
|
*outError = cErr
|
||
|
|
return 1
|
||
|
|
}
|
||
|
|
return 0
|
||
|
|
}
|
||
|
|
|
||
|
|
//export goValidatorFreeUserData
|
||
|
|
func goValidatorFreeUserData(userData unsafe.Pointer) {
|
||
|
|
|
||
|
|
// No-op to avoid cleanup-queue panics. Handles cleaned in Unregister().
|
||
|
|
}
|
||
|
|
|
||
|
|
//export goValidatorFreeString
|
||
|
|
func goValidatorFreeString(ptr *C.char) {
|
||
|
|
if ptr != nil {
|
||
|
|
C.free(unsafe.Pointer(ptr))
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// RegisterValidator registers a Validator implementation with the C runtime.
|
||
|
|
func RegisterValidator(impl Validator) error {
|
||
|
|
handle := cgo.NewHandle(impl)
|
||
|
|
// Build the C vtable DEBUG:c_vtable_struct=KREUZBERGKreuzbergValidatorVTable
|
||
|
|
vtable := C.KREUZBERGKreuzbergValidatorVTable{
|
||
|
|
validate: (*[0]byte)(unsafe.Pointer(C.goValidatorValidate)),
|
||
|
|
should_validate: (*[0]byte)(unsafe.Pointer(C.goValidatorShouldValidate)),
|
||
|
|
priority: (*[0]byte)(unsafe.Pointer(C.goValidatorPriority)),
|
||
|
|
name_fn: (*[0]byte)(unsafe.Pointer(C.goValidatorName)),
|
||
|
|
version_fn: (*[0]byte)(unsafe.Pointer(C.goValidatorVersion)),
|
||
|
|
initialize_fn: (*[0]byte)(unsafe.Pointer(C.goValidatorInitialize)),
|
||
|
|
shutdown_fn: (*[0]byte)(unsafe.Pointer(C.goValidatorShutdown)),
|
||
|
|
free_string: (*[0]byte)(unsafe.Pointer(C.goValidatorFreeString)),
|
||
|
|
free_user_data: (*[0]byte)(unsafe.Pointer(C.goValidatorFreeUserData)),
|
||
|
|
}
|
||
|
|
|
||
|
|
// Call C registration
|
||
|
|
cName := C.CString(impl.Name())
|
||
|
|
defer C.free(unsafe.Pointer(cName))
|
||
|
|
|
||
|
|
var cErr *C.char
|
||
|
|
rc := C.kreuzberg_register_validator(
|
||
|
|
cName,
|
||
|
|
vtable,
|
||
|
|
unsafe.Pointer(uintptr(handle)),
|
||
|
|
&cErr,
|
||
|
|
)
|
||
|
|
|
||
|
|
if rc != 0 {
|
||
|
|
msg := "failed to register Validator"
|
||
|
|
if cErr != nil {
|
||
|
|
msg = C.GoString(cErr)
|
||
|
|
C.kreuzberg_free_string(cErr)
|
||
|
|
}
|
||
|
|
handle.Delete()
|
||
|
|
return fmt.Errorf("%s", msg)
|
||
|
|
}
|
||
|
|
|
||
|
|
// Store handle by name for later cleanup on unregister
|
||
|
|
validatorRegistry.store(impl.Name(), handle)
|
||
|
|
return nil
|
||
|
|
}
|
||
|
|
|
||
|
|
// UnregisterValidator unregisters a Validator implementation.
|
||
|
|
func UnregisterValidator(name string) error {
|
||
|
|
cName := C.CString(name)
|
||
|
|
defer C.free(unsafe.Pointer(cName))
|
||
|
|
var cErr *C.char
|
||
|
|
rc := C.kreuzberg_unregister_validator(cName, &cErr)
|
||
|
|
|
||
|
|
if rc != 0 {
|
||
|
|
msg := "failed to unregister Validator"
|
||
|
|
if cErr != nil {
|
||
|
|
msg = C.GoString(cErr)
|
||
|
|
C.kreuzberg_free_string(cErr)
|
||
|
|
}
|
||
|
|
return fmt.Errorf("%s", msg)
|
||
|
|
}
|
||
|
|
|
||
|
|
// Delete the handle now that Rust has unregistered the plugin
|
||
|
|
validatorRegistry.delete(name)
|
||
|
|
return nil
|
||
|
|
}
|
||
|
|
|
||
|
|
// ClearValidators removes all registered Validator implementations.
|
||
|
|
func ClearValidators() error {
|
||
|
|
var cErr *C.char
|
||
|
|
rc := C.kreuzberg_clear_validator(&cErr)
|
||
|
|
|
||
|
|
if rc != 0 {
|
||
|
|
msg := "failed to clear Validator plugins"
|
||
|
|
if cErr != nil {
|
||
|
|
msg = C.GoString(cErr)
|
||
|
|
C.free(unsafe.Pointer(cErr))
|
||
|
|
}
|
||
|
|
return fmt.Errorf("%s", msg)
|
||
|
|
}
|
||
|
|
|
||
|
|
// Delete all handles now that Rust has cleared all plugins
|
||
|
|
validatorRegistry.clear()
|
||
|
|
return nil
|
||
|
|
}
|
||
|
|
|
||
|
|
// EmbeddingBackend defines the Go interface for the EmbeddingBackend trait.
|
||
|
|
type EmbeddingBackend interface {
|
||
|
|
// Name returns the plugin name.
|
||
|
|
Name() string
|
||
|
|
// Version returns the plugin version.
|
||
|
|
Version() string
|
||
|
|
// Initialize is called when the plugin is loaded.
|
||
|
|
Initialize() error
|
||
|
|
// Shutdown is called when the plugin is unloaded.
|
||
|
|
Shutdown() error
|
||
|
|
// dimensions
|
||
|
|
Dimensions() uint
|
||
|
|
|
||
|
|
// embed
|
||
|
|
Embed(texts []string) ([][]float32, error)
|
||
|
|
|
||
|
|
}
|
||
|
|
|
||
|
|
//export goEmbeddingBackendDimensions
|
||
|
|
func goEmbeddingBackendDimensions(
|
||
|
|
userData unsafe.Pointer,
|
||
|
|
outResult **C.char,
|
||
|
|
outError **C.char,
|
||
|
|
) C.int32_t {
|
||
|
|
|
||
|
|
handle := cgo.Handle(uintptr(unsafe.Pointer(userData)))
|
||
|
|
impl, ok := handle.Value().(EmbeddingBackend)
|
||
|
|
|
||
|
|
if !ok {
|
||
|
|
return 1 // error: invalid handle
|
||
|
|
}
|
||
|
|
|
||
|
|
// Call the method
|
||
|
|
result := impl.Dimensions()
|
||
|
|
|
||
|
|
jsonBytes, _ := json.Marshal(result)
|
||
|
|
cResult := C.CString(string(jsonBytes))
|
||
|
|
*outResult = cResult
|
||
|
|
return 0 // success
|
||
|
|
}
|
||
|
|
|
||
|
|
//export goEmbeddingBackendEmbed
|
||
|
|
func goEmbeddingBackendEmbed(
|
||
|
|
userData unsafe.Pointer,
|
||
|
|
texts *C.char,
|
||
|
|
outResult **C.char,
|
||
|
|
outError **C.char,
|
||
|
|
) C.int32_t {
|
||
|
|
|
||
|
|
handle := cgo.Handle(uintptr(unsafe.Pointer(userData)))
|
||
|
|
impl, ok := handle.Value().(EmbeddingBackend)
|
||
|
|
|
||
|
|
if !ok {
|
||
|
|
return 1 // error: invalid handle
|
||
|
|
}
|
||
|
|
|
||
|
|
var goTexts []string
|
||
|
|
if texts != nil {
|
||
|
|
json.Unmarshal([]byte(C.GoString(texts)), &goTexts)
|
||
|
|
|
||
|
|
}
|
||
|
|
|
||
|
|
// Call the method
|
||
|
|
result, err := impl.Embed(goTexts)
|
||
|
|
|
||
|
|
if err != nil {
|
||
|
|
cErr := C.CString(err.Error())
|
||
|
|
*outError = cErr
|
||
|
|
return 1
|
||
|
|
}
|
||
|
|
jsonBytes, _ := json.Marshal(result)
|
||
|
|
cResult := C.CString(string(jsonBytes))
|
||
|
|
*outResult = cResult
|
||
|
|
return 0 // success
|
||
|
|
}
|
||
|
|
|
||
|
|
//export goEmbeddingBackendName
|
||
|
|
func goEmbeddingBackendName(userData unsafe.Pointer, outResult **C.char, outError **C.char) C.int32_t {
|
||
|
|
|
||
|
|
handle := cgo.Handle(uintptr(unsafe.Pointer(userData)))
|
||
|
|
impl, ok := handle.Value().(EmbeddingBackend)
|
||
|
|
|
||
|
|
if !ok {
|
||
|
|
return 1
|
||
|
|
}
|
||
|
|
name := impl.Name()
|
||
|
|
cName := C.CString(name)
|
||
|
|
*outResult = cName
|
||
|
|
return 0
|
||
|
|
}
|
||
|
|
|
||
|
|
//export goEmbeddingBackendVersion
|
||
|
|
func goEmbeddingBackendVersion(userData unsafe.Pointer, outResult **C.char, outError **C.char) C.int32_t {
|
||
|
|
|
||
|
|
handle := cgo.Handle(uintptr(unsafe.Pointer(userData)))
|
||
|
|
impl, ok := handle.Value().(EmbeddingBackend)
|
||
|
|
|
||
|
|
if !ok {
|
||
|
|
return 1
|
||
|
|
}
|
||
|
|
version := impl.Version()
|
||
|
|
cVersion := C.CString(version)
|
||
|
|
*outResult = cVersion
|
||
|
|
return 0
|
||
|
|
}
|
||
|
|
|
||
|
|
//export goEmbeddingBackendInitialize
|
||
|
|
func goEmbeddingBackendInitialize(userData unsafe.Pointer, outError **C.char) C.int32_t {
|
||
|
|
|
||
|
|
handle := cgo.Handle(uintptr(unsafe.Pointer(userData)))
|
||
|
|
impl, ok := handle.Value().(EmbeddingBackend)
|
||
|
|
|
||
|
|
if !ok {
|
||
|
|
return 1
|
||
|
|
}
|
||
|
|
err := impl.Initialize()
|
||
|
|
if err != nil {
|
||
|
|
cErr := C.CString(err.Error())
|
||
|
|
*outError = cErr
|
||
|
|
return 1
|
||
|
|
}
|
||
|
|
return 0
|
||
|
|
}
|
||
|
|
|
||
|
|
//export goEmbeddingBackendShutdown
|
||
|
|
func goEmbeddingBackendShutdown(userData unsafe.Pointer, outError **C.char) C.int32_t {
|
||
|
|
|
||
|
|
handle := cgo.Handle(uintptr(unsafe.Pointer(userData)))
|
||
|
|
impl, ok := handle.Value().(EmbeddingBackend)
|
||
|
|
|
||
|
|
if !ok {
|
||
|
|
return 1
|
||
|
|
}
|
||
|
|
err := impl.Shutdown()
|
||
|
|
if err != nil {
|
||
|
|
cErr := C.CString(err.Error())
|
||
|
|
*outError = cErr
|
||
|
|
return 1
|
||
|
|
}
|
||
|
|
return 0
|
||
|
|
}
|
||
|
|
|
||
|
|
//export goEmbeddingBackendFreeUserData
|
||
|
|
func goEmbeddingBackendFreeUserData(userData unsafe.Pointer) {
|
||
|
|
|
||
|
|
// No-op to avoid cleanup-queue panics. Handles cleaned in Unregister().
|
||
|
|
}
|
||
|
|
|
||
|
|
//export goEmbeddingBackendFreeString
|
||
|
|
func goEmbeddingBackendFreeString(ptr *C.char) {
|
||
|
|
if ptr != nil {
|
||
|
|
C.free(unsafe.Pointer(ptr))
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// RegisterEmbeddingBackend registers a EmbeddingBackend implementation with the C runtime.
|
||
|
|
func RegisterEmbeddingBackend(impl EmbeddingBackend) error {
|
||
|
|
handle := cgo.NewHandle(impl)
|
||
|
|
// Build the C vtable DEBUG:c_vtable_struct=KREUZBERGKreuzbergEmbeddingBackendVTable
|
||
|
|
vtable := C.KREUZBERGKreuzbergEmbeddingBackendVTable{
|
||
|
|
dimensions: (*[0]byte)(unsafe.Pointer(C.goEmbeddingBackendDimensions)),
|
||
|
|
embed: (*[0]byte)(unsafe.Pointer(C.goEmbeddingBackendEmbed)),
|
||
|
|
name_fn: (*[0]byte)(unsafe.Pointer(C.goEmbeddingBackendName)),
|
||
|
|
version_fn: (*[0]byte)(unsafe.Pointer(C.goEmbeddingBackendVersion)),
|
||
|
|
initialize_fn: (*[0]byte)(unsafe.Pointer(C.goEmbeddingBackendInitialize)),
|
||
|
|
shutdown_fn: (*[0]byte)(unsafe.Pointer(C.goEmbeddingBackendShutdown)),
|
||
|
|
free_string: (*[0]byte)(unsafe.Pointer(C.goEmbeddingBackendFreeString)),
|
||
|
|
free_user_data: (*[0]byte)(unsafe.Pointer(C.goEmbeddingBackendFreeUserData)),
|
||
|
|
}
|
||
|
|
|
||
|
|
// Call C registration
|
||
|
|
cName := C.CString(impl.Name())
|
||
|
|
defer C.free(unsafe.Pointer(cName))
|
||
|
|
|
||
|
|
var cErr *C.char
|
||
|
|
rc := C.kreuzberg_register_embedding_backend(
|
||
|
|
cName,
|
||
|
|
vtable,
|
||
|
|
unsafe.Pointer(uintptr(handle)),
|
||
|
|
&cErr,
|
||
|
|
)
|
||
|
|
|
||
|
|
if rc != 0 {
|
||
|
|
msg := "failed to register EmbeddingBackend"
|
||
|
|
if cErr != nil {
|
||
|
|
msg = C.GoString(cErr)
|
||
|
|
C.kreuzberg_free_string(cErr)
|
||
|
|
}
|
||
|
|
handle.Delete()
|
||
|
|
return fmt.Errorf("%s", msg)
|
||
|
|
}
|
||
|
|
|
||
|
|
// Store handle by name for later cleanup on unregister
|
||
|
|
embedding_backendRegistry.store(impl.Name(), handle)
|
||
|
|
return nil
|
||
|
|
}
|
||
|
|
|
||
|
|
// UnregisterEmbeddingBackend unregisters a EmbeddingBackend implementation.
|
||
|
|
func UnregisterEmbeddingBackend(name string) error {
|
||
|
|
cName := C.CString(name)
|
||
|
|
defer C.free(unsafe.Pointer(cName))
|
||
|
|
var cErr *C.char
|
||
|
|
rc := C.kreuzberg_unregister_embedding_backend(cName, &cErr)
|
||
|
|
|
||
|
|
if rc != 0 {
|
||
|
|
msg := "failed to unregister EmbeddingBackend"
|
||
|
|
if cErr != nil {
|
||
|
|
msg = C.GoString(cErr)
|
||
|
|
C.kreuzberg_free_string(cErr)
|
||
|
|
}
|
||
|
|
return fmt.Errorf("%s", msg)
|
||
|
|
}
|
||
|
|
|
||
|
|
// Delete the handle now that Rust has unregistered the plugin
|
||
|
|
embedding_backendRegistry.delete(name)
|
||
|
|
return nil
|
||
|
|
}
|
||
|
|
|
||
|
|
// ClearEmbeddingBackends removes all registered EmbeddingBackend implementations.
|
||
|
|
func ClearEmbeddingBackends() error {
|
||
|
|
var cErr *C.char
|
||
|
|
rc := C.kreuzberg_clear_embedding_backend(&cErr)
|
||
|
|
|
||
|
|
if rc != 0 {
|
||
|
|
msg := "failed to clear EmbeddingBackend plugins"
|
||
|
|
if cErr != nil {
|
||
|
|
msg = C.GoString(cErr)
|
||
|
|
C.free(unsafe.Pointer(cErr))
|
||
|
|
}
|
||
|
|
return fmt.Errorf("%s", msg)
|
||
|
|
}
|
||
|
|
|
||
|
|
// Delete all handles now that Rust has cleared all plugins
|
||
|
|
embedding_backendRegistry.clear()
|
||
|
|
return nil
|
||
|
|
}
|
||
|
|
|
||
|
|
// DocumentExtractor defines the Go interface for the DocumentExtractor trait.
|
||
|
|
type DocumentExtractor interface {
|
||
|
|
// Name returns the plugin name.
|
||
|
|
Name() string
|
||
|
|
// Version returns the plugin version.
|
||
|
|
Version() string
|
||
|
|
// Initialize is called when the plugin is loaded.
|
||
|
|
Initialize() error
|
||
|
|
// Shutdown is called when the plugin is unloaded.
|
||
|
|
Shutdown() error
|
||
|
|
// extract_bytes
|
||
|
|
ExtractBytes(content []byte, mime_type string, config ExtractionConfig) (json.RawMessage, error)
|
||
|
|
|
||
|
|
// extract_file
|
||
|
|
ExtractFile(path string, mime_type string, config ExtractionConfig) (json.RawMessage, error)
|
||
|
|
|
||
|
|
// supported_mime_types
|
||
|
|
SupportedMimeTypes() []string
|
||
|
|
|
||
|
|
// priority
|
||
|
|
Priority() int32
|
||
|
|
|
||
|
|
// can_handle
|
||
|
|
CanHandle(_path string, _mime_type string) bool
|
||
|
|
|
||
|
|
}
|
||
|
|
|
||
|
|
//export goDocumentExtractorExtractBytes
|
||
|
|
func goDocumentExtractorExtractBytes(
|
||
|
|
userData unsafe.Pointer,
|
||
|
|
content *C.uint8_t,
|
||
|
|
contentLen C.size_t,
|
||
|
|
mime_type *C.char,
|
||
|
|
config *C.char,
|
||
|
|
outResult **C.char,
|
||
|
|
outError **C.char,
|
||
|
|
) C.int32_t {
|
||
|
|
|
||
|
|
handle := cgo.Handle(uintptr(unsafe.Pointer(userData)))
|
||
|
|
impl, ok := handle.Value().(DocumentExtractor)
|
||
|
|
|
||
|
|
if !ok {
|
||
|
|
return 1 // error: invalid handle
|
||
|
|
}
|
||
|
|
|
||
|
|
var goContent []byte
|
||
|
|
if content != nil {
|
||
|
|
goContent = unsafe.Slice((*byte)(unsafe.Pointer(content)), int(contentLen))
|
||
|
|
}
|
||
|
|
|
||
|
|
goMime_type := C.GoString(mime_type)
|
||
|
|
|
||
|
|
var goConfig ExtractionConfig
|
||
|
|
if config != nil {
|
||
|
|
json.Unmarshal([]byte(C.GoString(config)), &goConfig)
|
||
|
|
|
||
|
|
}
|
||
|
|
|
||
|
|
// Call the method
|
||
|
|
result, err := impl.ExtractBytes(goContent, goMime_type, goConfig)
|
||
|
|
|
||
|
|
if err != nil {
|
||
|
|
cErr := C.CString(err.Error())
|
||
|
|
*outError = cErr
|
||
|
|
return 1
|
||
|
|
}
|
||
|
|
cResult := C.CString(string(result))
|
||
|
|
*outResult = cResult
|
||
|
|
return 0 // success
|
||
|
|
}
|
||
|
|
|
||
|
|
//export goDocumentExtractorExtractFile
|
||
|
|
func goDocumentExtractorExtractFile(
|
||
|
|
userData unsafe.Pointer,
|
||
|
|
path *C.char,
|
||
|
|
mime_type *C.char,
|
||
|
|
config *C.char,
|
||
|
|
outResult **C.char,
|
||
|
|
outError **C.char,
|
||
|
|
) C.int32_t {
|
||
|
|
|
||
|
|
handle := cgo.Handle(uintptr(unsafe.Pointer(userData)))
|
||
|
|
impl, ok := handle.Value().(DocumentExtractor)
|
||
|
|
|
||
|
|
if !ok {
|
||
|
|
return 1 // error: invalid handle
|
||
|
|
}
|
||
|
|
|
||
|
|
goPath := C.GoString(path)
|
||
|
|
|
||
|
|
goMime_type := C.GoString(mime_type)
|
||
|
|
|
||
|
|
var goConfig ExtractionConfig
|
||
|
|
if config != nil {
|
||
|
|
json.Unmarshal([]byte(C.GoString(config)), &goConfig)
|
||
|
|
|
||
|
|
}
|
||
|
|
|
||
|
|
// Call the method
|
||
|
|
result, err := impl.ExtractFile(goPath, goMime_type, goConfig)
|
||
|
|
|
||
|
|
if err != nil {
|
||
|
|
cErr := C.CString(err.Error())
|
||
|
|
*outError = cErr
|
||
|
|
return 1
|
||
|
|
}
|
||
|
|
cResult := C.CString(string(result))
|
||
|
|
*outResult = cResult
|
||
|
|
return 0 // success
|
||
|
|
}
|
||
|
|
|
||
|
|
//export goDocumentExtractorSupportedMimeTypes
|
||
|
|
func goDocumentExtractorSupportedMimeTypes(
|
||
|
|
userData unsafe.Pointer,
|
||
|
|
outResult **C.char,
|
||
|
|
outError **C.char,
|
||
|
|
) C.int32_t {
|
||
|
|
|
||
|
|
handle := cgo.Handle(uintptr(unsafe.Pointer(userData)))
|
||
|
|
impl, ok := handle.Value().(DocumentExtractor)
|
||
|
|
|
||
|
|
if !ok {
|
||
|
|
return 1 // error: invalid handle
|
||
|
|
}
|
||
|
|
|
||
|
|
// Call the method
|
||
|
|
result := impl.SupportedMimeTypes()
|
||
|
|
|
||
|
|
jsonBytes, _ := json.Marshal(result)
|
||
|
|
cResult := C.CString(string(jsonBytes))
|
||
|
|
*outResult = cResult
|
||
|
|
return 0 // success
|
||
|
|
}
|
||
|
|
|
||
|
|
//export goDocumentExtractorPriority
|
||
|
|
func goDocumentExtractorPriority(
|
||
|
|
userData unsafe.Pointer,
|
||
|
|
outResult **C.char,
|
||
|
|
outError **C.char,
|
||
|
|
) C.int32_t {
|
||
|
|
|
||
|
|
handle := cgo.Handle(uintptr(unsafe.Pointer(userData)))
|
||
|
|
impl, ok := handle.Value().(DocumentExtractor)
|
||
|
|
|
||
|
|
if !ok {
|
||
|
|
return 1 // error: invalid handle
|
||
|
|
}
|
||
|
|
|
||
|
|
// Call the method
|
||
|
|
result := impl.Priority()
|
||
|
|
|
||
|
|
jsonBytes, _ := json.Marshal(result)
|
||
|
|
cResult := C.CString(string(jsonBytes))
|
||
|
|
*outResult = cResult
|
||
|
|
return 0 // success
|
||
|
|
}
|
||
|
|
|
||
|
|
//export goDocumentExtractorCanHandle
|
||
|
|
func goDocumentExtractorCanHandle(
|
||
|
|
userData unsafe.Pointer,
|
||
|
|
_path *C.char,
|
||
|
|
_mime_type *C.char,
|
||
|
|
outResult **C.char,
|
||
|
|
outError **C.char,
|
||
|
|
) C.int32_t {
|
||
|
|
|
||
|
|
handle := cgo.Handle(uintptr(unsafe.Pointer(userData)))
|
||
|
|
impl, ok := handle.Value().(DocumentExtractor)
|
||
|
|
|
||
|
|
if !ok {
|
||
|
|
return 1 // error: invalid handle
|
||
|
|
}
|
||
|
|
|
||
|
|
go_path := C.GoString(_path)
|
||
|
|
|
||
|
|
go_mime_type := C.GoString(_mime_type)
|
||
|
|
|
||
|
|
// Call the method
|
||
|
|
result := impl.CanHandle(go_path, go_mime_type)
|
||
|
|
|
||
|
|
jsonBytes, _ := json.Marshal(result)
|
||
|
|
cResult := C.CString(string(jsonBytes))
|
||
|
|
*outResult = cResult
|
||
|
|
return 0 // success
|
||
|
|
}
|
||
|
|
|
||
|
|
//export goDocumentExtractorName
|
||
|
|
func goDocumentExtractorName(userData unsafe.Pointer, outResult **C.char, outError **C.char) C.int32_t {
|
||
|
|
|
||
|
|
handle := cgo.Handle(uintptr(unsafe.Pointer(userData)))
|
||
|
|
impl, ok := handle.Value().(DocumentExtractor)
|
||
|
|
|
||
|
|
if !ok {
|
||
|
|
return 1
|
||
|
|
}
|
||
|
|
name := impl.Name()
|
||
|
|
cName := C.CString(name)
|
||
|
|
*outResult = cName
|
||
|
|
return 0
|
||
|
|
}
|
||
|
|
|
||
|
|
//export goDocumentExtractorVersion
|
||
|
|
func goDocumentExtractorVersion(userData unsafe.Pointer, outResult **C.char, outError **C.char) C.int32_t {
|
||
|
|
|
||
|
|
handle := cgo.Handle(uintptr(unsafe.Pointer(userData)))
|
||
|
|
impl, ok := handle.Value().(DocumentExtractor)
|
||
|
|
|
||
|
|
if !ok {
|
||
|
|
return 1
|
||
|
|
}
|
||
|
|
version := impl.Version()
|
||
|
|
cVersion := C.CString(version)
|
||
|
|
*outResult = cVersion
|
||
|
|
return 0
|
||
|
|
}
|
||
|
|
|
||
|
|
//export goDocumentExtractorInitialize
|
||
|
|
func goDocumentExtractorInitialize(userData unsafe.Pointer, outError **C.char) C.int32_t {
|
||
|
|
|
||
|
|
handle := cgo.Handle(uintptr(unsafe.Pointer(userData)))
|
||
|
|
impl, ok := handle.Value().(DocumentExtractor)
|
||
|
|
|
||
|
|
if !ok {
|
||
|
|
return 1
|
||
|
|
}
|
||
|
|
err := impl.Initialize()
|
||
|
|
if err != nil {
|
||
|
|
cErr := C.CString(err.Error())
|
||
|
|
*outError = cErr
|
||
|
|
return 1
|
||
|
|
}
|
||
|
|
return 0
|
||
|
|
}
|
||
|
|
|
||
|
|
//export goDocumentExtractorShutdown
|
||
|
|
func goDocumentExtractorShutdown(userData unsafe.Pointer, outError **C.char) C.int32_t {
|
||
|
|
|
||
|
|
handle := cgo.Handle(uintptr(unsafe.Pointer(userData)))
|
||
|
|
impl, ok := handle.Value().(DocumentExtractor)
|
||
|
|
|
||
|
|
if !ok {
|
||
|
|
return 1
|
||
|
|
}
|
||
|
|
err := impl.Shutdown()
|
||
|
|
if err != nil {
|
||
|
|
cErr := C.CString(err.Error())
|
||
|
|
*outError = cErr
|
||
|
|
return 1
|
||
|
|
}
|
||
|
|
return 0
|
||
|
|
}
|
||
|
|
|
||
|
|
//export goDocumentExtractorFreeUserData
|
||
|
|
func goDocumentExtractorFreeUserData(userData unsafe.Pointer) {
|
||
|
|
|
||
|
|
// No-op to avoid cleanup-queue panics. Handles cleaned in Unregister().
|
||
|
|
}
|
||
|
|
|
||
|
|
//export goDocumentExtractorFreeString
|
||
|
|
func goDocumentExtractorFreeString(ptr *C.char) {
|
||
|
|
if ptr != nil {
|
||
|
|
C.free(unsafe.Pointer(ptr))
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// RegisterDocumentExtractor registers a DocumentExtractor implementation with the C runtime.
|
||
|
|
func RegisterDocumentExtractor(impl DocumentExtractor) error {
|
||
|
|
handle := cgo.NewHandle(impl)
|
||
|
|
// Build the C vtable DEBUG:c_vtable_struct=KREUZBERGKreuzbergDocumentExtractorVTable
|
||
|
|
vtable := C.KREUZBERGKreuzbergDocumentExtractorVTable{
|
||
|
|
extract_bytes: (*[0]byte)(unsafe.Pointer(C.goDocumentExtractorExtractBytes)),
|
||
|
|
extract_file: (*[0]byte)(unsafe.Pointer(C.goDocumentExtractorExtractFile)),
|
||
|
|
supported_mime_types: (*[0]byte)(unsafe.Pointer(C.goDocumentExtractorSupportedMimeTypes)),
|
||
|
|
priority: (*[0]byte)(unsafe.Pointer(C.goDocumentExtractorPriority)),
|
||
|
|
can_handle: (*[0]byte)(unsafe.Pointer(C.goDocumentExtractorCanHandle)),
|
||
|
|
name_fn: (*[0]byte)(unsafe.Pointer(C.goDocumentExtractorName)),
|
||
|
|
version_fn: (*[0]byte)(unsafe.Pointer(C.goDocumentExtractorVersion)),
|
||
|
|
initialize_fn: (*[0]byte)(unsafe.Pointer(C.goDocumentExtractorInitialize)),
|
||
|
|
shutdown_fn: (*[0]byte)(unsafe.Pointer(C.goDocumentExtractorShutdown)),
|
||
|
|
free_string: (*[0]byte)(unsafe.Pointer(C.goDocumentExtractorFreeString)),
|
||
|
|
free_user_data: (*[0]byte)(unsafe.Pointer(C.goDocumentExtractorFreeUserData)),
|
||
|
|
}
|
||
|
|
|
||
|
|
// Call C registration
|
||
|
|
cName := C.CString(impl.Name())
|
||
|
|
defer C.free(unsafe.Pointer(cName))
|
||
|
|
|
||
|
|
var cErr *C.char
|
||
|
|
rc := C.kreuzberg_register_document_extractor(
|
||
|
|
cName,
|
||
|
|
vtable,
|
||
|
|
unsafe.Pointer(uintptr(handle)),
|
||
|
|
&cErr,
|
||
|
|
)
|
||
|
|
|
||
|
|
if rc != 0 {
|
||
|
|
msg := "failed to register DocumentExtractor"
|
||
|
|
if cErr != nil {
|
||
|
|
msg = C.GoString(cErr)
|
||
|
|
C.kreuzberg_free_string(cErr)
|
||
|
|
}
|
||
|
|
handle.Delete()
|
||
|
|
return fmt.Errorf("%s", msg)
|
||
|
|
}
|
||
|
|
|
||
|
|
// Store handle by name for later cleanup on unregister
|
||
|
|
document_extractorRegistry.store(impl.Name(), handle)
|
||
|
|
return nil
|
||
|
|
}
|
||
|
|
|
||
|
|
// UnregisterDocumentExtractor unregisters a DocumentExtractor implementation.
|
||
|
|
func UnregisterDocumentExtractor(name string) error {
|
||
|
|
cName := C.CString(name)
|
||
|
|
defer C.free(unsafe.Pointer(cName))
|
||
|
|
var cErr *C.char
|
||
|
|
rc := C.kreuzberg_unregister_document_extractor(cName, &cErr)
|
||
|
|
|
||
|
|
if rc != 0 {
|
||
|
|
msg := "failed to unregister DocumentExtractor"
|
||
|
|
if cErr != nil {
|
||
|
|
msg = C.GoString(cErr)
|
||
|
|
C.kreuzberg_free_string(cErr)
|
||
|
|
}
|
||
|
|
return fmt.Errorf("%s", msg)
|
||
|
|
}
|
||
|
|
|
||
|
|
// Delete the handle now that Rust has unregistered the plugin
|
||
|
|
document_extractorRegistry.delete(name)
|
||
|
|
return nil
|
||
|
|
}
|
||
|
|
|
||
|
|
// ClearDocumentExtractors removes all registered DocumentExtractor implementations.
|
||
|
|
func ClearDocumentExtractors() error {
|
||
|
|
var cErr *C.char
|
||
|
|
rc := C.kreuzberg_clear_document_extractor(&cErr)
|
||
|
|
|
||
|
|
if rc != 0 {
|
||
|
|
msg := "failed to clear DocumentExtractor plugins"
|
||
|
|
if cErr != nil {
|
||
|
|
msg = C.GoString(cErr)
|
||
|
|
C.free(unsafe.Pointer(cErr))
|
||
|
|
}
|
||
|
|
return fmt.Errorf("%s", msg)
|
||
|
|
}
|
||
|
|
|
||
|
|
// Delete all handles now that Rust has cleared all plugins
|
||
|
|
document_extractorRegistry.clear()
|
||
|
|
return nil
|
||
|
|
}
|
||
|
|
|
||
|
|
// Renderer defines the Go interface for the Renderer trait.
|
||
|
|
type Renderer interface {
|
||
|
|
// Name returns the plugin name.
|
||
|
|
Name() string
|
||
|
|
// Version returns the plugin version.
|
||
|
|
Version() string
|
||
|
|
// Initialize is called when the plugin is loaded.
|
||
|
|
Initialize() error
|
||
|
|
// Shutdown is called when the plugin is unloaded.
|
||
|
|
Shutdown() error
|
||
|
|
// render
|
||
|
|
Render(doc json.RawMessage) (string, error)
|
||
|
|
|
||
|
|
}
|
||
|
|
|
||
|
|
//export goRendererRender
|
||
|
|
func goRendererRender(
|
||
|
|
userData unsafe.Pointer,
|
||
|
|
doc *C.char,
|
||
|
|
outResult **C.char,
|
||
|
|
outError **C.char,
|
||
|
|
) C.int32_t {
|
||
|
|
|
||
|
|
handle := cgo.Handle(uintptr(unsafe.Pointer(userData)))
|
||
|
|
impl, ok := handle.Value().(Renderer)
|
||
|
|
|
||
|
|
if !ok {
|
||
|
|
return 1 // error: invalid handle
|
||
|
|
}
|
||
|
|
|
||
|
|
var goDoc json.RawMessage
|
||
|
|
if doc != nil {
|
||
|
|
goDoc = json.RawMessage(C.GoString(doc))
|
||
|
|
}
|
||
|
|
|
||
|
|
// Call the method
|
||
|
|
result, err := impl.Render(goDoc)
|
||
|
|
|
||
|
|
if err != nil {
|
||
|
|
cErr := C.CString(err.Error())
|
||
|
|
*outError = cErr
|
||
|
|
return 1
|
||
|
|
}
|
||
|
|
cResult := C.CString(result)
|
||
|
|
*outResult = cResult
|
||
|
|
return 0 // success
|
||
|
|
}
|
||
|
|
|
||
|
|
//export goRendererName
|
||
|
|
func goRendererName(userData unsafe.Pointer, outResult **C.char, outError **C.char) C.int32_t {
|
||
|
|
|
||
|
|
handle := cgo.Handle(uintptr(unsafe.Pointer(userData)))
|
||
|
|
impl, ok := handle.Value().(Renderer)
|
||
|
|
|
||
|
|
if !ok {
|
||
|
|
return 1
|
||
|
|
}
|
||
|
|
name := impl.Name()
|
||
|
|
cName := C.CString(name)
|
||
|
|
*outResult = cName
|
||
|
|
return 0
|
||
|
|
}
|
||
|
|
|
||
|
|
//export goRendererVersion
|
||
|
|
func goRendererVersion(userData unsafe.Pointer, outResult **C.char, outError **C.char) C.int32_t {
|
||
|
|
|
||
|
|
handle := cgo.Handle(uintptr(unsafe.Pointer(userData)))
|
||
|
|
impl, ok := handle.Value().(Renderer)
|
||
|
|
|
||
|
|
if !ok {
|
||
|
|
return 1
|
||
|
|
}
|
||
|
|
version := impl.Version()
|
||
|
|
cVersion := C.CString(version)
|
||
|
|
*outResult = cVersion
|
||
|
|
return 0
|
||
|
|
}
|
||
|
|
|
||
|
|
//export goRendererInitialize
|
||
|
|
func goRendererInitialize(userData unsafe.Pointer, outError **C.char) C.int32_t {
|
||
|
|
|
||
|
|
handle := cgo.Handle(uintptr(unsafe.Pointer(userData)))
|
||
|
|
impl, ok := handle.Value().(Renderer)
|
||
|
|
|
||
|
|
if !ok {
|
||
|
|
return 1
|
||
|
|
}
|
||
|
|
err := impl.Initialize()
|
||
|
|
if err != nil {
|
||
|
|
cErr := C.CString(err.Error())
|
||
|
|
*outError = cErr
|
||
|
|
return 1
|
||
|
|
}
|
||
|
|
return 0
|
||
|
|
}
|
||
|
|
|
||
|
|
//export goRendererShutdown
|
||
|
|
func goRendererShutdown(userData unsafe.Pointer, outError **C.char) C.int32_t {
|
||
|
|
|
||
|
|
handle := cgo.Handle(uintptr(unsafe.Pointer(userData)))
|
||
|
|
impl, ok := handle.Value().(Renderer)
|
||
|
|
|
||
|
|
if !ok {
|
||
|
|
return 1
|
||
|
|
}
|
||
|
|
err := impl.Shutdown()
|
||
|
|
if err != nil {
|
||
|
|
cErr := C.CString(err.Error())
|
||
|
|
*outError = cErr
|
||
|
|
return 1
|
||
|
|
}
|
||
|
|
return 0
|
||
|
|
}
|
||
|
|
|
||
|
|
//export goRendererFreeUserData
|
||
|
|
func goRendererFreeUserData(userData unsafe.Pointer) {
|
||
|
|
|
||
|
|
// No-op to avoid cleanup-queue panics. Handles cleaned in Unregister().
|
||
|
|
}
|
||
|
|
|
||
|
|
//export goRendererFreeString
|
||
|
|
func goRendererFreeString(ptr *C.char) {
|
||
|
|
if ptr != nil {
|
||
|
|
C.free(unsafe.Pointer(ptr))
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// RegisterRenderer registers a Renderer implementation with the C runtime.
|
||
|
|
func RegisterRenderer(impl Renderer) error {
|
||
|
|
handle := cgo.NewHandle(impl)
|
||
|
|
// Build the C vtable DEBUG:c_vtable_struct=KREUZBERGKreuzbergRendererVTable
|
||
|
|
vtable := C.KREUZBERGKreuzbergRendererVTable{
|
||
|
|
render: (*[0]byte)(unsafe.Pointer(C.goRendererRender)),
|
||
|
|
name_fn: (*[0]byte)(unsafe.Pointer(C.goRendererName)),
|
||
|
|
version_fn: (*[0]byte)(unsafe.Pointer(C.goRendererVersion)),
|
||
|
|
initialize_fn: (*[0]byte)(unsafe.Pointer(C.goRendererInitialize)),
|
||
|
|
shutdown_fn: (*[0]byte)(unsafe.Pointer(C.goRendererShutdown)),
|
||
|
|
free_string: (*[0]byte)(unsafe.Pointer(C.goRendererFreeString)),
|
||
|
|
free_user_data: (*[0]byte)(unsafe.Pointer(C.goRendererFreeUserData)),
|
||
|
|
}
|
||
|
|
|
||
|
|
// Call C registration
|
||
|
|
cName := C.CString(impl.Name())
|
||
|
|
defer C.free(unsafe.Pointer(cName))
|
||
|
|
|
||
|
|
var cErr *C.char
|
||
|
|
rc := C.kreuzberg_register_renderer(
|
||
|
|
cName,
|
||
|
|
vtable,
|
||
|
|
unsafe.Pointer(uintptr(handle)),
|
||
|
|
&cErr,
|
||
|
|
)
|
||
|
|
|
||
|
|
if rc != 0 {
|
||
|
|
msg := "failed to register Renderer"
|
||
|
|
if cErr != nil {
|
||
|
|
msg = C.GoString(cErr)
|
||
|
|
C.kreuzberg_free_string(cErr)
|
||
|
|
}
|
||
|
|
handle.Delete()
|
||
|
|
return fmt.Errorf("%s", msg)
|
||
|
|
}
|
||
|
|
|
||
|
|
// Store handle by name for later cleanup on unregister
|
||
|
|
rendererRegistry.store(impl.Name(), handle)
|
||
|
|
return nil
|
||
|
|
}
|
||
|
|
|
||
|
|
// UnregisterRenderer unregisters a Renderer implementation.
|
||
|
|
func UnregisterRenderer(name string) error {
|
||
|
|
cName := C.CString(name)
|
||
|
|
defer C.free(unsafe.Pointer(cName))
|
||
|
|
var cErr *C.char
|
||
|
|
rc := C.kreuzberg_unregister_renderer(cName, &cErr)
|
||
|
|
|
||
|
|
if rc != 0 {
|
||
|
|
msg := "failed to unregister Renderer"
|
||
|
|
if cErr != nil {
|
||
|
|
msg = C.GoString(cErr)
|
||
|
|
C.kreuzberg_free_string(cErr)
|
||
|
|
}
|
||
|
|
return fmt.Errorf("%s", msg)
|
||
|
|
}
|
||
|
|
|
||
|
|
// Delete the handle now that Rust has unregistered the plugin
|
||
|
|
rendererRegistry.delete(name)
|
||
|
|
return nil
|
||
|
|
}
|
||
|
|
|
||
|
|
// ClearRenderers removes all registered Renderer implementations.
|
||
|
|
func ClearRenderers() error {
|
||
|
|
var cErr *C.char
|
||
|
|
rc := C.kreuzberg_clear_renderer(&cErr)
|
||
|
|
|
||
|
|
if rc != 0 {
|
||
|
|
msg := "failed to clear Renderer plugins"
|
||
|
|
if cErr != nil {
|
||
|
|
msg = C.GoString(cErr)
|
||
|
|
C.free(unsafe.Pointer(cErr))
|
||
|
|
}
|
||
|
|
return fmt.Errorf("%s", msg)
|
||
|
|
}
|
||
|
|
|
||
|
|
// Delete all handles now that Rust has cleared all plugins
|
||
|
|
rendererRegistry.clear()
|
||
|
|
return nil
|
||
|
|
}
|