forked from liias/monkey
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
17 changed files
with
515 additions
and
31 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
jar.archiveName = "deserializer.jar" |
115 changes: 115 additions & 0 deletions
115
deserializer/src/main/java/io/github/liias/monkey/deserializer/Deserializer.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,115 @@ | ||
package io.github.liias.monkey.deserializer; | ||
|
||
import io.github.liias.monkey.deserializer.type.MonkeyType; | ||
import io.github.liias.monkey.deserializer.type.MonkeyTypeCollection; | ||
import io.github.liias.monkey.deserializer.type.MonkeyTypeString; | ||
import org.jetbrains.annotations.NotNull; | ||
|
||
import java.nio.ByteBuffer; | ||
import java.nio.charset.StandardCharsets; | ||
import java.util.*; | ||
import java.util.stream.IntStream; | ||
|
||
public class Deserializer { | ||
private static final int STRING_BLOCK_MARKER = 0xABCDABCD; | ||
private static final int DATA_BLOCK_MARKER = 0xDA7ADA7A; | ||
|
||
@NotNull | ||
private final List<MonkeyType> monkeyTypes; | ||
|
||
@NotNull | ||
private final Map<Integer, String> stringsByOffset; | ||
|
||
public Deserializer(byte[] bytes) { | ||
int stringBlockOffset = 0; | ||
int stringBlockSize = getBlockSize(bytes, stringBlockOffset, STRING_BLOCK_MARKER); | ||
byte[] stringBlockBytes = getBlockBytes(bytes, stringBlockOffset, stringBlockSize); | ||
stringsByOffset = deserializeStrings(stringBlockBytes); | ||
|
||
int dataBlockOffset = stringBlockSize == 0 ? 0 : stringBlockSize + 8; | ||
int dataBlockSize = getBlockSize(bytes, dataBlockOffset, DATA_BLOCK_MARKER); | ||
byte[] dataBlockBytes = getBlockBytes(bytes, dataBlockOffset, dataBlockSize); | ||
|
||
monkeyTypes = deserializeDataBlock(dataBlockBytes); | ||
} | ||
|
||
public List<MonkeyType> getTypes() { | ||
return monkeyTypes; | ||
} | ||
|
||
private static Map<Integer, String> deserializeStrings(byte[] bytes) { | ||
Map<Integer, String> stringsByOffset = new HashMap<>(); | ||
|
||
int offset = 0; | ||
while (offset < bytes.length) { | ||
int stringSize = ByteBuffer.wrap(bytes, offset, 2).getShort(); | ||
byte[] stringBytes = Arrays.copyOfRange(bytes, offset + 2, offset + 2 + stringSize - 1); | ||
String stringValue = new String(stringBytes, StandardCharsets.UTF_8); | ||
stringsByOffset.put(offset, stringValue); | ||
offset += (2 + stringSize); | ||
} | ||
|
||
return stringsByOffset; | ||
} | ||
|
||
private List<MonkeyType> deserializeDataBlock(byte[] bytes) { | ||
LinkedList<MonkeyType> deserializedQueue = fillDeserializedQueue(bytes); | ||
return fillCollections(deserializedQueue); | ||
} | ||
|
||
@NotNull | ||
private LinkedList<MonkeyType> fillDeserializedQueue(byte[] bytes) { | ||
LinkedList<MonkeyType> deserializedQueue = new LinkedList<>(); | ||
int i = 0; | ||
while (i < bytes.length) { | ||
byte type = bytes[i]; | ||
int size = MonkeyType.getSize(type); | ||
ByteBuffer bb = ByteBuffer.wrap(bytes, 1 + i, size); | ||
MonkeyType monkeyType = MonkeyType.of(type, bb); | ||
if (monkeyType instanceof MonkeyTypeString) { | ||
MonkeyTypeString monkeyTypeString = (MonkeyTypeString) monkeyType; | ||
monkeyTypeString.setValue(stringsByOffset.get(monkeyTypeString.getOffset())); | ||
} | ||
deserializedQueue.add(monkeyType); | ||
i = i + 1 + monkeyType.getSize(); | ||
} | ||
return deserializedQueue; | ||
} | ||
|
||
private List<MonkeyType> fillCollections(LinkedList<MonkeyType> deserializedQueue) { | ||
List<MonkeyType> deserialized = new ArrayList<>(); | ||
|
||
do { | ||
MonkeyType monkeyType = deserializedQueue.poll(); | ||
if (monkeyType instanceof MonkeyTypeCollection) { | ||
fillCollection((MonkeyTypeCollection) monkeyType, deserializedQueue); | ||
} | ||
deserialized.add(monkeyType); | ||
} while (!deserializedQueue.isEmpty()); | ||
return deserialized; | ||
} | ||
|
||
private static void fillCollection(MonkeyTypeCollection monkeyType, LinkedList<MonkeyType> deserializedQueue) { | ||
IntStream.range(0, monkeyType.getChildCount()).forEach(i -> monkeyType.fill(deserializedQueue)); | ||
monkeyType.getChildren().stream() | ||
.filter(mt -> mt instanceof MonkeyTypeCollection) | ||
.map(mt -> (MonkeyTypeCollection) mt) | ||
.forEach(mt -> fillCollection(mt, deserializedQueue)); | ||
} | ||
|
||
private static byte[] getBlockBytes(byte[] bytes, int offset, int size) { | ||
if (size > 0) { | ||
return Arrays.copyOfRange(bytes, offset + 8, offset + 8 + size); | ||
} | ||
return new byte[0]; | ||
} | ||
|
||
private static int getBlockSize(byte[] bytes, int offset, int startMarker) { | ||
ByteBuffer bb = ByteBuffer.wrap(bytes, offset, 8); | ||
// getInt() also increments position by 4 | ||
if (bb.getInt() == startMarker) { | ||
return bb.getInt(); | ||
} | ||
return 0; | ||
} | ||
} |
58 changes: 58 additions & 0 deletions
58
deserializer/src/main/java/io/github/liias/monkey/deserializer/type/MonkeyType.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
package io.github.liias.monkey.deserializer.type; | ||
|
||
import com.google.common.collect.ImmutableMap; | ||
|
||
import java.nio.ByteBuffer; | ||
import java.util.Map; | ||
|
||
public abstract class MonkeyType<T> { | ||
|
||
public abstract T getValue(); | ||
|
||
public abstract int getSize(); | ||
|
||
public interface Type { | ||
byte NULL = 0; | ||
byte INT = 1; | ||
byte FLOAT = 2; | ||
byte STRING = 3; | ||
byte ARRAY = 5; | ||
byte BOOLEAN = 9; | ||
byte HASH = 11; | ||
} | ||
|
||
public static Map<Byte, Integer> sizes = ImmutableMap.<Byte, Integer>builder() | ||
.put(Type.NULL, 0) | ||
.put(Type.INT, 4) | ||
.put(Type.FLOAT, 4) | ||
.put(Type.STRING, 4) | ||
.put(Type.ARRAY, 4) | ||
.put(Type.BOOLEAN, 1) | ||
.put(Type.HASH, 4) | ||
.build(); | ||
|
||
public static int getSize(byte type) { | ||
return sizes.get(type); | ||
} | ||
|
||
public static MonkeyType of(byte type, ByteBuffer bb) { | ||
switch (type) { | ||
case Type.NULL: | ||
return new MonkeyTypeNull(); | ||
case Type.INT: | ||
return new MonkeyTypeInt(bb); | ||
case Type.FLOAT: | ||
return new MonkeyTypeFloat(bb); | ||
case Type.STRING: | ||
return new MonkeyTypeString(bb); | ||
case Type.ARRAY: | ||
return new MonkeyTypeArray(bb); | ||
case Type.BOOLEAN: | ||
return new MonkeyTypeBool(bb); | ||
case Type.HASH: | ||
return new MonkeyTypeHash(bb); | ||
} | ||
|
||
throw new IllegalArgumentException("unknown type"); | ||
} | ||
} |
57 changes: 57 additions & 0 deletions
57
deserializer/src/main/java/io/github/liias/monkey/deserializer/type/MonkeyTypeArray.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
package io.github.liias.monkey.deserializer.type; | ||
|
||
import org.jetbrains.annotations.NotNull; | ||
|
||
import java.nio.ByteBuffer; | ||
import java.util.ArrayList; | ||
import java.util.Arrays; | ||
import java.util.LinkedList; | ||
import java.util.List; | ||
|
||
public class MonkeyTypeArray extends MonkeyType<List<MonkeyType>> implements MonkeyTypeCollection { | ||
|
||
private final int childCount; | ||
|
||
@NotNull | ||
private final List<MonkeyType> items; | ||
|
||
public MonkeyTypeArray(ByteBuffer bb) { | ||
childCount = bb.getInt(); | ||
items = new ArrayList<>(); | ||
} | ||
|
||
@Override | ||
public int getChildCount() { | ||
return childCount; | ||
} | ||
|
||
@Override | ||
public List<MonkeyType> getValue() { | ||
return items; | ||
} | ||
|
||
@Override | ||
public int getSize() { | ||
return 4; | ||
} | ||
|
||
public void add(MonkeyType monkeyType) { | ||
items.add(monkeyType); | ||
} | ||
|
||
@Override | ||
public void fill(LinkedList<MonkeyType> deserializedQueue) { | ||
add(deserializedQueue.poll()); | ||
} | ||
|
||
@Override | ||
public List<MonkeyType> getChildren() { | ||
return items; | ||
} | ||
|
||
@Override | ||
public String toString() { | ||
return Arrays.toString(items.toArray()); | ||
} | ||
|
||
} |
26 changes: 26 additions & 0 deletions
26
deserializer/src/main/java/io/github/liias/monkey/deserializer/type/MonkeyTypeBool.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
package io.github.liias.monkey.deserializer.type; | ||
|
||
import java.nio.ByteBuffer; | ||
|
||
public class MonkeyTypeBool extends MonkeyType<Boolean> { | ||
final boolean value; | ||
|
||
public MonkeyTypeBool(ByteBuffer bb) { | ||
value = bb.get() > 0; | ||
} | ||
|
||
@Override | ||
public Boolean getValue() { | ||
return value; | ||
} | ||
|
||
@Override | ||
public int getSize() { | ||
return 1; | ||
} | ||
|
||
@Override | ||
public String toString() { | ||
return String.valueOf(value); | ||
} | ||
} |
12 changes: 12 additions & 0 deletions
12
...rializer/src/main/java/io/github/liias/monkey/deserializer/type/MonkeyTypeCollection.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
package io.github.liias.monkey.deserializer.type; | ||
|
||
import java.util.LinkedList; | ||
import java.util.List; | ||
|
||
public interface MonkeyTypeCollection { | ||
int getChildCount(); | ||
|
||
void fill(LinkedList<MonkeyType> deserializedQueue); | ||
|
||
List<MonkeyType> getChildren(); | ||
} |
28 changes: 28 additions & 0 deletions
28
deserializer/src/main/java/io/github/liias/monkey/deserializer/type/MonkeyTypeFloat.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
package io.github.liias.monkey.deserializer.type; | ||
|
||
import java.nio.ByteBuffer; | ||
|
||
public class MonkeyTypeFloat extends MonkeyType<Float> { | ||
|
||
private final float value; | ||
|
||
public MonkeyTypeFloat(ByteBuffer bb) { | ||
value = bb.getFloat(); | ||
} | ||
|
||
@Override | ||
public Float getValue() { | ||
return value; | ||
} | ||
|
||
@Override | ||
public int getSize() { | ||
return 4; | ||
} | ||
|
||
@Override | ||
public String toString() { | ||
return String.valueOf(value); | ||
} | ||
|
||
} |
Oops, something went wrong.