Skip to content

Commit

Permalink
fixed Issue #6, now does strict parsing, field names MUST be ordered …
Browse files Browse the repository at this point in the history
…correctly
  • Loading branch information
franslundberg committed May 18, 2018
1 parent 06477b8 commit ff2be91
Show file tree
Hide file tree
Showing 5 changed files with 57 additions and 70 deletions.
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ A Java implementation of Binson. Binson is like JSON, but faster, binary and
even simpler. See [binson.org](http://binson.org/).



Use
===

Expand All @@ -25,6 +26,7 @@ This library also contains JSON (http://json.org/) support. See methods
Binson.fromJson() and Binson.toJson().



Build
=====

Expand All @@ -36,6 +38,8 @@ Other build tools should be easy to adapt for the source.
The code in src/ only depends on the JVM (Java 6 or later should work).

The tests in src-test/ depends on JUnit (junit-4.12.jar, hamcrest-core-1.3.jar).
JUnit jars are not included in the repo.



Log
Expand Down
22 changes: 22 additions & 0 deletions src-test/org/binson/FieldOrderTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -112,5 +112,27 @@ public void testAlex2a() {
Assert.assertArrayEquals(expected, binson.toBytes());
}

@Test(expected=BinsonFormatException.class)
public void testFromBytesWithUnorderedFields() {
// Based on issue #6 reported by Felix Grape, 2018-02-09.

byte[] unordered = {0x40,
0x14, 0x01, 0x42, 0x14, 0x01, 0x42, // "B": "B"
0x14, 0x01, 0x41, 0x14, 0x01, 0x42, // "A": "A"
0x41};

Binson.fromBytes(unordered);
}

@Test(expected=BinsonFormatException.class)
public void testFromBytesWithDuplicateFields() {
// Based on issue #6 reported by Felix Grape, 2018-02-09.

byte[] duplicates = {0x40,
0x14, 0x01, 0x42, 0x14, 0x01, 0x42, // "B": "B"
0x14, 0x01, 0x42, 0x14, 0x01, 0x42, // "B": "A"
0x41};

Binson.fromBytes(duplicates);
}
}
15 changes: 15 additions & 0 deletions src/org/binson/lowlevel/BinsonFieldNameComparator.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,21 @@
* representation as UTF-8 bytes. Used to order Binson fields when serializing.
*/
public class BinsonFieldNameComparator implements Comparator<String> {
/**
* The instance of the class, one instance is enough since if can be freely shared
* between threads. It has no state.
*/
public static final BinsonFieldNameComparator INSTANCE = new BinsonFieldNameComparator();

/**
* Use the INSTANCE instance.
*/
private BinsonFieldNameComparator() {}

/**
* Compares its two arguments for order. Returns a negative integer, zero, or a
* positive integer as the first argument is less than, equal to, or greater than the second.
*/
public int compare(String s1, String s2) {
return ByteArrayComparator.compareArrays(s1.getBytes(StandardCharsets.UTF_8), s2.getBytes(StandardCharsets.UTF_8));
}
Expand Down
18 changes: 15 additions & 3 deletions src/org/binson/lowlevel/BinsonParser.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ public class BinsonParser {
private final InputStream in;
private int maxSize = 40*1000000;
private long streamOffset = 0;

/**
* Creates a new parser that takes data from
* the given input stream. "public" since 2.1.
Expand Down Expand Up @@ -77,6 +76,7 @@ private Binson parseObject() throws IOException {
private Binson parseFields() throws IOException {
Binson object = new Binson();
int type;
String currentFieldName = null;

outer: while (true) {
type = readOne();
Expand All @@ -85,7 +85,7 @@ private Binson parseFields() throws IOException {
case STRING1:
case STRING2:
case STRING4:
parseField(type, object);
currentFieldName = parseField(currentFieldName, type, object);
break;
case END:
break outer;
Expand All @@ -97,10 +97,22 @@ private Binson parseFields() throws IOException {
return object;
}

private void parseField(int type, Binson dest) throws IOException {
/**
* Parses a field and returns the field name.
*/
private String parseField(String currentFieldName, int type, Binson dest) throws IOException {
String name = parseString(type);

if (currentFieldName != null) {
if (BinsonFieldNameComparator.INSTANCE.compare(currentFieldName, name) >= 0) {
throw new BinsonFormatException("bad field order, " + currentFieldName + ", " + name);
}
}

Object value = parseValue(false);
dest.putElement(name, value);

return name;
}

private Object parseValue(boolean inArray) throws IOException {
Expand Down
68 changes: 1 addition & 67 deletions src/org/binson/lowlevel/OutputWriter.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,11 @@
* @author Frans Lundberg
*/
public class OutputWriter {
private static final BinsonFieldNameComparator BINSON_STRING_COMPARATOR = new BinsonFieldNameComparator();
private static final String[] EMPTY_STRING_ARRAY = new String[0];

public static void writeToOutput(Binson obj, Output output) throws IOException {
String[] keys = obj.keySet().toArray(EMPTY_STRING_ARRAY);
Arrays.sort(keys, BINSON_STRING_COMPARATOR);
Arrays.sort(keys, BinsonFieldNameComparator.INSTANCE);

boolean isFirstPair = true;

Expand Down Expand Up @@ -75,71 +74,6 @@ private static void writeValue(Output output, ValueType type, Object value) thro
default:
throw new Error("never happens, " + type.toString());
}

/*
int classNameLength = value.getClass().getName().length();
switch (classNameLength) {
case Constants.BOOLEAN_CLASSNAME_LENGTH:
if (value instanceof Boolean) {
output.writeBoolean((Boolean) value);
}
if (value instanceof Binson) {
Binson object = (Binson) value;
writeToOutput(object, output);
break;
}
break;
case Constants.LONG_CLASSNAME_LENGTH:
if (value instanceof Long) {
output.writeInteger((Long) value);
}
break;
case Constants.DOUBLE_CLASSNAME_LENGTH: // Double, String - same length
if (value instanceof Double) {
output.writeDouble((Double) value);
} else if (value instanceof String) {
output.writeString((String) value);
}
break;
case Constants.BYTES_CLASSNAME_LENGTH:
if (value instanceof byte[]) {
output.writeBytes((byte[]) value);
}
break;
default:
if (value instanceof Binson) {
Binson object = (Binson) value;
writeToOutput(object, output);
break;
} else if (value instanceof BinsonArray) {
BinsonArray array = (BinsonArray) value;
output.writeBeginArray();
boolean isFirst = true;
for (int i = 0; i < array.size(); i++) {
Object element = array.getElement(i);
if (isFirst) {
isFirst = false;
} else {
output.writeArrayValueSeparator();
}
writeValue(output, element);
}
output.writeEndArray();
} else {
// Note, this code does not support ignoring other value types.
}
break;
}
*/
}

private static void writeArray(BinsonArray array, Output output) throws IOException {
Expand Down

0 comments on commit ff2be91

Please sign in to comment.