+ if (!(head->prop_name = upkg_get_name(upkg, index)))
+ return 0;
+ len += rc;
+
+ /* A property called "None" terminates the list, and does not have
+ * the usual header. */
+ if (!strcmp(head->prop_name, "None")) {
+ head->type = PROPERTY_END;
+ head->size = 0;
+ return len;
+ }
+
+ if (n-len < 1)
+ return 0;
+ head->tag_msb = (buf[len] >> 7) & 0x01;
+ tag_size = (buf[len] >> 4) & 0x07;
+ head->type = (buf[len] >> 0) & 0x0f;
+ len++;
+
+ /*
+ * TODO: Confirm the correct relative ordering of the next three
+ * fields.
+ */
+ if (head->type == PROPERTY_STRUCT) {
+ rc = upkg_decode_index(&index, buf+len, n-len);
+ if (rc == 0)
+ return 0;
+ if (!(head->struct_name = upkg_get_name(upkg, index)))
+ return 0;
+ len += rc;
+ }
+
+ rc = decode_tag_size(&head->size, tag_size, buf+len, n-len);
+ if (head->size == 0)
+ return 0;
+ len += rc;
+
+ head->array_idx = 0;
+ if (head->tag_msb && head->type != PROPERTY_BOOLEAN) {
+ rc = decode_array_index(&head->array_idx, buf+len, n-len);
+ if (rc == 0)
+ return 0;
+ len += rc;
+ }
+
+ return len;
+}
+
+static int decode_object_property(UObject *uo, GValue *val, unsigned long len)
+{
+ struct u_object_priv *priv = U_OBJECT_GET_PRIV(uo);
+ GObject *obj = NULL;
+ long index;
+ int rc;
+
+ rc = upkg_decode_index(&index, priv->buf+len, priv->nbuf-len);
+ if (rc == 0 || index == 0)
+ return -1;
+
+ if (index < 0) {
+ fprintf(stderr, "Imports not supported yet.\n");
+ } else {
+ obj = u_object_new_from_package(uo->pkg, index-1);
+ }
+
+ g_value_init(val, U_TYPE_OBJECT);
+ g_value_take_object(val, obj);
+ return 0;
+}
+
+static unsigned long deserialize_property(UObject *uo, struct prop_head *head)
+{
+ struct u_object_priv *priv = U_OBJECT_GET_PRIV(uo);
+ unsigned long rc, len = 0;
+ GValue val = {0};
+
+ rc = decode_prop_header(uo->pkg, head, priv->buf, priv->nbuf);
+ if (rc == 0)