diff --git a/briar-api/src/org/briarproject/api/data/BdfDictionary.java b/briar-api/src/org/briarproject/api/data/BdfDictionary.java
index 113d0334c2c4fcc5797349213c99f4f9d450d3a6..ed0d5b98f95492b6d77668183053afc6ab963096 100644
--- a/briar-api/src/org/briarproject/api/data/BdfDictionary.java
+++ b/briar-api/src/org/briarproject/api/data/BdfDictionary.java
@@ -4,11 +4,36 @@ import org.briarproject.api.Bytes;
 import org.briarproject.api.FormatException;
 
 import java.util.Hashtable;
+import java.util.Map;
+import java.util.Map.Entry;
 
 public class BdfDictionary extends Hashtable<String, Object> {
 
 	public static final Object NULL_VALUE = new Object();
 
+	/**
+	 * Factory method for constructing dictionaries inline.
+	 * <pre>
+	 * BdfDictionary.of(
+	 *     new BdfEntry("foo", foo),
+	 *     new BdfEntry("bar", bar)
+	 * );
+	 * </pre>
+	 */
+	public static BdfDictionary of(Entry<String, Object>... entries) {
+		BdfDictionary d = new BdfDictionary();
+		for (Entry<String, Object> e : entries) d.put(e.getKey(), e.getValue());
+		return d;
+	}
+
+	public BdfDictionary() {
+		super();
+	}
+
+	public BdfDictionary(Map<String, Object> m) {
+		super(m);
+	}
+
 	public Boolean getBoolean(String key) throws FormatException {
 		Object o = get(key);
 		if (o instanceof Boolean) return (Boolean) o;
diff --git a/briar-api/src/org/briarproject/api/data/BdfEntry.java b/briar-api/src/org/briarproject/api/data/BdfEntry.java
new file mode 100644
index 0000000000000000000000000000000000000000..0168d2a3c5672661b4896ea300ed587765b160bd
--- /dev/null
+++ b/briar-api/src/org/briarproject/api/data/BdfEntry.java
@@ -0,0 +1,32 @@
+package org.briarproject.api.data;
+
+import java.util.Map.Entry;
+
+// This class is not thread-safe
+public class BdfEntry implements Entry<String, Object> {
+
+	private final String key;
+	private Object value;
+
+	public BdfEntry(String key, Object value) {
+		this.key = key;
+		this.value = value;
+	}
+
+	@Override
+	public String getKey() {
+		return key;
+	}
+
+	@Override
+	public Object getValue() {
+		return value;
+	}
+
+	@Override
+	public Object setValue(Object value) {
+		Object oldValue = this.value;
+		this.value = value;
+		return oldValue;
+	}
+}
diff --git a/briar-api/src/org/briarproject/api/data/BdfList.java b/briar-api/src/org/briarproject/api/data/BdfList.java
index a9c7a4344118ef7a3b3af4602c0d4c476aa71cfb..2d58bcd388c0e33cc8f9b2b0c767efb8437bac04 100644
--- a/briar-api/src/org/briarproject/api/data/BdfList.java
+++ b/briar-api/src/org/briarproject/api/data/BdfList.java
@@ -3,10 +3,30 @@ package org.briarproject.api.data;
 import org.briarproject.api.Bytes;
 import org.briarproject.api.FormatException;
 
+import java.util.Arrays;
+import java.util.List;
 import java.util.Vector;
 
 public class BdfList extends Vector<Object> {
 
+	/**
+	 * Factory method for constructing lists inline.
+	 * <pre>
+	 * BdfList.of(1, 2, 3);
+	 * </pre>
+	 */
+	public static BdfList of(Object... items) {
+		return new BdfList(Arrays.asList(items));
+	}
+
+	public BdfList() {
+		super();
+	}
+
+	public BdfList(List<Object> items) {
+		super(items);
+	}
+
 	public Boolean getBoolean(int index) throws FormatException {
 		Object o = get(index);
 		if (o instanceof Boolean) return (Boolean) o;
diff --git a/briar-tests/src/org/briarproject/data/BdfDictionaryTest.java b/briar-tests/src/org/briarproject/data/BdfDictionaryTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..99e42bcf236d4558c78fd26068f87ea42a580cab
--- /dev/null
+++ b/briar-tests/src/org/briarproject/data/BdfDictionaryTest.java
@@ -0,0 +1,61 @@
+package org.briarproject.data;
+
+import org.briarproject.BriarTestCase;
+import org.briarproject.api.Bytes;
+import org.briarproject.api.data.BdfDictionary;
+import org.briarproject.api.data.BdfEntry;
+import org.junit.Test;
+
+import java.util.Collections;
+
+import static org.briarproject.api.data.BdfDictionary.NULL_VALUE;
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+
+public class BdfDictionaryTest extends BriarTestCase {
+
+	@Test
+	public void testConstructors() {
+		assertEquals(Collections.emptyMap(), new BdfDictionary());
+		assertEquals(Collections.singletonMap("foo", NULL_VALUE),
+				new BdfDictionary(Collections.singletonMap("foo", NULL_VALUE)));
+	}
+
+	@Test
+	public void testFactoryMethod() {
+		assertEquals(Collections.emptyMap(), BdfDictionary.of());
+		assertEquals(Collections.singletonMap("foo", NULL_VALUE),
+				BdfDictionary.of(new BdfEntry("foo", NULL_VALUE)));
+	}
+
+	@Test
+	public void testIntegerPromotion() throws Exception {
+		BdfDictionary d = new BdfDictionary();
+		d.put("foo", (byte) 1);
+		d.put("bar", (short) 2);
+		d.put("baz", 3);
+		d.put("bam", 4L);
+		assertEquals(Long.valueOf(1), d.getInteger("foo"));
+		assertEquals(Long.valueOf(2), d.getInteger("bar"));
+		assertEquals(Long.valueOf(3), d.getInteger("baz"));
+		assertEquals(Long.valueOf(4), d.getInteger("bam"));
+	}
+
+	@Test
+	public void testFloatPromotion() throws Exception {
+		BdfDictionary d = new BdfDictionary();
+		d.put("foo", 1F);
+		d.put("bar", 2D);
+		assertEquals(Double.valueOf(1), d.getFloat("foo"));
+		assertEquals(Double.valueOf(2), d.getFloat("bar"));
+	}
+
+	@Test
+	public void testByteArrayUnwrapping() throws Exception {
+		BdfDictionary d = new BdfDictionary();
+		d.put("foo", new byte[123]);
+		d.put("bar", new Bytes(new byte[123]));
+		assertArrayEquals(new byte[123], d.getRaw("foo"));
+		assertArrayEquals(new byte[123], d.getRaw("bar"));
+	}
+}
diff --git a/briar-tests/src/org/briarproject/data/BdfListTest.java b/briar-tests/src/org/briarproject/data/BdfListTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..4b0275faadcc1b7e99c86c9e8b94e03d2eeda509
--- /dev/null
+++ b/briar-tests/src/org/briarproject/data/BdfListTest.java
@@ -0,0 +1,61 @@
+package org.briarproject.data;
+
+import org.briarproject.BriarTestCase;
+import org.briarproject.api.Bytes;
+import org.briarproject.api.data.BdfList;
+import org.junit.Test;
+
+import java.util.Arrays;
+import java.util.Collections;
+
+import static org.briarproject.api.data.BdfDictionary.NULL_VALUE;
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+
+public class BdfListTest extends BriarTestCase {
+
+	@Test
+	public void testConstructors() {
+		assertEquals(Collections.emptyList(), new BdfList());
+		assertEquals(Arrays.asList(1, 2, NULL_VALUE),
+				new BdfList(Arrays.asList(1, 2, NULL_VALUE)));
+	}
+
+	@Test
+	public void testFactoryMethod() {
+		assertEquals(Collections.emptyList(), BdfList.of());
+		assertEquals(Arrays.asList(1, 2, NULL_VALUE),
+				BdfList.of(1, 2, NULL_VALUE));
+	}
+
+	@Test
+	public void testIntegerPromotion() throws Exception {
+		BdfList list = new BdfList();
+		list.add((byte) 1);
+		list.add((short) 2);
+		list.add(3);
+		list.add(4L);
+		assertEquals(Long.valueOf(1), list.getInteger(0));
+		assertEquals(Long.valueOf(2), list.getInteger(1));
+		assertEquals(Long.valueOf(3), list.getInteger(2));
+		assertEquals(Long.valueOf(4), list.getInteger(3));
+	}
+
+	@Test
+	public void testFloatPromotion() throws Exception {
+		BdfList list = new BdfList();
+		list.add(1F);
+		list.add(2D);
+		assertEquals(Double.valueOf(1), list.getFloat(0));
+		assertEquals(Double.valueOf(2), list.getFloat(1));
+	}
+
+	@Test
+	public void testByteArrayUnwrapping() throws Exception {
+		BdfList list = new BdfList();
+		list.add(new byte[123]);
+		list.add(new Bytes(new byte[123]));
+		assertArrayEquals(new byte[123], list.getRaw(0));
+		assertArrayEquals(new byte[123], list.getRaw(1));
+	}
+}