diff options
author | bptato <nincsnevem662@gmail.com> | 2024-12-08 17:45:27 +0100 |
---|---|---|
committer | bptato <nincsnevem662@gmail.com> | 2024-12-08 18:10:28 +0100 |
commit | 8974f7deaaecd84b5f95e40bf935f735253521f3 (patch) | |
tree | 2ed5a61ba633dbae71596a85734f7ffe31576d3c /src | |
parent | f6f340bfaa65657e78f93adb1fa715261c466fbc (diff) | |
download | chawan-8974f7deaaecd84b5f95e40bf935f735253521f3.tar.gz |
response: simplify text()
It gets copied once anyway, so just use a blob. I guess I could skip the copy with some effort, but the 4 lines implementation is too attractive :P This is still an improvement, as it doesn't needlessly zero-fill the buffer on realloc. (I've also removed the final realloc from blob, as it seemed quite pointless. Using Content-Length could help... except it doesn't, because it refers to the encoded length. Ugh.)
Diffstat (limited to 'src')
-rw-r--r-- | src/server/response.nim | 49 | ||||
-rw-r--r-- | src/types/blob.nim | 7 |
2 files changed, 14 insertions, 42 deletions
diff --git a/src/server/response.nim b/src/server/response.nim index 37ff2434..1f68932a 100644 --- a/src/server/response.nim +++ b/src/server/response.nim @@ -124,49 +124,8 @@ proc resume*(response: Response) = response.resumeFun(response.outputId) response.resumeFun = nil -type TextOpaque = ref object of RootObj - buf: string - bodyRead: Promise[JSResult[string]] - const BufferSize = 4096 -proc onReadText(response: Response) = - let opaque = TextOpaque(response.opaque) - while true: - let olen = opaque.buf.len - try: - opaque.buf.setLen(olen + BufferSize) - let n = response.body.recvData(addr opaque.buf[olen], BufferSize) - opaque.buf.setLen(olen + n) - if n == 0: - break - except ErrorAgain: - opaque.buf.setLen(olen) - break - -proc onFinishText(response: Response; success: bool) = - let opaque = TextOpaque(response.opaque) - let bodyRead = opaque.bodyRead - if success: - let charset = response.getCharset(CHARSET_UTF_8) - bodyRead.resolve(JSResult[string].ok(opaque.buf.decodeAll(charset))) - else: - bodyRead.resolve(JSResult[string].err(newFetchTypeError())) - -proc text*(response: Response): Promise[JSResult[string]] {.jsfunc.} = - if response.body == nil: - return newResolvedPromise(JSResult[string].ok("")) - if response.bodyUsed: - let err = newTypeError("Body has already been consumed") - return newResolvedPromise(JSResult[string].err(err)) - let opaque = TextOpaque(bodyRead: Promise[JSResult[string]]()) - response.opaque = opaque - response.onRead = onReadText - response.onFinish = onFinishText - response.bodyUsed = true - response.resume() - return opaque.bodyRead - type BlobOpaque = ref object of RootObj p: pointer len: int @@ -194,7 +153,7 @@ proc onFinishBlob(response: Response; success: bool) = let opaque = BlobOpaque(response.opaque) let bodyRead = opaque.bodyRead if success: - let p = realloc(opaque.p, opaque.len) + let p = opaque.p opaque.p = nil let blob = if p == nil: newBlob(nil, 0, opaque.contentType, nil) @@ -225,6 +184,12 @@ proc blob*(response: Response): Promise[JSResult[Blob]] {.jsfunc.} = response.resume() return opaque.bodyRead +proc text*(response: Response): Promise[JSResult[string]] {.jsfunc.} = + return response.blob().then(proc(res: JSResult[Blob]): JSResult[string] = + let blob = ?res + return ok(blob.toOpenArray().toValidUTF8()) + ) + proc json(ctx: JSContext; this: Response): Promise[JSValue] {.jsfunc.} = return this.text().then(proc(s: JSResult[string]): JSValue = if s.isNone: diff --git a/src/types/blob.nim b/src/types/blob.nim index f21d0954..689883a8 100644 --- a/src/types/blob.nim +++ b/src/types/blob.nim @@ -77,6 +77,13 @@ proc deallocBlob*(opaque, p: pointer) = if p != nil: dealloc(p) +template toOpenArray*(blob: Blob): openArray[char] = + let p = cast[ptr UncheckedArray[char]](blob.buffer) + if p != nil: + p.toOpenArray(0, blob.size - 1) + else: + [] + proc finalize(blob: Blob) {.jsfin.} = if blob.fd.isSome: discard close(blob.fd.get) |