Search in sources :

Example 1 with Sink

use of primal.fp.Funs.Sink in project suite by stupidsing.

the class Dump method toLine.

private static void toLine(Object node, Sink<String> sink) {
    var dumpedObjects = new IdentityHashMap<Object, Object>();
    new Object() {

        private void d(Object object, String suffix) {
            if (object == null)
                sink.f("null");
            else if (dumpedObjects.put(object, true) == null)
                try {
                    d_(object);
                } finally {
                    dumpedObjects.remove(object);
                }
            else
                sink.f("(recursed)");
            sink.f(suffix);
        }

        private void d_(Object object) {
            var clazz = object.getClass();
            if (clazz.isArray()) {
                sink.f("[");
                for (var i = 0; i < Array.getLength(object); i++) d(Array.get(object, i), ",");
                sink.f("]");
            } else if (Util.isSimple(clazz))
                sink.f(object.toString());
            else
                new // 
                Switch<Object>(// 
                object).doIf(Collection.class, collection -> {
                    sink.f("[");
                    for (var object1 : collection) d(object1, ",");
                    sink.f("]");
                }).doIf(Map.class, map -> {
                    sink.f("{");
                    for (var e : ((Map<?, ?>) object).entrySet()) {
                        d(e.getKey(), ":");
                        d(e.getValue(), ",");
                    }
                    sink.f("}");
                }).doIf(MapObject.class, mi -> {
                    sink.f(mi.getClass().getSimpleName());
                    sink.f("{");
                    for (var object1 : MapObject_.list(mi)) d(object1, ",");
                    sink.f("}");
                }).doIf(Pair.class, pair -> {
                    sink.f("<");
                    d(pair.k, "|");
                    d(pair.v, ">");
                }).doIf(Object.class, o -> {
                    sink.f(o.getClass().getSimpleName());
                    sink.f("{");
                    for (var pair : readers(object)) {
                        Object value;
                        try {
                            value = pair.v.call();
                        } catch (Throwable ex) {
                            value = "<" + ex.getClass() + ">";
                        }
                        if (value != null) {
                            sink.f(pair.k + ":");
                            d(value, ",");
                        }
                    }
                    sink.f("}");
                }).nonNullResult();
        }
    }.d(node, "");
}
Also used : Pair(primal.adt.Pair) Array(java.lang.reflect.Array) IdentityHashMap(java.util.IdentityHashMap) Singleton(suite.node.util.Singleton) Build(primal.Verbs.Build) Collection(java.util.Collection) Util(suite.util.Util) Callable(java.util.concurrent.Callable) MapObject_(suite.object.MapObject_) Log_(primal.os.Log_) Assoc(primal.parser.Operator.Assoc) Sink(primal.fp.Funs.Sink) Read(primal.MoreVerbs.Read) Tree(suite.node.Tree) Streamlet(primal.streamlet.Streamlet) SmartSplit(suite.util.SmartSplit) List(java.util.List) MapObject(suite.object.MapObject) Map(java.util.Map) Substring(primal.Verbs.Substring) Get(primal.Verbs.Get) Switch(suite.util.Switch) Left(primal.Verbs.Left) IdentityHashMap(java.util.IdentityHashMap) MapObject(suite.object.MapObject) IdentityHashMap(java.util.IdentityHashMap) Map(java.util.Map) Pair(primal.adt.Pair)

Example 2 with Sink

use of primal.fp.Funs.Sink 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 Sink

use of primal.fp.Funs.Sink in project suite by stupidsing.

the class NioClusterMapTest method testClusterMap.

@Test
public void testClusterMap() throws IOException {
    var nNodes = 3;
    var peers = forInt(nNodes).map2(i -> "NODE" + i, i -> new InetSocketAddress(localHost, 3000 + i)).toMap();
    var clusters = // 
    Read.from2(// 
    peers).keys().map2(name -> name, // 
    name -> ex(() -> new NioCluster(name, peers))).toMap();
    for (var cluster : clusters.values()) cluster.start();
    var peerNames = new ArrayList<>(peers.keySet());
    var clMap = // 
    Read.from2(// 
    peers).keys().map2(name -> name, // 
    name -> new NioClusterMap<Integer, String>(clusters.get(name))).toMap();
    Sleep.quietly(5 * 1000);
    System.out.println("=== CLUSTER FORMED (" + LocalDateTime.now() + ") ===\n");
    Source<NioClusterMap<Integer, String>> peerf = () -> clMap.get(peerNames.get(random.nextInt(nNodes)));
    Int_Obj<Sink<Runnable>> setf = i -> cont -> peerf.g().set(i, Integer.toString(i), v0 -> cont.run(), fail);
    Int_Obj<Sink<Runnable>> getf = i -> cont -> peerf.g().get(i, v -> {
        assertEquals(Integer.toString(i), v);
        cont.run();
    }, fail);
    Fun<NioCluster, Sink<Runnable>> closef = cluster -> cont -> {
        try {
            cluster.stop();
            System.out.println("=== CLUSTER STOPPED (" + LocalDateTime.now() + ") ===\n");
        } catch (IOException ex) {
            fail(ex);
        }
        cont.run();
    };
    var sinks = // 
    Streamlet.concat(// 
    forInt(9).map(setf), // 
    forInt(9).map(getf), Read.from2(clusters).values().map(closef)).toList();
    new Object() {

        public void run(int i) {
            if (i < sinks.size())
                sinks.get(i).f(() -> run(i + 1));
        }
    }.run(0);
    Read.from2(clusters).values().map(cluster -> New.thread(cluster::run)).collect(Start::thenJoin);
    for (var cluster : clusters.values()) cluster.close();
}
Also used : NioClusterMap(suite.net.cluster.impl.NioClusterMap) Fail.fail(primal.statics.Fail.fail) Fun(primal.fp.Funs.Fun) Source(primal.fp.Funs.Source) LocalDateTime(java.time.LocalDateTime) IOException(java.io.IOException) Random(java.util.Random) Start(primal.Verbs.Start) New(primal.Verbs.New) Log_(primal.os.Log_) InetSocketAddress(java.net.InetSocketAddress) Sink(primal.fp.Funs.Sink) Read(primal.MoreVerbs.Read) Streamlet_.forInt(suite.util.Streamlet_.forInt) ArrayList(java.util.ArrayList) InetAddress(java.net.InetAddress) Test(org.junit.jupiter.api.Test) Streamlet(primal.streamlet.Streamlet) Rethrow.ex(primal.statics.Rethrow.ex) Rethrow(primal.statics.Rethrow) Int_Obj(primal.primitive.IntPrim.Int_Obj) Assertions.assertEquals(org.junit.jupiter.api.Assertions.assertEquals) Sleep(primal.Verbs.Sleep) NioCluster(suite.net.cluster.impl.NioCluster) NioClusterMap(suite.net.cluster.impl.NioClusterMap) Start(primal.Verbs.Start) InetSocketAddress(java.net.InetSocketAddress) ArrayList(java.util.ArrayList) IOException(java.io.IOException) NioCluster(suite.net.cluster.impl.NioCluster) Sink(primal.fp.Funs.Sink) Test(org.junit.jupiter.api.Test)

Example 4 with Sink

use of primal.fp.Funs.Sink in project suite by stupidsing.

the class IterativeParser method parse.

public Node parse(String in0) {
    var in = Preprocess.transform(PreprocessorFactory.create(operators), in0).k;
    var stack = new ArrayDeque<Section>();
    Sink<Operator> addOperator = operator -> {
        var section = stack.peek();
        var tree = section.unwind(operator);
        var tree0 = tree.getRight();
        var tree1 = Tree.of(operator, tree0, Atom.NIL);
        Tree.forceSetRight(tree, tree1);
        section.push(tree1);
    };
    Sink<Node> add = node -> {
        var section = stack.peek();
        if (!section.isDanglingRight)
            addOperator.f(opTuple);
        Tree.forceSetRight(section.list.getLast(), node);
        section.isDanglingRight = false;
    };
    var lex = new Lexer(operators, opTuple, in);
    stack.push(new Section(' '));
    Token token;
    while ((token = lex.lex()) != null) {
        var operator = token.operator;
        var data = token.getData();
        var ch = data.charAt(0);
        if (operator != null) {
            addOperator.f(operator);
            if (operator == TermOp.BRACES)
                stack.push(new Section('{'));
        } else if (ch == '(' || ch == '[' || ch == '{')
            stack.push(new Section(ch));
        else if (ch == ')' || ch == ']' || ch == '}') {
            var section = stack.pop();
            var kind = section.kind;
            if (kind == '(' && ch == ')' || kind == '[' && ch == ']' || kind == '{' && ch == '}') {
                var node = section.unwind(null).getRight();
                if (ch == ']')
                    node = TreeTuple.of(Atom.of("["), node);
                else if (ch == '}')
                    node = TreeTuple.of(Atom.of("{"), node);
                add.f(node);
            } else
                fail("cannot parse " + in);
        } else if (ch == '`')
            if (stack.peek().kind == ch) {
                var node = stack.pop().unwind(null).getRight();
                node = TreeTuple.of(Atom.of("`"), node);
                add.f(node);
            } else
                stack.push(new Section(ch));
        else if (Is.notBlank(data))
            add.f(terminalParser.parseTerminal(data));
    }
    return stack.size() == 1 ? stack.pop().unwind(null).getRight() : fail("cannot parse " + in);
}
Also used : Operator(primal.parser.Operator) Fail.fail(primal.statics.Fail.fail) Operator(primal.parser.Operator) TermOp(suite.node.io.TermOp) Deque(java.util.Deque) Assoc(primal.parser.Operator.Assoc) Sink(primal.fp.Funs.Sink) Is(primal.Verbs.Is) Tree(suite.node.Tree) Lexer(primal.parser.Lexer) Node(suite.node.Node) List(java.util.List) Token(primal.parser.Lexer.Token) Preprocess(suite.text.Preprocess) Atom(suite.node.Atom) ArrayDeque(java.util.ArrayDeque) TreeTuple(suite.node.tree.TreeTuple) Lexer(primal.parser.Lexer) Node(suite.node.Node) Token(primal.parser.Lexer.Token) ArrayDeque(java.util.ArrayDeque)

Aggregations

Sink (primal.fp.Funs.Sink)4 List (java.util.List)3 Read (primal.MoreVerbs.Read)3 Log_ (primal.os.Log_)3 Fail.fail (primal.statics.Fail.fail)3 ArrayList (java.util.ArrayList)2 Source (primal.fp.Funs.Source)2 Rethrow.ex (primal.statics.Rethrow.ex)2 Streamlet (primal.streamlet.Streamlet)2 IOException (java.io.IOException)1 Array (java.lang.reflect.Array)1 InetAddress (java.net.InetAddress)1 InetSocketAddress (java.net.InetSocketAddress)1 URLDecoder (java.net.URLDecoder)1 LocalDateTime (java.time.LocalDateTime)1 ArrayDeque (java.util.ArrayDeque)1 Collection (java.util.Collection)1 Deque (java.util.Deque)1 IdentityHashMap (java.util.IdentityHashMap)1 Map (java.util.Map)1