
com.github.davidmoten.rx.internal.operators.TransformerDecode Maven / Gradle / Ivy
package com.github.davidmoten.rx.internal.operators;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.charset.CharacterCodingException;
import java.nio.charset.CharsetDecoder;
import java.nio.charset.CoderResult;
import com.github.davidmoten.rx.Transformers;
import rx.Observable.Transformer;
import rx.Subscriber;
import rx.functions.Func0;
import rx.functions.Func2;
import rx.functions.Func3;
public final class TransformerDecode {
public static Transformer decode(final CharsetDecoder decoder) {
Func0 initialState = new Func0() {
@Override
public ByteBuffer call() {
return null;
}
};
Func3, ByteBuffer> transition = new Func3, ByteBuffer>() {
@Override
public ByteBuffer call(ByteBuffer last, byte[] next, Subscriber o) {
Result result = process(next, last, false, decoder, o);
return result.leftOver;
}
};
Func2, Boolean> completion = new Func2, Boolean>() {
@Override
public Boolean call(ByteBuffer last, Subscriber subscriber) {
return process(null, last, true, decoder, subscriber).canEmitFurther;
}
};
return Transformers.stateMachine(initialState, transition, completion);
}
private static final class Result {
final ByteBuffer leftOver;
final boolean canEmitFurther;
Result(ByteBuffer leftOver, boolean canEmitFurther) {
this.leftOver = leftOver;
this.canEmitFurther = canEmitFurther;
}
}
public static Result process(byte[] next, ByteBuffer last, boolean endOfInput,
CharsetDecoder decoder, Subscriber o) {
if (o.isUnsubscribed())
return new Result(null, false);
ByteBuffer bb;
if (last != null) {
if (next != null) {
// merge leftover in front of the next bytes
bb = ByteBuffer.allocate(last.remaining() + next.length);
bb.put(last);
bb.put(next);
bb.flip();
} else { // next == null
bb = last;
}
} else { // last == null
if (next != null) {
bb = ByteBuffer.wrap(next);
} else { // next == null
return new Result(null, true);
}
}
CharBuffer cb = CharBuffer.allocate((int) (bb.limit() * decoder.averageCharsPerByte()));
CoderResult cr = decoder.decode(bb, cb, endOfInput);
cb.flip();
if (cr.isError()) {
try {
cr.throwException();
} catch (CharacterCodingException e) {
o.onError(e);
return new Result(null, false);
}
}
ByteBuffer leftOver;
if (bb.remaining() > 0) {
leftOver = bb;
} else {
leftOver = null;
}
String string = cb.toString();
if (!string.isEmpty())
o.onNext(string);
return new Result(leftOver, true);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy