164 lines
4.5 KiB
Java
164 lines
4.5 KiB
Java
package io.github.lonamiwebs.overgram.utils;
|
|
|
|
|
|
import io.github.lonamiwebs.overgram.tl.TLObject;
|
|
|
|
import java.io.ByteArrayOutputStream;
|
|
import java.io.IOException;
|
|
import java.math.BigInteger;
|
|
import java.nio.ByteBuffer;
|
|
import java.nio.ByteOrder;
|
|
import java.nio.charset.StandardCharsets;
|
|
import java.util.Arrays;
|
|
import java.util.List;
|
|
|
|
public class BinaryWriter {
|
|
|
|
private static final ByteOrder ORDER = ByteOrder.LITTLE_ENDIAN;
|
|
|
|
private final ByteArrayOutputStream buffer;
|
|
|
|
public BinaryWriter() {
|
|
buffer = new ByteArrayOutputStream(128);
|
|
}
|
|
|
|
public BinaryWriter(final int capacity) {
|
|
buffer = new ByteArrayOutputStream(capacity);
|
|
}
|
|
|
|
public void write(final byte value) {
|
|
buffer.write(value);
|
|
}
|
|
|
|
public void write(final int value) {
|
|
try {
|
|
buffer.write(ByteBuffer.allocate(4).order(ORDER).putInt(value).array());
|
|
} catch (IOException ignored) {
|
|
throw new RuntimeException();
|
|
}
|
|
}
|
|
|
|
public void write(final long value) {
|
|
try {
|
|
buffer.write(ByteBuffer.allocate(8).order(ORDER).putLong(value).array());
|
|
} catch (IOException ignored) {
|
|
throw new RuntimeException();
|
|
}
|
|
}
|
|
|
|
public void write(final BigInteger value, final int size) {
|
|
final byte[] bytes = value.toByteArray();
|
|
final byte[] result;
|
|
if (bytes.length == size) {
|
|
result = bytes;
|
|
} else {
|
|
result = new byte[size];
|
|
final byte fill = value.signum() > 0 ? 0 : (byte) 0xff;
|
|
System.arraycopy(bytes, 0, result, size - bytes.length, bytes.length);
|
|
for (int i = size - bytes.length; i-- != 0; ) {
|
|
result[i] = fill;
|
|
}
|
|
}
|
|
|
|
buffer.write(ORDER == ByteOrder.BIG_ENDIAN ? result : Utils.reversed(result), 0, size);
|
|
}
|
|
|
|
public void write(final double value) {
|
|
try {
|
|
buffer.write(ByteBuffer.allocate(8).order(ORDER).putDouble(value).array());
|
|
} catch (IOException ignored) {
|
|
throw new RuntimeException();
|
|
}
|
|
}
|
|
|
|
public void write(final boolean value) {
|
|
write(value ? 0x997275b5 : 0xbc799737);
|
|
}
|
|
|
|
public void write(final byte[] bytes) {
|
|
try {
|
|
int padding;
|
|
if (bytes.length < 0xfe) {
|
|
padding = (bytes.length + 1) % 4;
|
|
buffer.write(bytes.length);
|
|
buffer.write(bytes);
|
|
} else {
|
|
padding = bytes.length % 4;
|
|
write(bytes.length << 8 | 0xfe);
|
|
buffer.write(bytes);
|
|
}
|
|
if (padding != 0) {
|
|
for (padding = 4 - padding; padding-- != 0; ) {
|
|
buffer.write(0);
|
|
}
|
|
}
|
|
} catch (IOException ignored) {
|
|
throw new RuntimeException();
|
|
}
|
|
}
|
|
|
|
public void writeRaw(final byte[] bytes) {
|
|
buffer.write(bytes, 0, bytes.length);
|
|
}
|
|
|
|
public void writeRaw(final byte[] bytes, final int start, final int length) {
|
|
buffer.write(bytes, start, length);
|
|
}
|
|
|
|
public void write(final String string) {
|
|
write(StandardCharsets.UTF_8.encode(string).array());
|
|
}
|
|
|
|
// TODO Handle boxed vs unboxed types (and vector<>)
|
|
public void write(final TLObject object) {
|
|
object.serialize(this);
|
|
}
|
|
|
|
@SuppressWarnings("unchecked")
|
|
public void write(final List<?> objects) {
|
|
write(0x1cb5c415);
|
|
write(objects.size());
|
|
if (objects.isEmpty()) {
|
|
return;
|
|
}
|
|
|
|
final Object first = objects.get(0);
|
|
if (first instanceof TLObject) {
|
|
for (final TLObject obj : (List<TLObject>) objects) {
|
|
write(obj);
|
|
}
|
|
} else if (first instanceof Integer) {
|
|
for (final Integer obj : (List<Integer>) objects) {
|
|
write(obj);
|
|
}
|
|
} else if (first instanceof Long) {
|
|
for (final Long obj : (List<Long>) objects) {
|
|
write(obj);
|
|
}
|
|
} else if (first instanceof byte[]) {
|
|
for (final byte[] obj : (List<byte[]>) objects) {
|
|
write(obj);
|
|
}
|
|
} else {
|
|
throw new UnsupportedOperationException();
|
|
}
|
|
}
|
|
|
|
public void clear() {
|
|
buffer.reset();
|
|
}
|
|
|
|
public int size() {
|
|
return buffer.size();
|
|
}
|
|
|
|
public byte[] toBytes() {
|
|
return buffer.toByteArray();
|
|
}
|
|
|
|
@Override
|
|
public String toString() {
|
|
return Arrays.toString(toBytes());
|
|
}
|
|
}
|