diff options
Diffstat (limited to 'adapter/img/jebp.nim')
-rw-r--r-- | adapter/img/jebp.nim | 67 |
1 files changed, 46 insertions, 21 deletions
diff --git a/adapter/img/jebp.nim b/adapter/img/jebp.nim index ec3c9073..03d72d59 100644 --- a/adapter/img/jebp.nim +++ b/adapter/img/jebp.nim @@ -1,5 +1,6 @@ import std/options import std/os +import std/posix import std/strutils import utils/sandbox @@ -17,6 +18,9 @@ else: {.passc: "-I" & currentSourcePath().parentDir().} +const STDIN_FILENO = 0 +const STDOUT_FILENO = 1 + {.push header: "jebp.h".} type jebp_io_callbacks {.importc.} = object @@ -48,13 +52,36 @@ proc jebp_free_image(image: ptr jebp_image_t) {.importc.} {.pop.} proc myRead(data: pointer; size: csize_t; user: pointer): csize_t {.cdecl.} = - return csize_t(stdin.readBuffer(data, size)) + var n = csize_t(0) + while n < size: + let i = read(STDIN_FILENO, addr cast[ptr UncheckedArray[char]](data)[n], + int(size - n)) + if i == 0: + break + n += csize_t(i) + return n proc stbir_resize_uint8(input_pixels: ptr uint8; input_w, input_h, input_stride_in_bytes: cint; output_pixels: ptr uint8; output_w, output_h, output_stride_in_bytes, num_channels: cint): cint {.importc.} +proc writeAll(data: pointer; size: int) = + var n = 0 + while n < size: + let i = write(STDOUT_FILENO, addr cast[ptr UncheckedArray[uint8]](data)[n], + int(size) - n) + assert i >= 0 + n += i + +proc puts(s: string) = + if s.len > 0: + writeAll(unsafeAddr s[0], s.len) + +proc die(s: string) {.noreturn.} = + puts(s) + quit(1) + proc main() = enterNetworkSandbox() let scheme = getEnv("MAPPED_URI_SCHEME") @@ -62,8 +89,7 @@ proc main() = case getEnv("MAPPED_URI_PATH") of "decode": if f != "webp": - stdout.write("Cha-Control: ConnectionError 1 unknown format " & f) - return + die("Cha-Control: ConnectionError 1 unknown format " & f) let headers = getEnv("REQUEST_HEADERS") var targetWidth = cint(-1) var targetHeight = cint(-1) @@ -76,13 +102,11 @@ proc main() = of "Cha-Image-Target-Dimensions": let s = v.split('x') if s.len != 2: - stdout.write("Cha-Control: ConnectionError 1 wrong dimensions") - return + die("Cha-Control: ConnectionError 1 wrong dimensions\n") let w = parseUInt32(s[0], allowSign = false) let h = parseUInt32(s[1], allowSign = false) if w.isNone or w.isNone: - stdout.write("Cha-Control: ConnectionError 1 wrong dimensions") - return + die("Cha-Control: ConnectionError 1 wrong dimensions\n") targetWidth = cint(w.get) targetHeight = cint(h.get) var image = jebp_image_t() @@ -90,32 +114,33 @@ proc main() = if infoOnly: let res = jebp_read_size_from_callbacks(addr image, addr cb, nil) if res == 0: - stdout.write("Cha-Image-Dimensions: " & $image.width & "x" & + puts("Cha-Image-Dimensions: " & $image.width & "x" & $image.height & "\n\n") + quit(0) else: - stdout.write("Cha-Control: ConnectionError 1 jepb error " & + die("Cha-Control: ConnectionError 1 jepb error " & $jebp_error_string(res)) - return let res = jebp_read_from_callbacks(addr image, addr cb, nil) if res != 0: - stdout.write("Cha-Control: ConnectionError 1 jebp error " & + die("Cha-Control: ConnectionError 1 jebp error " & $jebp_error_string(res)) elif targetWidth != -1 and targetHeight != -1: - let p2 = cast[ptr uint8](alloc(targetWidth * targetHeight * 4)) + let hdr = "Cha-Image-Dimensions: " & $targetWidth & "x" & $targetHeight & + "\n\n" + let p2 = cast[ptr UncheckedArray[uint8]](alloc(hdr.len + + targetWidth * targetHeight * 4)) + copyMem(addr p2[0], unsafeAddr hdr[0], hdr.len) doAssert stbir_resize_uint8(cast[ptr uint8](image.pixels), image.width, - image.height, 0, p2, targetWidth, targetHeight, 0, 4) == 1 - stdout.write("Cha-Image-Dimensions: " & $targetWidth & "x" & - $targetHeight & "\n\n") - discard stdout.writeBuffer(p2, targetWidth * targetHeight * 4) + image.height, 0, addr p2[hdr.len], targetWidth, targetHeight, 0, 4) == 1 + writeAll(p2, hdr.len + targetWidth * targetHeight * 4) dealloc(p2) jebp_free_image(addr image) else: - stdout.write("Cha-Image-Dimensions: " & $image.width & "x" & - $image.height & "\n\n") - discard stdout.writeBuffer(cast[ptr uint8](image.pixels), image.width * - image.height * 4) + puts("Cha-Image-Dimensions: " & $image.width & "x" & $image.height & + "\n\n") + writeAll(image.pixels, image.width * image.height * 4) jebp_free_image(addr image) of "encode": - stdout.write("Cha-Control: ConnectionError 1 not supported") + die("Cha-Control: ConnectionError 1 not supported") main() |