<commit_before>import ceylon.file { Path, File, parsePath }
import ceylon.io { newOpenFile, OpenFile }
import ceylon.io.buffer { ByteBuffer, newByteBuffer }
import ceylon.net.http.server { Response, Request, Exception }
import ceylon.net.http { contentType, contentLength }


"Endpoint for serving static files."
by("<NAME>")
shared void serveStaticFile(
                externalPath, 
                String fileMapper(Request request) => request.path,
                EndpointOptions endpointOptions = EndpointOptions())
        (Request request, Response response, Callable<Anything, []> complete) {
    
    "Root directory containing files."
    String externalPath;
    
    Path filePath = parsePath(externalPath + fileMapper(request));
    if (is File file = filePath.resource) {
        //TODO log
        //print("Serving file: ``filePath.absolutePath.string``");
        
        value openFile = newOpenFile(file);

        variable Integer available = file.size;
        response.addHeader(contentLength(available.string));
        if (is String cntType = file.contentType) {
            response.addHeader(contentType(cntType));
        }

        void onComplete() {
            openFile.close();
            complete();
        }

        FileWritter(openFile, response, onComplete, endpointOptions).send();

    } else {
        response.responseStatus=404;
        //TODO log
        //print("file does not exist");
    }
}

class FileWritter(OpenFile openFile, Response response, void completed(), EndpointOptions endpointOptions) {
    variable Integer available = openFile.size;
    ByteBuffer byteBuffer = newByteBuffer(endpointOptions.outputBufferSize);

    shared void send() {
        read();
    }

    void read() {
        if (available > 0) {
            value read = openFile.read(byteBuffer);
            if (read == -1) {
                available = 0;
            } else {
                available -= read;
            }
            byteBuffer.flip();
            write();
        } else {
            completed();
        }
    }
    <commit_msg>Exit if file cannot be read & optimize buffer allocation.<commit_after>import ceylon.file { Path, File, parsePath }
import ceylon.io { newOpenFile, OpenFile }
import ceylon.io.buffer { ByteBuffer, newByteBuffer }
import ceylon.net.http.server { Response, Request, Exception }
import ceylon.net.http { contentType, contentLength }


"Endpoint for serving static files."
by("<NAME>")
shared void serveStaticFile(
                externalPath, 
                String fileMapper(Request request) => request.path,
                EndpointOptions endpointOptions = EndpointOptions())
        (Request request, Response response, Callable<Anything, []> complete) {
    
    "Root directory containing files."
    String externalPath;
    
    Path filePath = parsePath(externalPath + fileMapper(request));
    if (is File file = filePath.resource) {
        //TODO log
        //print("Serving file: ``filePath.absolutePath.string``");
        
        value openFile = newOpenFile(file);

        variable Integer available = file.size;
        response.addHeader(contentLength(available.string));
        if (is String cntType = file.contentType) {
            response.addHeader(contentType(cntType));
        }

        void onComplete() {
            openFile.close();
            complete();
        }

        FileWritter(openFile, response, onComplete, endpointOptions).send();

    } else {
        response.responseStatus=404;
        //TODO log
        print("File ``filePath.absolutePath.string`` does not exist.");
    }
}

class FileWritter(OpenFile openFile, Response response, void completed(), EndpointOptions endpointOptions) {
    variable Integer available = openFile.size;
    variable Integer readFailed = 0;
    Integer bufferSize = endpointOptions.outputBufferSize < available then endpointOptions.outputBufferSize else available;
    ByteBuffer byteBuffer = newByteBuffer(bufferSize);

    shared void send() {
        read();
    }

    void read() {
        if (available > 0) {
            value read = openFile.read(byteBuffer);
            if (read == -1) {
                available = 0;
            } else if (read == 0) {
                readFailed ++;
                if (readFailed > 10) { //try to read 10 times
                    //TODO log
                    print("Error reading file ``openFile.resource.path``.");
                    completed();
                    return;
                }
            } else {
                available -= read;
                readFailed = 0;
            }
            byteBuffer.flip();
            write();
        } else {
            completed();
        }
    }
    
{'fraction_non_alphanumeric': 0.10217897186376138, 'fraction_numerical': 0.0040194626613073835, 'mean_word_length': 2.104399212081418, 'pattern_counts': {'":': 0, '<': 8, '<?xml version=': 0, '>': 12, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2141816', 'n_tokens_mistral': 1236, 'n_tokens_neox': 1173, 'n_words': 315}