Search in sources :

Example 1 with Bytes

use of primal.primitive.adt.Bytes in project suite by stupidsing.

the class ImperativeCompilerTest method testExpr.

@Test
public void testExpr() {
    Bytes bytes = imperativeCompiler.compile(0, "null/* + 1 = 2;");
    assertNotNull(bytes);
    System.out.println(bytes);
}
Also used : Bytes(primal.primitive.adt.Bytes) Test(org.junit.jupiter.api.Test)

Example 2 with Bytes

use of primal.primitive.adt.Bytes in project suite by stupidsing.

the class HttpNio method listen.

private void listen(Reg reg) {
    var rw = new Object() {

        // 0 - read, 1 - write, 2 - close after all written
        private int stage = 0;

        private Bytes br = Bytes.empty;

        private Bytes bw = Bytes.empty;

        private Puller<Bytes> write;

        private Source<Boolean> eater = () -> parseLine(line -> handleRequest1stLine(line.trim(), response -> {
            var data = // 
            "HTTP/1.1 " + response.status + "\r\n" + response.headers.streamlet().map((k, v) -> k + ": " + v + "\r\n").toJoinedString() + "\r\n";
            stage = 1;
            if (response.body != null)
                write = Puller.concat(Pull.from(data), response.body);
            else {
                bw = Bytes.of(data.getBytes(Utf8.charset));
                response.write.f(bytes -> {
                    if (bytes != null)
                        bw = bw.append(bytes);
                    else
                        stage = 2;
                    listen();
                });
            }
        }));

        private void listen() {
            if (!bw.isEmpty())
                reg.listenWrite(() -> bw, this::written);
            else if (stage == 0)
                reg.listenRead(in -> {
                    read(in);
                    listen();
                });
            else if (stage == 1 && write != null)
                reg.listenWrite(() -> bw = write.pull(), this::written);
            else if (stage == 2)
                reg.listenWrite(() -> null, null);
            else if (stage == 3)
                reg.listen(0, null, null, null);
        }

        private void read(Bytes in) {
            if (in != null) {
                br = br.append(in);
                while (eater.g()) ;
            } else
                // closes connection
                write = Puller.empty();
        }

        private void written(int n) {
            if (0 <= n)
                bw = bw.range(n);
            else
                stage = 3;
            listen();
        }

        private void handleRequest1stLine(String line, Sink<Response> cb) {
            var hrhl = handleRequestHeaderLine(lines -> handleRequestBody(line, lines, cb));
            eater = () -> parseLine(hrhl);
        }

        private Sink<String> handleRequestHeaderLine(Sink<List<String>> cb) {
            var lines = new ArrayList<String>();
            return line0 -> {
                var line1 = line0.trim();
                if (!line1.isEmpty())
                    lines.add(line1);
                else
                    cb.f(lines);
            };
        }

        private void handleRequestBody(String line0, List<String> headerLines, Sink<Response> cb) {
            eater = () -> // 
            FixieArray.of(// 
            line0.split(" ")).map((method, url, proto) -> handleRequestBody(proto, method, url, headerLines, cb));
        }

        private // 
        boolean handleRequestBody(// 
        String proto, // 
        String method, // 
        String url, // 
        List<String> lines, Sink<Response> cb) {
            var headers = // 
            Read.from(// 
            lines).fold(new Header(), (headers_, line_) -> // 
            Split.strl(line_, // 
            ":").map((k, v) -> headers_.put(k, v)));
            var queue = new ArrayBlockingQueue<Bytes>(Buffer.size);
            Sink<Bytes> offer = queue::add;
            Source<Bytes> take = queue::poll;
            Fun2<String, String, Request> requestFun = (host, pqs) -> Split.strl(pqs, "?").map((path0, query) -> {
                var path1 = path0.startsWith("/") ? path0 : "/" + path0;
                var path2 = ex(() -> URLDecoder.decode(path1, Utf8.charset));
                return // 
                Equals.string(proto, "HTTP/1.1") ? // 
                new Request(method, host, path2, query, headers, Puller.of(take)) : fail("only HTTP/1.1 is supported");
            });
            var pp = Split.string(url, "://");
            var request = pp != null ? Split.strl(pp.v, "/").map(requestFun) : requestFun.apply("", url);
            var cl = request.headers.getOpt("Content-Length").map(Long::parseLong);
            var te = Equals.ab(request.headers.getOpt("Transfer-Encoding"), Opt.of("chunked"));
            Log_.info(request.getLogString());
            if (te)
                eater = handleChunkedRequestBody(request, offer, cb);
            else if (cl.hasValue())
                eater = handleRequestBody(request, offer, cl.g(), cb);
            else
                eater = handleRequestBody(request, offer, 0, cb);
            return true;
        }

        private // 
        Source<Boolean> handleRequestBody(// 
        Request request, // 
        Sink<Bytes> body, // 
        long contentLength, Sink<Response> cb) {
            return new Source<>() {

                private int n;

                public Boolean g() {
                    body.f(br);
                    var isOpen = br != null;
                    if (isOpen) {
                        n += br.size();
                        br = Bytes.empty;
                    }
                    if (!isOpen || contentLength <= n)
                        cb.f(handler.handle(request));
                    return false;
                }
            };
        }

        private Source<Boolean> handleChunkedRequestBody(Request request, Sink<Bytes> body, Sink<Response> cb) {
            return () -> {
                for (var i0 = 0; i0 < br.size(); i0++) if (br.get(i0) == 10) {
                    var line = new String(br.range(0, i0).toArray(), Utf8.charset);
                    var size = Integer.parseInt(line.trim(), 16);
                    for (var i1 = i0 + 1 + size; i1 < br.size(); i1++) if (br.get(i1) == 10) {
                        var chunk = br.range(i0 + 1, i1);
                        br = br.range(i1);
                        body.f(chunk);
                        return true;
                    }
                    if (size == 0)
                        cb.f(handler.handle(request));
                }
                return false;
            };
        }

        private boolean parseLine(Sink<String> handleLine) {
            for (var i = 0; i < br.size(); i++) if (br.get(i) == 10) {
                var line = new String(br.range(0, i).toArray(), Utf8.charset);
                br = br.range(i + 1);
                handleLine.f(line);
                return true;
            }
            return false;
        }
    };
    rw.listen();
}
Also used : FixieArray(primal.adt.FixieArray) Fail.fail(primal.statics.Fail.fail) URLDecoder(java.net.URLDecoder) Reg(suite.os.ListenNio.Reg) Sink(primal.fp.Funs.Sink) ArrayList(java.util.ArrayList) Response(suite.http.Http.Response) Utf8(primal.Nouns.Utf8) Request(suite.http.Http.Request) Split(primal.MoreVerbs.Split) Opt(primal.adt.Opt) Pull(primal.MoreVerbs.Pull) Handler(suite.http.Http.Handler) ListenNio(suite.os.ListenNio) Buffer(primal.Nouns.Buffer) Source(primal.fp.Funs.Source) Header(suite.http.Http.Header) Log_(primal.os.Log_) Read(primal.MoreVerbs.Read) Bytes(primal.primitive.adt.Bytes) ArrayBlockingQueue(java.util.concurrent.ArrayBlockingQueue) List(java.util.List) Rethrow.ex(primal.statics.Rethrow.ex) Fun2(primal.fp.Funs2.Fun2) Equals(primal.Verbs.Equals) Puller(primal.puller.Puller) ArrayList(java.util.ArrayList) Request(suite.http.Http.Request) Source(primal.fp.Funs.Source) Bytes(primal.primitive.adt.Bytes) Sink(primal.fp.Funs.Sink) Header(suite.http.Http.Header) ArrayBlockingQueue(java.util.concurrent.ArrayBlockingQueue) Puller(primal.puller.Puller) ArrayList(java.util.ArrayList) List(java.util.List)

Example 3 with Bytes

use of primal.primitive.adt.Bytes in project suite by stupidsing.

the class HttpHandle method serveDir.

public Handler serveDir(Path root) {
    return request -> ex(() -> {
        var path = root;
        long size;
        for (var p : request.paths) if (!Equals.string(p, ".."))
            path = path.resolve(p);
        var file = path.toFile();
        if (file.exists())
            try (var raf = new RandomAccessFile(file, "r")) {
                size = raf.getChannel().size();
                var array = // 
                request.headers.getOpt(// 
                "Range").map(// 
                range -> range.split(",")).filter(// 
                ranges -> ranges.length == 1).map(// 
                ranges -> ranges[0].split("-")).or(new String[0]);
                if (array.length == 2) {
                    var a0 = array[0];
                    var a1 = array[1];
                    var p0 = max(!a1.isEmpty() ? Long.valueOf(a0) : Long.MIN_VALUE, 0);
                    var px = min(!a1.isEmpty() ? Long.valueOf(a1) : Long.MAX_VALUE, size);
                    var p = LngMutable.of(p0);
                    var empty = // 
                    new Header().put("Content-Range", // 
                    "bytes " + p0 + "-" + px + "/" + size).put("Content-Type", "text/html; charset=UTF-8");
                    return Response.of(Http.S206, empty, Pull.from(new InputStream() {

                        public int read() throws IOException {
                            var pos = p.value();
                            if (pos != px) {
                                raf.seek(p.increment());
                                p.update(pos + 1);
                                return raf.read();
                            } else
                                return -1;
                        }

                        public int read(byte[] b, int off, int len0) throws IOException {
                            var pos = p.value();
                            if (pos != px) {
                                var len1 = min(len0, (int) (px - pos));
                                raf.seek(pos);
                                var n = raf.read(b, off, len1);
                                p.update(pos + n);
                                return n;
                            } else
                                return -1;
                        }
                    }));
                } else
                    return Response.of(Http.S200, Pull.from(Files.newInputStream(path)), size);
            }
        else
            return Http.R404;
    });
}
Also used : PerMap(primal.persistent.PerMap) RandomAccessFile(java.io.RandomAccessFile) Files(java.nio.file.Files) IOException(java.io.IOException) Math.min(java.lang.Math.min) Header(suite.http.Http.Header) Sink(primal.fp.Funs.Sink) Bytes(primal.primitive.adt.Bytes) Response(suite.http.Http.Response) Rethrow.ex(primal.statics.Rethrow.ex) Math.max(java.lang.Math.max) Pull(primal.MoreVerbs.Pull) LngMutable(primal.primitive.adt.LngMutable) Equals(primal.Verbs.Equals) Path(java.nio.file.Path) PerList(primal.persistent.PerList) Handler(suite.http.Http.Handler) InputStream(java.io.InputStream) RandomAccessFile(java.io.RandomAccessFile) Header(suite.http.Http.Header) InputStream(java.io.InputStream) IOException(java.io.IOException)

Example 4 with Bytes

use of primal.primitive.adt.Bytes in project suite by stupidsing.

the class NioDispatchTest method testTextExchange.

@Test
public void testTextExchange() throws IOException {
    try (var dispatch = new NioDispatch();
        var listen = listen(dispatch)) {
        // 
        dispatch.asyncConnect(// 
        new InetSocketAddress(localHost, port), rw -> {
            var buffer = dispatch.new BufferRw(rw);
            buffer.writeAll(Bytes.concat(helloBytes, lfs), v -> buffer.readLine(lf, bytes -> {
                assertEquals(helloBytes, bytes);
                System.out.println("OK");
                rw.close();
                dispatch.stop();
            }, fail), fail);
        }, fail);
        dispatch.run();
    }
}
Also used : PrintWriter(java.io.PrintWriter) Socket(java.net.Socket) IOException(java.io.IOException) Start(primal.Verbs.Start) Log_(primal.os.Log_) InputStreamReader(java.io.InputStreamReader) InetSocketAddress(java.net.InetSocketAddress) Sink(primal.fp.Funs.Sink) Bytes(primal.primitive.adt.Bytes) InetAddress(java.net.InetAddress) Test(org.junit.jupiter.api.Test) AsyncRw(suite.net.nio.NioDispatch.AsyncRw) Charset(java.nio.charset.Charset) Closeable(java.io.Closeable) Utf8(primal.Nouns.Utf8) Rethrow(primal.statics.Rethrow) Assertions.assertEquals(org.junit.jupiter.api.Assertions.assertEquals) BufferedReader(java.io.BufferedReader) InetSocketAddress(java.net.InetSocketAddress) Test(org.junit.jupiter.api.Test)

Example 5 with Bytes

use of primal.primitive.adt.Bytes in project suite by stupidsing.

the class ImperativeCompilerTest method testDeclare.

@Test
public void testDeclare() {
    Bytes bytes = imperativeCompiler.compile(0, "declare v = 1; {v} = 2;");
    assertNotNull(bytes);
    System.out.println(bytes);
}
Also used : Bytes(primal.primitive.adt.Bytes) Test(org.junit.jupiter.api.Test)

Aggregations

Bytes (primal.primitive.adt.Bytes)8 ArrayList (java.util.ArrayList)3 Test (org.junit.jupiter.api.Test)3 Utf8 (primal.Nouns.Utf8)3 Sink (primal.fp.Funs.Sink)3 IOException (java.io.IOException)2 List (java.util.List)2 Pull (primal.MoreVerbs.Pull)2 Read (primal.MoreVerbs.Read)2 Split (primal.MoreVerbs.Split)2 Equals (primal.Verbs.Equals)2 Log_ (primal.os.Log_)2 BytesBuilder (primal.primitive.adt.Bytes.BytesBuilder)2 Rethrow.ex (primal.statics.Rethrow.ex)2 Handler (suite.http.Http.Handler)2 Header (suite.http.Http.Header)2 Response (suite.http.Http.Response)2 BufferedReader (java.io.BufferedReader)1 Closeable (java.io.Closeable)1 InputStream (java.io.InputStream)1