Simplified serialisation format.

This commit is contained in:
akwizgran
2012-05-08 11:02:49 +02:00
parent a82ae82108
commit 78e18fb373
6 changed files with 85 additions and 82 deletions

View File

@@ -181,7 +181,7 @@ class ReaderImpl implements Reader {
private int readInt32Bits() throws IOException {
readIntoBuffer(4);
return ((buf[0] & 0xFF) << 24) | ((buf[1] & 0xFF) << 16) |
((buf[2] & 0xFF) << 8) | (buf[3] & 0xFF);
((buf[2] & 0xFF) << 8) | (buf[3] & 0xFF);
}
private void readIntoBuffer(int length) throws IOException {
@@ -220,16 +220,16 @@ class ReaderImpl implements Reader {
private long readInt64Bits() throws IOException {
readIntoBuffer(8);
return ((buf[0] & 0xFFL) << 56) | ((buf[1] & 0xFFL) << 48) |
((buf[2] & 0xFFL) << 40) | ((buf[3] & 0xFFL) << 32) |
((buf[4] & 0xFFL) << 24) | ((buf[5] & 0xFFL) << 16) |
((buf[6] & 0xFFL) << 8) | (buf[7] & 0xFFL);
((buf[2] & 0xFFL) << 40) | ((buf[3] & 0xFFL) << 32) |
((buf[4] & 0xFFL) << 24) | ((buf[5] & 0xFFL) << 16) |
((buf[6] & 0xFFL) << 8) | (buf[7] & 0xFFL);
}
public boolean hasIntAny() throws IOException {
if(!hasLookahead) readLookahead(true);
if(eof) return false;
return next >= 0 || next == Tag.INT8 || next == Tag.INT16
|| next == Tag.INT32 || next == Tag.INT64;
|| next == Tag.INT32 || next == Tag.INT64;
}
public long readIntAny() throws IOException {
@@ -270,7 +270,7 @@ class ReaderImpl implements Reader {
if(!hasLookahead) readLookahead(true);
if(eof) return false;
return next == Tag.STRING
|| (next & Tag.SHORT_MASK) == Tag.SHORT_STRING;
|| (next & Tag.SHORT_MASK) == Tag.SHORT_STRING;
}
public String readString() throws IOException {
@@ -302,7 +302,7 @@ class ReaderImpl implements Reader {
if(!hasLookahead) readLookahead(true);
if(eof) return false;
return next >= 0 || next == Tag.INT8 || next == Tag.INT16
|| next == Tag.INT32;
|| next == Tag.INT32;
}
public boolean hasBytes() throws IOException {
@@ -331,8 +331,8 @@ class ReaderImpl implements Reader {
public boolean hasList() throws IOException {
if(!hasLookahead) readLookahead(true);
if(eof) return false;
return next == Tag.LIST || next == Tag.LIST_START
|| (next & Tag.SHORT_MASK) == Tag.SHORT_LIST;
return next == Tag.LIST
|| (next & Tag.SHORT_MASK) == Tag.SHORT_LIST;
}
public List<Object> readList() throws IOException {
@@ -343,8 +343,6 @@ class ReaderImpl implements Reader {
if(!hasList()) throw new FormatException();
consumeLookahead();
if(next == Tag.LIST) {
return readList(e, readLength());
} else if(next == Tag.LIST_START) {
List<E> list = new ArrayList<E>();
while(!hasEnd()) list.add(readObject(e));
readEnd();
@@ -400,7 +398,7 @@ class ReaderImpl implements Reader {
if(!hasLookahead) readLookahead(true);
if(eof) return false;
return next == Tag.STRUCT
|| (next & Tag.SHORT_STRUCT_MASK) == Tag.SHORT_STRUCT;
|| (next & Tag.SHORT_STRUCT_MASK) == Tag.SHORT_STRUCT;
}
private Object readStruct() throws IOException {
@@ -441,7 +439,7 @@ class ReaderImpl implements Reader {
public boolean hasListStart() throws IOException {
if(!hasLookahead) readLookahead(true);
if(eof) return false;
return next == Tag.LIST_START;
return next == Tag.LIST;
}
public void readListStart() throws IOException {
@@ -460,8 +458,8 @@ class ReaderImpl implements Reader {
public boolean hasMap() throws IOException {
if(!hasLookahead) readLookahead(true);
if(eof) return false;
return next == Tag.MAP || next == Tag.MAP_START
|| (next & Tag.SHORT_MASK) == Tag.SHORT_MAP;
return next == Tag.MAP
|| (next & Tag.SHORT_MASK) == Tag.SHORT_MAP;
}
public Map<Object, Object> readMap() throws IOException {
@@ -472,8 +470,6 @@ class ReaderImpl implements Reader {
if(!hasMap()) throw new FormatException();
consumeLookahead();
if(next == Tag.MAP) {
return readMap(k, v, readLength());
} else if(next == Tag.MAP_START) {
Map<K, V> m = new HashMap<K, V>();
while(!hasEnd()) {
if(m.put(readObject(k), readObject(v)) != null)
@@ -488,7 +484,7 @@ class ReaderImpl implements Reader {
}
private <K, V> Map<K, V> readMap(Class<K> k, Class<V> v, int size)
throws IOException {
throws IOException {
assert size >= 0;
if(size == 0) return Collections.emptyMap();
Map<K, V> m = new HashMap<K, V>();
@@ -502,7 +498,7 @@ class ReaderImpl implements Reader {
public boolean hasMapStart() throws IOException {
if(!hasLookahead) readLookahead(true);
if(eof) return false;
return next == Tag.MAP_START;
return next == Tag.MAP;
}
public void readMapStart() throws IOException {

View File

@@ -11,7 +11,7 @@ class SerialComponentImpl implements SerialComponent {
}
public int getSerialisedListStartLength() {
// LIST_START tag
// LIST tag
return 1;
}

View File

@@ -2,30 +2,28 @@ package net.sf.briar.serial;
interface Tag {
static final byte FALSE = -1; // 1111 1111
static final byte TRUE = -2; // 1111 1110
static final byte INT8 = -3; // 1111 1101
static final byte INT16 = -4; // 1111 1100
static final byte INT32 = -5; // 1111 1011
static final byte INT64 = -6; // 1111 1010
static final byte FLOAT32 = -7; // 1111 1001
static final byte FLOAT64 = -8; // 1111 1000
static final byte STRING = -9; // 1111 0111
static final byte BYTES = -10; // 1111 0110
static final byte LIST = -11; // 1111 0101
static final byte MAP = -12; // 1111 0100
static final byte LIST_START = -13; // 1111 0011
static final byte MAP_START = -14; // 1111 0010
static final byte END = -15; // 1111 0001
static final byte NULL = -16; // 1111 0000
static final byte STRUCT = -17; // 1110 1111
static final byte FALSE = (byte) 0xFF; // 1111 1111
static final byte TRUE = (byte) 0xFE; // 1111 1110
static final byte INT8 = (byte) 0xFD; // 1111 1101
static final byte INT16 = (byte) 0xFC; // 1111 1100
static final byte INT32 = (byte) 0xFB; // 1111 1011
static final byte INT64 = (byte) 0xFA; // 1111 1010
static final byte FLOAT32 = (byte) 0xF9; // 1111 1001
static final byte FLOAT64 = (byte) 0xF8; // 1111 1000
static final byte STRING = (byte) 0xF7; // 1111 0111
static final byte BYTES = (byte) 0xF6; // 1111 0110
static final byte LIST = (byte) 0xF5; // 1111 0111
static final byte MAP = (byte) 0xF4; // 1111 0100
static final byte END = (byte) 0xF3; // 1111 0011
static final byte NULL = (byte) 0xF2; // 1111 0010
static final byte STRUCT = (byte) 0xF1; // 1111 0001
static final int SHORT_MASK = 0xF0; // Match first four bits
static final int SHORT_STRING = 0x80; // 1000 xxxx
static final int SHORT_BYTES = 0x90; // 1001 xxxx
static final int SHORT_LIST = 0xA0; // 1010 xxxx
static final int SHORT_MAP = 0xB0; // 1011 xxxx
static final int SHORT_STRUCT_MASK = 0xE0; // Match first three bits
static final int SHORT_STRUCT = 0xC0; // 110x xxxx
static final int SHORT_MASK = 0xF0; // Match first four bits
static final int SHORT_STRUCT_MASK = 0xE0; // Match first three bits
}

View File

@@ -103,8 +103,9 @@ class WriterImpl implements Writer {
public void writeString(String s) throws IOException {
byte[] b = s.getBytes("UTF-8");
if(b.length < 16) write((byte) (Tag.SHORT_STRING | b.length));
else {
if(b.length < 16) {
write((byte) (Tag.SHORT_STRING | b.length));
} else {
write(Tag.STRING);
writeLength(b.length);
}
@@ -120,8 +121,9 @@ class WriterImpl implements Writer {
}
public void writeBytes(byte[] b) throws IOException {
if(b.length < 16) write((byte) (Tag.SHORT_BYTES | b.length));
else {
if(b.length < 16) {
write((byte) (Tag.SHORT_BYTES | b.length));
} else {
write(Tag.BYTES);
writeLength(b.length);
}
@@ -130,12 +132,14 @@ class WriterImpl implements Writer {
public void writeList(Collection<?> c) throws IOException {
int length = c.size();
if(length < 16) write((byte) (Tag.SHORT_LIST | length));
else {
if(length < 16) {
write((byte) (Tag.SHORT_LIST | length));
for(Object o : c) writeObject(o);
} else {
write(Tag.LIST);
writeLength(length);
for(Object o : c) writeObject(o);
write(Tag.END);
}
for(Object o : c) writeObject(o);
}
private void writeObject(Object o) throws IOException {
@@ -155,7 +159,7 @@ class WriterImpl implements Writer {
}
public void writeListStart() throws IOException {
write(Tag.LIST_START);
write(Tag.LIST);
}
public void writeListEnd() throws IOException {
@@ -164,19 +168,24 @@ class WriterImpl implements Writer {
public void writeMap(Map<?, ?> m) throws IOException {
int length = m.size();
if(length < 16) write((byte) (Tag.SHORT_MAP | length));
else {
if(length < 16) {
write((byte) (Tag.SHORT_MAP | length));
for(Entry<?, ?> e : m.entrySet()) {
writeObject(e.getKey());
writeObject(e.getValue());
}
} else {
write(Tag.MAP);
writeLength(length);
}
for(Entry<?, ?> e : m.entrySet()) {
writeObject(e.getKey());
writeObject(e.getValue());
for(Entry<?, ?> e : m.entrySet()) {
writeObject(e.getKey());
writeObject(e.getValue());
}
write(Tag.END);
}
}
public void writeMapStart() throws IOException {
write(Tag.MAP_START);
write(Tag.MAP);
}
public void writeMapEnd() throws IOException {

View File

@@ -178,7 +178,7 @@ public class ReaderImplTest extends BriarTestCase {
@Test
public void testReadList() throws Exception {
setContents("F5" + "03" + "01" + "83666F6F" + "FC0080");
setContents("F5" + "01" + "83666F6F" + "FC0080" + "F3");
List<Object> l = r.readList(Object.class);
assertNotNull(l);
assertEquals(3, l.size());
@@ -213,7 +213,7 @@ public class ReaderImplTest extends BriarTestCase {
@Test
public void testReadShortMap() throws Exception {
setContents("B" + "2" + "83666F6F" + "7B" + "90" + "F0");
setContents("B" + "2" + "83666F6F" + "7B" + "90" + "F2");
Map<Object, Object> m = r.readMap(Object.class, Object.class);
assertNotNull(m);
assertEquals(2, m.size());
@@ -226,7 +226,7 @@ public class ReaderImplTest extends BriarTestCase {
@Test
public void testReadMap() throws Exception {
setContents("F4" + "02" + "83666F6F" + "7B" + "90" + "F0");
setContents("F4" + "83666F6F" + "7B" + "90" + "F2" + "F3");
Map<Object, Object> m = r.readMap(Object.class, Object.class);
assertNotNull(m);
assertEquals(2, m.size());
@@ -239,7 +239,7 @@ public class ReaderImplTest extends BriarTestCase {
@Test
public void testReadMapTypeSafe() throws Exception {
setContents("B" + "2" + "83666F6F" + "7B" + "80" + "F0");
setContents("B" + "2" + "83666F6F" + "7B" + "80" + "F2");
Map<String, Byte> m = r.readMap(String.class, Byte.class);
assertNotNull(m);
assertEquals(2, m.size());
@@ -268,7 +268,7 @@ public class ReaderImplTest extends BriarTestCase {
@Test
public void testReadDelimitedList() throws Exception {
setContents("F3" + "01" + "83666F6F" + "FC0080" + "F1");
setContents("F5" + "01" + "83666F6F" + "FC0080" + "F3");
List<Object> l = r.readList(Object.class);
assertNotNull(l);
assertEquals(3, l.size());
@@ -280,7 +280,7 @@ public class ReaderImplTest extends BriarTestCase {
@Test
public void testReadDelimitedListElements() throws Exception {
setContents("F3" + "01" + "83666F6F" + "FC0080" + "F1");
setContents("F5" + "01" + "83666F6F" + "FC0080" + "F3");
assertTrue(r.hasListStart());
r.readListStart();
assertFalse(r.hasListEnd());
@@ -296,7 +296,7 @@ public class ReaderImplTest extends BriarTestCase {
@Test
public void testReadDelimitedListTypeSafe() throws Exception {
setContents("F3" + "01" + "02" + "03" + "F1");
setContents("F5" + "01" + "02" + "03" + "F3");
List<Byte> l = r.readList(Byte.class);
assertNotNull(l);
assertEquals(3, l.size());
@@ -308,7 +308,7 @@ public class ReaderImplTest extends BriarTestCase {
@Test
public void testReadDelimitedMap() throws Exception {
setContents("F2" + "83666F6F" + "7B" + "90" + "F0" + "F1");
setContents("F4" + "83666F6F" + "7B" + "90" + "F2" + "F3");
Map<Object, Object> m = r.readMap(Object.class, Object.class);
assertNotNull(m);
assertEquals(2, m.size());
@@ -321,7 +321,7 @@ public class ReaderImplTest extends BriarTestCase {
@Test
public void testReadDelimitedMapEntries() throws Exception {
setContents("F2" + "83666F6F" + "7B" + "90" + "F0" + "F1");
setContents("F4" + "83666F6F" + "7B" + "90" + "F2" + "F3");
assertTrue(r.hasMapStart());
r.readMapStart();
assertFalse(r.hasMapEnd());
@@ -340,7 +340,7 @@ public class ReaderImplTest extends BriarTestCase {
@Test
public void testReadDelimitedMapTypeSafe() throws Exception {
setContents("F2" + "83666F6F" + "7B" + "80" + "F0" + "F1");
setContents("F4" + "83666F6F" + "7B" + "80" + "F2" + "F3");
Map<String, Byte> m = r.readMap(String.class, Byte.class);
assertNotNull(m);
assertEquals(2, m.size());
@@ -372,7 +372,7 @@ public class ReaderImplTest extends BriarTestCase {
@Test
public void testReadStruct() throws Exception {
setContents("C0" + "83666F6F" + "EF" + "FF" + "83666F6F");
setContents("C0" + "83666F6F" + "F1" + "FF" + "83666F6F");
// Add object readers for two structs
r.addObjectReader(0, new ObjectReader<Foo>() {
public Foo readObject(Reader r) throws IOException {
@@ -395,7 +395,7 @@ public class ReaderImplTest extends BriarTestCase {
@Test
public void testReadStructWithConsumer() throws Exception {
setContents("C0" + "83666F6F" + "EF" + "FF" + "83666F6F");
setContents("C0" + "83666F6F" + "F1" + "FF" + "83666F6F");
// Add object readers for two structs
r.addObjectReader(0, new ObjectReader<Foo>() {
public Foo readObject(Reader r) throws IOException {
@@ -427,7 +427,7 @@ public class ReaderImplTest extends BriarTestCase {
assertTrue(r.hasStruct(255));
assertEquals("foo", r.readStruct(255, Bar.class).s);
// Check that everything was passed to the consumer
assertEquals("C0" + "83666F6F" + "EF" + "FF" + "83666F6F",
assertEquals("C0" + "83666F6F" + "F1" + "FF" + "83666F6F",
StringUtils.toHexString(out.toByteArray()));
}

View File

@@ -179,8 +179,8 @@ public class WriterImplTest extends BriarTestCase {
List<Object> l = new ArrayList<Object>();
for(int i = 0; i < 16; i++) l.add(i);
w.writeList(l);
// LIST tag, length as uint7, elements as uint7
checkContents("F5" + "10" + "000102030405060708090A0B0C0D0E0F");
// LIST tag, elements as uint7, END tag
checkContents("F5" + "000102030405060708090A0B0C0D0E0F" + "F3");
}
@Test
@@ -191,7 +191,7 @@ public class WriterImplTest extends BriarTestCase {
l.add(2);
w.writeList(l);
// SHORT_LIST tag, length, 1 as uint7, null, 2 as uint7
checkContents("A" + "3" + "01" + "F0" + "02");
checkContents("A" + "3" + "01" + "F2" + "02");
}
@Test
@@ -212,10 +212,10 @@ public class WriterImplTest extends BriarTestCase {
Map<Object, Object> m = new LinkedHashMap<Object, Object>();
for(int i = 0; i < 16; i++) m.put(i, i + 1);
w.writeMap(m);
// MAP tag, size as uint7, entries as uint7
checkContents("F4" + "10" + "0001" + "0102" + "0203" + "0304" + "0405"
// MAP tag, entries as uint7, END tag
checkContents("F4" + "0001" + "0102" + "0203" + "0304" + "0405"
+ "0506" + "0607" + "0708" + "0809" + "090A" + "0A0B" + "0B0C"
+ "0C0D" + "0D0E" + "0E0F" + "0F10");
+ "0C0D" + "0D0E" + "0E0F" + "0F10" + "F3");
}
@Test
@@ -225,9 +225,9 @@ public class WriterImplTest extends BriarTestCase {
w.writeString("foo"); // Written as short string
w.writeIntAny(128L); // Written as an int16
w.writeListEnd();
// LIST_START tag, 1 as uint7, "foo" as short string, 128 as int16,
// LIST tag, 1 as uint7, "foo" as short string, 128 as int16,
// END tag
checkContents("F3" + "01" + "83666F6F" + "FC0080" + "F1");
checkContents("F5" + "01" + "83666F6F" + "FC0080" + "F3");
}
@Test
@@ -238,9 +238,9 @@ public class WriterImplTest extends BriarTestCase {
w.writeBytes(new byte[] {}); // Written as short bytes
w.writeNull();
w.writeMapEnd();
// MAP_START tag, "foo" as short string, 123 as uint7,
// MAP tag, "foo" as short string, 123 as uint7,
// byte[] {} as short bytes, NULL tag, END tag
checkContents("F2" + "83666F6F" + "7B" + "90" + "F0" + "F1");
checkContents("F4" + "83666F6F" + "7B" + "90" + "F2" + "F3");
}
@Test
@@ -261,7 +261,7 @@ public class WriterImplTest extends BriarTestCase {
@Test
public void testWriteNull() throws IOException {
w.writeNull();
checkContents("F0");
checkContents("F2");
}
@Test
@@ -278,7 +278,7 @@ public class WriterImplTest extends BriarTestCase {
w.writeStructId(32);
w.writeStructId(255);
// STRUCT tag, 32 as uint8, STRUCT tag, 255 as uint8
checkContents("EF" + "20" + "EF" + "FF");
checkContents("F1" + "20" + "F1" + "FF");
}
private void checkContents(String hex) throws IOException {