
io.datakernel.csp.binary.BinaryChannelSupplier Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of datakernel-csp Show documentation
Show all versions of datakernel-csp Show documentation
Communicating sequential process via channels, similar to Golang's channels.
A channel could be imagine as a pipe which connects some processes.
The newest version!
/*
* Copyright (C) 2015-2018 SoftIndex LLC.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.datakernel.csp.binary;
import io.datakernel.async.function.AsyncSupplier;
import io.datakernel.async.process.Cancellable;
import io.datakernel.bytebuf.ByteBuf;
import io.datakernel.bytebuf.ByteBufQueue;
import io.datakernel.common.parse.ParseException;
import io.datakernel.csp.ChannelSupplier;
import io.datakernel.promise.Promise;
import io.datakernel.promise.SettablePromise;
import org.jetbrains.annotations.NotNull;
import java.util.Iterator;
public abstract class BinaryChannelSupplier implements Cancellable {
public static final Exception UNEXPECTED_DATA_EXCEPTION = new ParseException(BinaryChannelSupplier.class, "Unexpected data after end-of-stream");
public static final Exception UNEXPECTED_END_OF_STREAM_EXCEPTION = new ParseException(BinaryChannelSupplier.class, "Unexpected end-of-stream");
protected final ByteBufQueue bufs;
protected BinaryChannelSupplier(ByteBufQueue bufs) {
this.bufs = bufs;
}
protected BinaryChannelSupplier() {
this.bufs = new ByteBufQueue();
}
public ByteBufQueue getBufs() {
return bufs;
}
public abstract Promise needMoreData();
public abstract Promise endOfStream();
public static BinaryChannelSupplier ofIterable(Iterable iterable) {
return of(ChannelSupplier.ofIterator(iterable.iterator()));
}
public static BinaryChannelSupplier ofIterator(Iterator iterator) {
return of(ChannelSupplier.ofIterator(iterator));
}
public static BinaryChannelSupplier of(ChannelSupplier input) {
return new BinaryChannelSupplier() {
@Override
public Promise needMoreData() {
return input.get()
.then(buf -> {
if (buf != null) {
bufs.add(buf);
return Promise.complete();
} else {
return Promise.ofException(UNEXPECTED_END_OF_STREAM_EXCEPTION);
}
});
}
@Override
public Promise endOfStream() {
if (!bufs.isEmpty()) {
bufs.recycle();
input.close(UNEXPECTED_DATA_EXCEPTION);
return Promise.ofException(UNEXPECTED_DATA_EXCEPTION);
}
return input.get()
.then(buf -> {
if (buf == null) {
return Promise.complete();
} else {
buf.recycle();
input.close(UNEXPECTED_DATA_EXCEPTION);
return Promise.ofException(UNEXPECTED_DATA_EXCEPTION);
}
});
}
@Override
public void close(@NotNull Throwable e) {
bufs.recycle();
input.close(e);
}
};
}
public static BinaryChannelSupplier ofProvidedQueue(ByteBufQueue queue,
AsyncSupplier get, AsyncSupplier complete, Cancellable cancellable) {
return new BinaryChannelSupplier(queue) {
@Override
public Promise needMoreData() {
return get.get();
}
@Override
public Promise endOfStream() {
return complete.get();
}
@Override
public void close(@NotNull Throwable e) {
cancellable.close(e);
}
};
}
public final Promise parse(ByteBufsParser parser) {
if (!bufs.isEmpty()) {
T result;
try {
result = parser.tryParse(bufs);
} catch (Exception e) {
return Promise.ofException(e);
}
if (result != null) {
return Promise.of(result);
}
}
return Promise.ofCallback(cb -> doParse(parser, cb));
}
private void doParse(ByteBufsParser parser, SettablePromise cb) {
needMoreData()
.whenComplete(($, e) -> {
if (e == null) {
T result;
try {
result = parser.tryParse(bufs);
} catch (Exception e2) {
close(e2);
cb.setException(e2);
return;
}
if (result == null) {
doParse(parser, cb);
return;
}
cb.set(result);
} else {
cb.setException(e);
}
});
}
public final Promise parseRemaining(ByteBufsParser parser) {
return parse(parser)
.then(result -> {
if (!bufs.isEmpty()) {
close(UNEXPECTED_DATA_EXCEPTION);
return Promise.ofException(UNEXPECTED_DATA_EXCEPTION);
}
return endOfStream().map($ -> result);
});
}
public final ChannelSupplier parseStream(ByteBufsParser parser) {
return ChannelSupplier.of(
() -> parse(parser)
.thenEx((value, e) -> {
if (e == null) return Promise.of(value);
if (e == UNEXPECTED_END_OF_STREAM_EXCEPTION && bufs.isEmpty()) return Promise.of(null);
return Promise.ofException(e);
}),
this);
}
public Promise bindTo(BinaryChannelInput input) {
return input.set(this);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy