Index: uspace/app/bithenge/blob.c
===================================================================
--- uspace/app/bithenge/blob.c	(revision 5f679702eab8b71b539c8b6540d64ad41702c3fb)
+++ uspace/app/bithenge/blob.c	(revision 5c925ce5a89fdac54d419c827dda95fc9f85e60e)
@@ -42,4 +42,5 @@
 #include <stdlib.h>
 #include "blob.h"
+#include "tree.h"
 
 /** Initialize a random access blob.
@@ -59,5 +60,6 @@
 	assert(ops->size);
 
-	blob->ops = ops;
+	blob->base.type = BITHENGE_NODE_BLOB;
+	blob->base.blob_ops = ops;
 	return EOK;
 }
@@ -234,5 +236,5 @@
  * @param len The length of the data.
  * @return EOK on success or an error code from errno.h. */
-int bithenge_new_blob_from_data(bithenge_blob_t **out, const void *data,
+int bithenge_new_blob_from_data(bithenge_node_t **out, const void *data,
     size_t len)
 {
@@ -258,5 +260,5 @@
 	blob->size = len;
 	blob->needs_free = true;
-	*out = blob_from_memory(blob);
+	*out = bithenge_blob_as_node(blob_from_memory(blob));
 	return EOK;
 }
@@ -273,5 +275,5 @@
  * blob is destroyed.
  * @return EOK on success or an error code from errno.h. */
-int bithenge_new_blob_from_buffer(bithenge_blob_t **out, const void *buffer,
+int bithenge_new_blob_from_buffer(bithenge_node_t **out, const void *buffer,
     size_t len, bool needs_free)
 {
@@ -291,5 +293,5 @@
 	blob->size = len;
 	blob->needs_free = needs_free;
-	*out = blob_from_memory(blob);
+	*out = bithenge_blob_as_node(blob_from_memory(blob));
 	return EOK;
 }
Index: uspace/app/bithenge/blob.h
===================================================================
--- uspace/app/bithenge/blob.h	(revision 5f679702eab8b71b539c8b6540d64ad41702c3fb)
+++ uspace/app/bithenge/blob.h	(revision 5c925ce5a89fdac54d419c827dda95fc9f85e60e)
@@ -39,10 +39,10 @@
 
 #include <sys/types.h>
+#include "tree.h"
 
 /** A blob of raw binary data. */
 typedef struct {
 	/** @privatesection */
-	/** Operations providing random access. */
-	const struct bithenge_random_access_blob_ops_t *ops;
+	struct bithenge_node_t base;
 } bithenge_blob_t;
 
@@ -121,6 +121,6 @@
 {
 	assert(blob);
-	assert(blob->ops);
-	return blob->ops->size(blob, size);
+	assert(blob->base.blob_ops);
+	return blob->base.blob_ops->size(blob, size);
 }
 
@@ -144,18 +144,16 @@
 {
 	assert(blob);
-	assert(blob->ops);
-	return blob->ops->read(blob, offset, buffer, size);
+	assert(blob->base.blob_ops);
+	return blob->base.blob_ops->read(blob, offset, buffer, size);
 }
 
-/** Destroy the blob.
- * @memberof bithenge_blob_t
- * @param blob The blob.
- * @return EOK on success or an error code from errno.h.
- */
-static inline int bithenge_blob_destroy(bithenge_blob_t *blob)
+static inline bithenge_node_t *bithenge_blob_as_node(bithenge_blob_t *blob)
 {
-	assert(blob);
-	assert(blob->ops);
-	return blob->ops->destroy(blob);
+	return &blob->base;
+}
+
+static inline bithenge_blob_t *bithenge_node_as_blob(bithenge_node_t *node)
+{
+	return (bithenge_blob_t *)node;
 }
 
@@ -166,8 +164,8 @@
     const bithenge_sequential_blob_ops_t *ops);
 
-int bithenge_new_blob_from_data(bithenge_blob_t **out, const void *data,
+int bithenge_new_blob_from_data(bithenge_node_t **out, const void *data,
     size_t len);
 
-int bithenge_new_blob_from_buffer(bithenge_blob_t **out, const void *buffer,
+int bithenge_new_blob_from_buffer(bithenge_node_t **out, const void *buffer,
     size_t len, bool needs_free);
 
Index: uspace/app/bithenge/block.c
===================================================================
--- uspace/app/bithenge/block.c	(revision 5f679702eab8b71b539c8b6540d64ad41702c3fb)
+++ uspace/app/bithenge/block.c	(revision 5c925ce5a89fdac54d419c827dda95fc9f85e60e)
@@ -97,5 +97,5 @@
  * @param service_id The service ID of the block device.
  * @return EOK on success or an error code from errno.h. */
-int bithenge_new_block_blob(bithenge_blob_t **out, service_id_t service_id)
+int bithenge_new_block_blob(bithenge_node_t **out, service_id_t service_id)
 {
 	assert(out);
@@ -138,5 +138,5 @@
 	blob->service_id = service_id;
 	blob->size = size;
-	*out = blob_from_block(blob);
+	*out = bithenge_blob_as_node(blob_from_block(blob));
 
 	return EOK;
Index: uspace/app/bithenge/block.h
===================================================================
--- uspace/app/bithenge/block.h	(revision 5f679702eab8b71b539c8b6540d64ad41702c3fb)
+++ uspace/app/bithenge/block.h	(revision 5c925ce5a89fdac54d419c827dda95fc9f85e60e)
@@ -41,5 +41,5 @@
 #include "blob.h"
 
-int bithenge_new_block_blob(bithenge_blob_t **, service_id_t);
+int bithenge_new_block_blob(bithenge_node_t **, service_id_t);
 
 #endif
Index: uspace/app/bithenge/file.c
===================================================================
--- uspace/app/bithenge/file.c	(revision 5f679702eab8b71b539c8b6540d64ad41702c3fb)
+++ uspace/app/bithenge/file.c	(revision 5c925ce5a89fdac54d419c827dda95fc9f85e60e)
@@ -97,5 +97,5 @@
 };
 
-static int new_file_blob(bithenge_blob_t **out, int fd, bool needs_close)
+static int new_file_blob(bithenge_node_t **out, int fd, bool needs_close)
 {
 	assert(out);
@@ -127,5 +127,5 @@
 	blob->size = stat.size;
 	blob->needs_close = needs_close;
-	*out = blob_from_file(blob);
+	*out = bithenge_blob_as_node(blob_from_file(blob));
 
 	return EOK;
@@ -137,5 +137,5 @@
  * @param filename The name of the file.
  * @return EOK on success or an error code from errno.h. */
-int bithenge_new_file_blob(bithenge_blob_t **out, const char *filename)
+int bithenge_new_file_blob(bithenge_node_t **out, const char *filename)
 {
 	assert(filename);
@@ -153,5 +153,5 @@
  * @param fd The file descriptor.
  * @return EOK on success or an error code from errno.h. */
-int bithenge_new_file_blob_from_fd(bithenge_blob_t **out, int fd)
+int bithenge_new_file_blob_from_fd(bithenge_node_t **out, int fd)
 {
 	return new_file_blob(out, fd, false);
@@ -163,5 +163,5 @@
  * @param file The file pointer.
  * @return EOK on success or an error code from errno.h. */
-int bithenge_new_file_blob_from_file(bithenge_blob_t **out, FILE *file)
+int bithenge_new_file_blob_from_file(bithenge_node_t **out, FILE *file)
 {
 	int fd = fileno(file);
Index: uspace/app/bithenge/file.h
===================================================================
--- uspace/app/bithenge/file.h	(revision 5f679702eab8b71b539c8b6540d64ad41702c3fb)
+++ uspace/app/bithenge/file.h	(revision 5c925ce5a89fdac54d419c827dda95fc9f85e60e)
@@ -41,7 +41,7 @@
 #include "blob.h"
 
-int bithenge_new_file_blob(bithenge_blob_t **, const char *);
-int bithenge_new_file_blob_from_fd(bithenge_blob_t **, int);
-int bithenge_new_file_blob_from_file(bithenge_blob_t **, FILE *);
+int bithenge_new_file_blob(bithenge_node_t **, const char *);
+int bithenge_new_file_blob_from_fd(bithenge_node_t **, int);
+int bithenge_new_file_blob_from_file(bithenge_node_t **, FILE *);
 
 #endif
Index: uspace/app/bithenge/print.c
===================================================================
--- uspace/app/bithenge/print.c	(revision 5f679702eab8b71b539c8b6540d64ad41702c3fb)
+++ uspace/app/bithenge/print.c	(revision 5c925ce5a89fdac54d419c827dda95fc9f85e60e)
@@ -37,4 +37,5 @@
 #include <errno.h>
 #include <stdio.h>
+#include "blob.h"
 #include "print.h"
 #include "tree.h"
@@ -120,4 +121,24 @@
 }
 
+static int print_blob(bithenge_print_type_t type, bithenge_node_t *node)
+{
+	bithenge_blob_t *blob = bithenge_node_as_blob(node);
+	aoff64_t pos = 0;
+	char buffer[1024];
+	aoff64_t size = sizeof(buffer);
+	int rc;
+	printf(type == BITHENGE_PRINT_PYTHON ? "b\"" : "\"");
+	do {
+		rc = bithenge_blob_read(blob, pos, buffer, &size);
+		if (rc != EOK)
+			return rc;
+		for (aoff64_t i = 0; i < size; i++)
+			printf("\\x%02x", buffer[i]);
+		pos += size;
+	} while (size == sizeof(buffer));
+	printf("\"");
+	return EOK;
+}
+
 int bithenge_print_node(bithenge_print_type_t type, bithenge_node_t *tree)
 {
@@ -133,4 +154,6 @@
 	case BITHENGE_NODE_STRING:
 		return print_string(type, tree);
+	case BITHENGE_NODE_BLOB:
+		return print_blob(type, tree);
 	}
 	return ENOTSUP;
Index: uspace/app/bithenge/test.c
===================================================================
--- uspace/app/bithenge/test.c	(revision 5f679702eab8b71b539c8b6540d64ad41702c3fb)
+++ uspace/app/bithenge/test.c	(revision 5c925ce5a89fdac54d419c827dda95fc9f85e60e)
@@ -53,6 +53,7 @@
 
 static void
-print_blob(bithenge_blob_t *blob)
+print_blob(bithenge_node_t *node)
 {
+	bithenge_blob_t *blob = bithenge_node_as_blob(node);
 	aoff64_t size;
 	bithenge_blob_size(blob, &size);
@@ -66,45 +67,44 @@
 int main(int argc, char *argv[])
 {
-	bithenge_blob_t *blob;
+	bithenge_node_t *node;
 
 	service_id_t service_id;
 	loc_service_get_id("bd/initrd", &service_id, 0);
-	bithenge_new_block_blob(&blob, service_id);
+	bithenge_new_block_blob(&node, service_id);
 	printf("Data from block:bd/initrd: ");
-	print_blob(blob);
-	bithenge_blob_destroy(blob);
+	print_blob(node);
+	bithenge_node_destroy(node);
 
 	const char data[] = "'Twas brillig, and the slithy toves";
-	bithenge_new_blob_from_data(&blob, data, sizeof(data));
+	bithenge_new_blob_from_data(&node, data, sizeof(data));
 	printf("Data from memory (from_data): ");
-	print_blob(blob);
-	bithenge_blob_destroy(blob);
+	print_blob(node);
+	bithenge_node_destroy(node);
 
-	bithenge_new_blob_from_buffer(&blob, data, sizeof(data), false);
+	bithenge_new_blob_from_buffer(&node, data, sizeof(data), false);
 	printf("Data from memory (from_buffer): ");
-	print_blob(blob);
-	bithenge_blob_destroy(blob);
+	print_blob(node);
+	bithenge_node_destroy(node);
 
-	bithenge_new_file_blob(&blob, "/textdemo");
+	bithenge_new_file_blob(&node, "/textdemo");
 	printf("Data from file:/textdemo: ");
-	print_blob(blob);
-	bithenge_blob_destroy(blob);
+	print_blob(node);
+	bithenge_node_destroy(node);
 
-	bithenge_new_file_blob_from_fd(&blob, 0);
+	bithenge_new_file_blob_from_fd(&node, 0);
 	printf("Data from fd:0: ");
-	print_blob(blob);
-	bithenge_blob_destroy(blob);
+	print_blob(node);
+	bithenge_node_destroy(node);
 
-	// {True: {}, -1351: "zero", "true": False, 0: 17}
-	bithenge_node_t *node;
+	// {True: {}, -1351: "\"false\"", "true": False, 0: b"..."}
 	bithenge_node_t *nodes[8];
 	bithenge_new_boolean_node(&nodes[0], true);
 	bithenge_new_simple_internal_node(&nodes[1], NULL, 0, false);
 	bithenge_new_integer_node(&nodes[2], -1351);
-	bithenge_new_string_node(&nodes[3], "zero", false);
+	bithenge_new_string_node(&nodes[3], "\"false\"", false);
 	bithenge_new_string_node(&nodes[4], "true", false);
 	bithenge_new_boolean_node(&nodes[5], false);
 	bithenge_new_integer_node(&nodes[6], 0);
-	bithenge_new_integer_node(&nodes[7], 17);
+	bithenge_new_blob_from_data(&nodes[7], data, sizeof(data));
 	bithenge_new_simple_internal_node(&node, nodes, 4, false);
 	bithenge_print_node(BITHENGE_PRINT_PYTHON, node);
Index: uspace/app/bithenge/tree.c
===================================================================
--- uspace/app/bithenge/tree.c	(revision 5f679702eab8b71b539c8b6540d64ad41702c3fb)
+++ uspace/app/bithenge/tree.c	(revision 5c925ce5a89fdac54d419c827dda95fc9f85e60e)
@@ -37,9 +37,19 @@
 #include <errno.h>
 #include <stdlib.h>
+#include "blob.h"
 #include "tree.h"
+
+static int blob_destroy(bithenge_node_t *base)
+{
+	bithenge_blob_t *blob = bithenge_node_as_blob(base);
+	assert(blob->base.blob_ops);
+	return blob->base.blob_ops->destroy(blob);
+}
 
 int bithenge_node_destroy(bithenge_node_t *node)
 {
 	switch (bithenge_node_type(node)) {
+	case BITHENGE_NODE_BLOB:
+		return blob_destroy(node);
 	case BITHENGE_NODE_STRING:
 		if (node->string_value.needs_free)
@@ -47,6 +57,5 @@
 		break;
 	case BITHENGE_NODE_INTERNAL:
-		/* TODO */
-		break;
+		return node->internal_ops->destroy(node);
 	case BITHENGE_NODE_BOOLEAN:
 		return EOK; // the boolean nodes are allocated statically below
@@ -84,6 +93,25 @@
 }
 
+static int simple_internal_node_destroy(bithenge_node_t *base)
+{
+	int rc;
+	simple_internal_node_t *node = node_as_simple(base);
+	for (bithenge_int_t i = 0; i < node->len; i++) {
+		rc = bithenge_node_destroy(node->nodes[2*i+0]);
+		if (rc != EOK)
+			return rc;
+		rc = bithenge_node_destroy(node->nodes[2*i+1]);
+		if (rc != EOK)
+			return rc;
+	}
+	if (node->needs_free)
+		free(node->nodes);
+	free(node);
+	return EOK;
+}
+
 static bithenge_internal_node_ops_t simple_internal_node_ops = {
-	.for_each = simple_internal_node_for_each
+	.for_each = simple_internal_node_for_each,
+	.destroy = simple_internal_node_destroy,
 };
 
Index: uspace/app/bithenge/tree.h
===================================================================
--- uspace/app/bithenge/tree.h	(revision 5f679702eab8b71b539c8b6540d64ad41702c3fb)
+++ uspace/app/bithenge/tree.h	(revision 5c925ce5a89fdac54d419c827dda95fc9f85e60e)
@@ -57,5 +57,5 @@
 	BITHENGE_NODE_INTEGER,
 	BITHENGE_NODE_STRING,
-	// TODO: BITHENGE_NODE_BLOB,
+	BITHENGE_NODE_BLOB,
 } bithenge_node_type_t;
 
@@ -63,5 +63,5 @@
 	bithenge_node_type_t type;
 	union {
-		struct bithenge_internal_node_ops_t *internal_ops;
+		const struct bithenge_internal_node_ops_t *internal_ops;
 		bool boolean_value;
 		bithenge_int_t integer_value;
@@ -70,4 +70,5 @@
 			bool needs_free;
 		} string_value;
+		const struct bithenge_random_access_blob_ops_t *blob_ops;
 	};
 } bithenge_node_t;
@@ -82,8 +83,10 @@
 typedef struct bithenge_internal_node_ops_t {
 	int (*for_each)(bithenge_node_t *node, bithenge_for_each_func_t func, void *data);
+	int (*destroy)(bithenge_node_t *node);
 } bithenge_internal_node_ops_t;
 
 static inline int bithenge_node_for_each(bithenge_node_t *node, bithenge_for_each_func_t func, void *data)
 {
+	assert(node->type == BITHENGE_NODE_INTERNAL);
 	return node->internal_ops->for_each(node, func, data);
 }
@@ -91,4 +94,5 @@
 static inline bool bithenge_boolean_node_value(bithenge_node_t *node)
 {
+	assert(node->type == BITHENGE_NODE_BOOLEAN);
 	return node->boolean_value;
 }
@@ -96,4 +100,5 @@
 static inline bithenge_int_t bithenge_integer_node_value(bithenge_node_t *node)
 {
+	assert(node->type == BITHENGE_NODE_INTEGER);
 	return node->integer_value;
 }
@@ -101,4 +106,5 @@
 static inline const char *bithenge_string_node_value(bithenge_node_t *node)
 {
+	assert(node->type == BITHENGE_NODE_STRING);
 	return node->string_value.ptr;
 }
