package co.nstant.in.cbor.encoder;
import java.io.IOException;
import java.io.OutputStream;
import java.math.BigInteger;
import co.nstant.in.cbor.CborEncoder;
import co.nstant.in.cbor.CborException;
import co.nstant.in.cbor.model.AdditionalInformation;
import co.nstant.in.cbor.model.ByteString;
import co.nstant.in.cbor.model.MajorType;
import co.nstant.in.cbor.model.Tag;
public abstract class AbstractEncoder<T> {
private final OutputStream outputStream;
protected final CborEncoder encoder;
public AbstractEncoder(CborEncoder encoder, OutputStream outputStream) {
this.encoder = encoder;
this.outputStream = outputStream;
}
public abstract void encode(T dataItem) throws CborException;
protected void encodeTypeChunked(MajorType majorType) throws CborException {
int symbol = majorType.getValue() << 5;
symbol |= AdditionalInformation.INDEFINITE.getValue();
try {
outputStream.write(symbol);
} catch (IOException ioException) {
throw new CborException(ioException);
}
}
protected void encodeTypeAndLength(MajorType majorType, long length)
throws CborException {
int symbol = majorType.getValue() << 5;
if (length <= 23L) {
write((int) (symbol | length));
} else if (length <= 255L) {
symbol |= AdditionalInformation.ONE_BYTE.getValue();
write(symbol);
write((int) length);
} else if (length <= 65535L) {
symbol |= AdditionalInformation.TWO_BYTES.getValue();
write(symbol);
write((int) (length >> 8));
write((int) (length & 0xFF));
} else if (length <= 4294967295L) {
symbol |= AdditionalInformation.FOUR_BYTES.getValue();
write(symbol);
write((int) ((length >> 24) & 0xFF));
write((int) ((length >> 16) & 0xFF));
write((int) ((length >> 8) & 0xFF));
write((int) (length & 0xFF));
} else {
symbol |= AdditionalInformation.EIGHT_BYTES.getValue();
write(symbol);
write((int) ((length >> 56) & 0xFF));
write((int) ((length >> 48) & 0xFF));
write((int) ((length >> 40) & 0xFF));
write((int) ((length >> 32) & 0xFF));
write((int) ((length >> 24) & 0xFF));
write((int) ((length >> 16) & 0xFF));
write((int) ((length >> 8) & 0xFF));
write((int) (length & 0xFF));
}
}
protected void encodeTypeAndLength(MajorType majorType, BigInteger length)
throws CborException {
boolean negative = majorType == MajorType.NEGATIVE_INTEGER;
int symbol = majorType.getValue() << 5;
if (length.compareTo(BigInteger.valueOf(24)) == -1) {
write(symbol | length.intValue());
} else if (length.compareTo(BigInteger.valueOf(256)) == -1) {
symbol |= AdditionalInformation.ONE_BYTE.getValue();
write(symbol);
write(length.intValue());
} else if (length.compareTo(BigInteger.valueOf(65536L)) == -1) {
symbol |= AdditionalInformation.TWO_BYTES.getValue();
write(symbol);
long twoByteValue = length.longValue();
write((int) (twoByteValue >> 8));
write((int) (twoByteValue & 0xFF));
} else if (length.compareTo(BigInteger.valueOf(4294967296L)) == -1) {
symbol |= AdditionalInformation.FOUR_BYTES.getValue();
write(symbol);
long fourByteValue = length.longValue();
write((int) ((fourByteValue >> 24) & 0xFF));
write((int) ((fourByteValue >> 16) & 0xFF));
write((int) ((fourByteValue >> 8) & 0xFF));
write((int) (fourByteValue & 0xFF));
} else if (length.compareTo(new BigInteger("18446744073709551616")) == -1) {
symbol |= AdditionalInformation.EIGHT_BYTES.getValue();
write(symbol);
BigInteger mask = BigInteger.valueOf(0xFF);
write(length.shiftRight(56).and(mask).intValue());
write(length.shiftRight(48).and(mask).intValue());
write(length.shiftRight(40).and(mask).intValue());
write(length.shiftRight(32).and(mask).intValue());
write(length.shiftRight(24).and(mask).intValue());
write(length.shiftRight(16).and(mask).intValue());
write(length.shiftRight(8).and(mask).intValue());
write(length.and(mask).intValue());
} else {
if (negative) {
encoder.encode(new Tag(3));
} else {
encoder.encode(new Tag(2));
}
encoder.encode(new ByteString(length.toByteArray()));
}
}
protected void write(int b) throws CborException {
try {
outputStream.write(b);
} catch (IOException ioException) {
throw new CborException(ioException);
}
}
protected void write(byte[] bytes) throws CborException {
try {
outputStream.write(bytes);
} catch (IOException ioException) {
throw new CborException(ioException);
}
}
}