Programming Language

Nocter

A self-contained systems language built around simplicity, encapsulation, and foolproof design.

/examples/async-http/streaming.nct

streaming.nct

use std/io.Reader
use std/string.String
use std/task
use std/task.Timeout
use std/time.Duration
use std/vec.Vec

const STREAM_BUFFER_BYTES: usize = 8192

const STREAM_LIMIT_BYTES: usize = 65536

async func read_before<R>(
    source: &+R,
    output: &+[u8],
    timeout: Duration,
): usize! where R impl Reader {
    let pending = task.with_timeout(source.read(output), timeout)
    match await pending {
        Timeout.completed(result) { return move result? }
        Timeout.elapsed {
            return error.new("async-http.timeout", "byte input exceeded the example timeout")
        }
    }
}

async func collect_text_before<R>(source: &+R, timeout: Duration): String! where R impl Reader {
    var bytes: Vec<u8> = Vec.empty()
    var scratch: Vec<u8> = Vec.with_capacity(STREAM_BUFFER_BYTES)
    while scratch.len() < STREAM_BUFFER_BYTES { scratch.push(0) }
    loop {
        let received = await read_before(source, &+scratch, timeout)?
        if received == 0 { return String.from_utf8(&bytes)? }
        if received > scratch.len() || bytes.len() > STREAM_LIMIT_BYTES - received {
            return error.new("async-http.limit", "byte input exceeded the example limit")
        }
        bytes.reserve(received)
        var offset: usize = 0
        while offset < received {
            bytes.push(scratch[offset])
            offset += 1
        }
    }
}