diff options
author | bptato <nincsnevem662@gmail.com> | 2024-11-15 17:06:53 +0100 |
---|---|---|
committer | bptato <nincsnevem662@gmail.com> | 2024-11-15 17:06:53 +0100 |
commit | def4ceccfb77afd74b1dd1273b66d036b766fd5f (patch) | |
tree | 8fb976f0ebe632029afe2ee9542d31b88e4f23d1 /src/html/jsencoding.nim | |
parent | fd10019d8b8a1b5dcb0026521fa8f5f072c3a10a (diff) | |
download | chawan-def4ceccfb77afd74b1dd1273b66d036b766fd5f.tar.gz |
js: reorganize modules, update docs
most of it has already been moved to monoucha, and the rest fits better in other directories. also, move urimethodmap to config
Diffstat (limited to 'src/html/jsencoding.nim')
-rw-r--r-- | src/html/jsencoding.nim | 100 |
1 files changed, 100 insertions, 0 deletions
diff --git a/src/html/jsencoding.nim b/src/html/jsencoding.nim new file mode 100644 index 00000000..7aae5eb2 --- /dev/null +++ b/src/html/jsencoding.nim @@ -0,0 +1,100 @@ +import chagashi/charset +import chagashi/decoder +import monoucha/javascript +import monoucha/jserror +import monoucha/jstypes +import monoucha/quickjs +import types/opt + +type + JSTextEncoder = ref object + + JSTextDecoder = ref object + encoding: Charset + ignoreBOM {.jsget.}: bool + errorMode: DecoderErrorMode + stream: bool + bomSeen: bool + tdctx: TextDecoderContext + +jsDestructor(JSTextDecoder) +jsDestructor(JSTextEncoder) + +type TextDecoderOptions = object of JSDict + fatal {.jsdefault.}: bool + ignoreBOM {.jsdefault.}: bool + +func newJSTextDecoder(label = "utf-8"; options = TextDecoderOptions()): + JSResult[JSTextDecoder] {.jsctor.} = + let encoding = getCharset(label) + if encoding in {CHARSET_UNKNOWN, CHARSET_REPLACEMENT}: + return errRangeError("Invalid encoding label") + let errorMode = if options.fatal: demFatal else: demReplacement + return ok(JSTextDecoder( + ignoreBOM: options.ignoreBOM, + errorMode: errorMode, + tdctx: initTextDecoderContext(encoding, errorMode), + encoding: encoding + )) + +func fatal(this: JSTextDecoder): bool {.jsfget.} = + return this.errorMode == demFatal + +type TextDecodeOptions = object of JSDict + stream {.jsdefault.}: bool + +#TODO AllowSharedBufferSource +proc decode(ctx: JSContext; this: JSTextDecoder; + input = none(JSArrayBufferView); options = TextDecodeOptions()): JSValue + {.jsfunc.} = + if not this.stream: + this.tdctx = initTextDecoderContext(this.encoding, this.errorMode) + this.bomSeen = false + this.stream = options.stream + if input.isSome: + let input = input.get + let H = int(input.abuf.len) - 1 + var oq = "" + let stream = this.stream + for chunk in this.tdctx.decode(input.abuf.p.toOpenArray(0, H), not stream): + oq &= chunk + if this.tdctx.failed: + this.tdctx.failed = false + return JS_ThrowTypeError(ctx, "failed to decode string") + return JS_NewStringLen(ctx, cstring(oq), csize_t(oq.len)) + return JS_NewString(ctx, "") + +func jencoding(this: JSTextDecoder): string {.jsfget: "encoding".} = + return $this.encoding + +func newTextEncoder(): JSTextEncoder {.jsctor.} = + return JSTextEncoder() + +func jencoding(this: JSTextEncoder): string {.jsfget: "encoding".} = + return "utf-8" + +proc dealloc_wrap(rt: JSRuntime; opaque, p: pointer) {.cdecl.} = + dealloc(p) + +proc encode(this: JSTextEncoder; input = ""): JSUint8Array {.jsfunc.} = + # we have to validate input first :/ + #TODO it is possible to do less copies here... + var input = input.toValidUTF8() + let buf = cast[ptr UncheckedArray[uint8]](alloc(input.len)) + copyMem(buf, addr input[0], input.len) + let abuf = JSArrayBuffer( + p: buf, + len: csize_t(input.len), + dealloc: dealloc_wrap + ) + return JSUint8Array( + abuf: abuf, + offset: 0, + nmemb: csize_t(input.len) + ) + +#TODO encodeInto + +proc addEncodingModule*(ctx: JSContext) = + ctx.registerType(JSTextDecoder, name = "TextDecoder") + ctx.registerType(JSTextEncoder, name = "TextEncoder") |