diff --git a/components/net/sf/briar/serial/ReaderImpl.java b/components/net/sf/briar/serial/ReaderImpl.java
index acb514460eafde19d2da3cf11039527dce3b87a3..7e4dc4c192e91e1298cde03280977cede496d789 100644
--- a/components/net/sf/briar/serial/ReaderImpl.java
+++ b/components/net/sf/briar/serial/ReaderImpl.java
@@ -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 {
diff --git a/components/net/sf/briar/serial/SerialComponentImpl.java b/components/net/sf/briar/serial/SerialComponentImpl.java
index 67c898272b65eb5b17895f4cabd4b72c33070f1f..950be7be1389e86511399c5ef1adeb1e068840e4 100644
--- a/components/net/sf/briar/serial/SerialComponentImpl.java
+++ b/components/net/sf/briar/serial/SerialComponentImpl.java
@@ -11,7 +11,7 @@ class SerialComponentImpl implements SerialComponent {
 	}
 
 	public int getSerialisedListStartLength() {
-		// LIST_START tag
+		// LIST tag
 		return 1;
 	}
 
diff --git a/components/net/sf/briar/serial/Tag.java b/components/net/sf/briar/serial/Tag.java
index 895079b4d46409bb5882f98f21f2ad5d55e6ff8b..20dffc0fd2d767c327b91e9e035b14d856bf16a6 100644
--- a/components/net/sf/briar/serial/Tag.java
+++ b/components/net/sf/briar/serial/Tag.java
@@ -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 = 0xC0; // 110x xxxx
 
+	static final int SHORT_MASK = 0xF0; // Match first four bits
 	static final int SHORT_STRUCT_MASK = 0xE0; // Match first three bits
-	static final int SHORT_STRUCT = 0xC0; // 110x xxxx
 }
diff --git a/components/net/sf/briar/serial/WriterImpl.java b/components/net/sf/briar/serial/WriterImpl.java
index 24060b0f68d3f8bf3d62a6f07995b371670aa532..239e15fc3c42051a8e4f68ef81ba707ef9851f79 100644
--- a/components/net/sf/briar/serial/WriterImpl.java
+++ b/components/net/sf/briar/serial/WriterImpl.java
@@ -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 {
diff --git a/test/net/sf/briar/serial/ReaderImplTest.java b/test/net/sf/briar/serial/ReaderImplTest.java
index 1ba3d19048f17a07435ef6fc4876e0b4b5521f01..49a7888d27345473340ea917dd3cf6cf7fc9510c 100644
--- a/test/net/sf/briar/serial/ReaderImplTest.java
+++ b/test/net/sf/briar/serial/ReaderImplTest.java
@@ -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()));
 	}
 
diff --git a/test/net/sf/briar/serial/WriterImplTest.java b/test/net/sf/briar/serial/WriterImplTest.java
index bfb697d6c47739be5d8f99fe37a9763e9d01d6e6..7c9112e9d0fedb68072371a369755f2120266654 100644
--- a/test/net/sf/briar/serial/WriterImplTest.java
+++ b/test/net/sf/briar/serial/WriterImplTest.java
@@ -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 {